From 03ec1d3bf862f78761f12865881ad0921553d299 Mon Sep 17 00:00:00 2001 From: Dawid Trzebiatowski Date: Wed, 21 Aug 2024 14:07:20 +0200 Subject: [PATCH 1/2] Enable caching of negative introspection responses --- lib/resty/openidc.lua | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/lib/resty/openidc.lua b/lib/resty/openidc.lua index 3ac7f20..21601df 100644 --- a/lib/resty/openidc.lua +++ b/lib/resty/openidc.lua @@ -1780,6 +1780,11 @@ function openidc.introspect(opts) if v then json = cjson.decode(v) + + if not json or not json.active then + err = "invalid cached token" + end + return json, err end @@ -1810,20 +1815,15 @@ function openidc.introspect(opts) end json, err = openidc.call_token_endpoint(opts, introspection_endpoint, body, opts.introspection_endpoint_auth_method, "introspection") - if not json then return json, err end - if not json.active then - err = "invalid token" - return json, err - end - -- cache the results local introspection_cache_ignore = opts.introspection_cache_ignore or false local expiry_claim = opts.introspection_expiry_claim or "exp" + if not introspection_cache_ignore and json[expiry_claim] then local introspection_interval = opts.introspection_interval or 0 local ttl = json[expiry_claim] @@ -1839,6 +1839,10 @@ function openidc.introspect(opts) set_cached_introspection(opts, access_token, cjson.encode(json), ttl) end + if not json.active then + err = "invalid token" + end + return json, err end From eb68d902d221537e605dbef55f8488e9d9fd952a Mon Sep 17 00:00:00 2001 From: Dawid Trzebiatowski Date: Tue, 17 Sep 2024 12:24:35 +0200 Subject: [PATCH 2/2] Adding option to disable negative cache --- README.md | 13 +++++++++++++ lib/resty/openidc.lua | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/README.md b/README.md index cc066bb..958bab7 100644 --- a/README.md +++ b/README.md @@ -384,6 +384,19 @@ from the cache. In order to avoid cache confusion it is recommended to set `opts.cache_segment` to unique strings for each set of related locations. +## Caching of negative Introspection responses + +By default `introspection` cache will not store negative responses. +This means that bad actor can potentialy try to exhaust introspection +endpoint by flooding service with a lot of calls with inproper token. +To prevent this situation `opts.introspection_enable_negative_cache` +can be set to `true`. This will enable `introspection` cache to store +negative responses for time defined in `exp` field. +Caching negative introspection responses will offload traffic from +introspection endpoint but also will expose NGINX for resource exhaustion +attacks as storing negative introspection responses will use extra +cache storage. + ## Revoke tokens The `revoke_tokens(opts, session)` function revokes the current refresh and access token. In contrast to a full logout, the session cookie will not be destroyed and the endsession endpoint will not be called. The function returns `true` if both tokens were revoked successfully. This function might be helpful in scenarios where you want to destroy/remove a session from the server side. diff --git a/lib/resty/openidc.lua b/lib/resty/openidc.lua index 21601df..ea2b502 100644 --- a/lib/resty/openidc.lua +++ b/lib/resty/openidc.lua @@ -1819,6 +1819,13 @@ function openidc.introspect(opts) return json, err end + -- check if negative cache should be in use + local introspection_enable_negative_cache = opts.introspection_enable_negative_cache or false + if not json.active and not introspection_enable_negative_cache then + err = "invalid token" + return json, err + end + -- cache the results local introspection_cache_ignore = opts.introspection_cache_ignore or false local expiry_claim = opts.introspection_expiry_claim or "exp"