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]