Alnyli07 commented on code in PR #13165:
URL: https://github.com/apache/apisix/pull/13165#discussion_r3044791664


##########
apisix/plugins/dpop.lua:
##########
@@ -0,0 +1,1384 @@
+local core = require("apisix.core")
+local cjson = require("cjson.safe")
+local resty_sha256 = require("resty.sha256")
+local http = require("resty.http")
+local openssl_pkey = require("resty.openssl.pkey")
+local lrucache = require("resty.lrucache")
+local ngx = ngx
+
+local plugin_name = "dpop"
+
+-- Module-level local JTI cache — fallback when ngx.shared.dpop_jti_cache
+-- is not configured. Per-worker only; ensures fail-closed per RFC 9449 §11.1.
+local _jti_local_cache = {}
+local _jti_local_count = 0
+
+local function jti_local_cleanup()
+    local now = ngx.time()
+    local new_count = 0
+    for k, expiry in pairs(_jti_local_cache) do
+        if expiry <= now then
+            _jti_local_cache[k] = nil
+        else
+            new_count = new_count + 1
+        end
+    end
+    _jti_local_count = new_count
+end
+
+-- PKey LRU cache: JWK JSON → openssl pkey object
+-- 128 entries is generous — typical deployment has 1-3 signing keys
+local _pkey_cache, pkey_cache_err = lrucache.new(128)
+if not _pkey_cache then
+    error("failed to create pkey LRU cache: " .. (pkey_cache_err or "unknown"))
+end
+
+-- Module-level JWKS caches
+local _jwks_cache = {}           -- jwks_uri -> { keys_by_kid = {kid -> 
jwk_table}, fetched_at }
+local _discovery_cache = {}      -- discovery_url -> { jwks_uri, fetched_at }
+local _jwks_last_refetch = 0     -- rate limit: max 1 refetch per 60s
+
+-- Introspection cache: module-level local fallback when 
ngx.shared.dpop_intro_cache
+-- is not configured. Per-worker only; shared dict preferred for cross-worker 
consistency.
+local _introspection_cache = {}
+local _introspection_cache_count = 0
+
+-- Infinispan digest auth nonce cache (per-worker)
+local _ispn_digest_cache = {}  -- endpoint -> { nonce, realm, qop, nc }
+
+-- HTTP Digest Auth helper: parse WWW-Authenticate header and compute 
Authorization
+local function ispn_digest_auth(www_auth, method, uri, username, password)
+    if not www_auth then return nil end
+    local realm = www_auth:match('realm="([^"]+)"')
+    local nonce = www_auth:match('nonce="([^"]+)"')
+    local qop   = www_auth:match('qop="([^"]*)"') or www_auth:match('qop=([^,% 
]+)')
+    if not realm or not nonce then return nil end
+    local nc = "00000001"
+    local cnonce = ngx.md5(tostring(ngx.now()) .. tostring(math.random(1, 
999999)))
+    local ha1 = ngx.md5(username .. ":" .. realm .. ":" .. password)
+    local ha2 = ngx.md5(method .. ":" .. uri)
+    local response
+    if qop and qop:find("auth") then
+        response = ngx.md5(ha1 .. ":" .. nonce .. ":" .. nc
+            .. ":" .. cnonce .. ":" .. "auth" .. ":" .. ha2)
+    else
+        response = ngx.md5(ha1 .. ":" .. nonce .. ":" .. ha2)
+    end
+    return 'Digest username="' .. username
+        .. '", realm="' .. realm
+        .. '", nonce="' .. nonce
+        .. '", uri="' .. uri
+        .. '", qop=auth, nc=' .. nc
+        .. ', cnonce="' .. cnonce
+        .. '", response="' .. response .. '"',
+        nonce, realm, qop
+end
+
+local schema = {
+    type = "object",
+    properties = {
+        allowed_algs = {
+            type = "array",
+            items = {
+                type = "string",
+                enum = {
+                    "ES256", "ES384", "ES512",
+                    "RS256", "RS384", "RS512",
+                    "PS256", "PS384", "PS512",
+                },

Review Comment:
   
   Thanks for flagging this.
   
   Our primary test environment uses Keycloak which defaults to ES256 for DPoP  
                                                                    
   proofs, and RS256/384/512 for access token signing — so those were the       
                                                                    
   algorithms we had full E2E coverage for. The schema was populated from the   
                                                                    
   full RFC 9449 recommended algorithm list for completeness, but the           
                                                                    
   verification implementation didn't keep pace with the schema. That's on us.  
                                                                    
                                                                                
                                                                     
   We'll add ES384, ES512, PS256, PS384, and PS512 support — 
`resty.openssl.pkey`                                                            
       
   already handles these, it's mainly a matter of mapping the correct hash      
                                                                    
   algorithm and padding parameters.                                            
                                                                    
                                                                                
                                                                     
   While we're at it — are there any other algorithms you'd like to see         
                                                                    
   supported, or is the current RFC 9449 set (EC + RSA + RSA-PSS families)      
                                                                    
   sufficient?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to