feat: JWT cache implementation based on sieve algorithm (#4084)

Changes:

1. Refactoring and some cleanup of JWT handling code:
* Instead of caching AuthResult cache decoded claims (which signature was verified). Validating claims and determining role is done after cache lookup
* Cleaned up API so that usage of it is simplified: lookupJwtCache cache key >>= parseClaims configJwtAud time
* Handling of JwtCacheState initialization and updates of configuration is encapsulated in Auth.JwtCache module

2. Generic high performance (hopefully) scalable, dynamically resizeable cache implementation based on stm, stm-hamt and sieve algorithm. It also integrates with PostgREST measurements infrastructure providing usage stats (ie. hit ratio, evictions count)
This commit is contained in:
Michal Kleczek
2025-07-29 18:51:41 -05:00
committed by GitHub
parent ac155a9391
commit 77ff11de95
35 changed files with 664 additions and 203 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"aliased\""
jwt-secret = ""
jwt-secret-is-base64 = true
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"role\""
jwt-secret = ""
jwt-secret-is-base64 = true
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"role\""
jwt-secret = ""
jwt-secret-is-base64 = true
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"
+1 -1
View File
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"role\""
jwt-secret = ""
jwt-secret-is-base64 = false
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"roles\"[?(@ == \"role1\")]"
jwt-secret = ""
jwt-secret-is-base64 = false
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"roles\"[?(@ != \"role1\")]"
jwt-secret = ""
jwt-secret-is-base64 = false
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"roles\"[?(@ ^== \"role1\")]"
jwt-secret = ""
jwt-secret-is-base64 = false
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"roles\"[?(@ ==^ \"role1\")]"
jwt-secret = ""
jwt-secret-is-base64 = false
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"roles\"[?(@ *== \"role1\")]"
jwt-secret = ""
jwt-secret-is-base64 = false
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"
@@ -23,7 +23,7 @@ jwt-aud = "https://otherexample.org"
jwt-role-claim-key = ".\"other\".\"pre_config_role\""
jwt-secret = "ODERREALLYREALLYREALLYREALLYVERYSAFE"
jwt-secret-is-base64 = false
jwt-cache-max-lifetime = 7200
jwt-cache-max-entries = 86400
log-level = "info"
log-query = "main-query"
openapi-mode = "disabled"
@@ -23,7 +23,7 @@ jwt-aud = "https://example.org"
jwt-role-claim-key = ".\"a\".\"role\""
jwt-secret = "OVERRIDE=REALLY=REALLY=REALLY=REALLY=VERY=SAFE"
jwt-secret-is-base64 = false
jwt-cache-max-lifetime = 3600
jwt-cache-max-entries = 86400
log-level = "info"
log-query = "main-query"
openapi-mode = "ignore-privileges"
+1 -1
View File
@@ -23,7 +23,7 @@ jwt-aud = "https://postgrest.org"
jwt-role-claim-key = ".\"user\"[0].\"real-role\""
jwt-secret = "c2VjdXJpdHl0aHJvdWdob2JzY3VyaXR5aW5iYXNlNjQ="
jwt-secret-is-base64 = true
jwt-cache-max-lifetime = 86400
jwt-cache-max-entries = 86400
log-level = "info"
log-query = "main-query"
openapi-mode = "ignore-privileges"
+1 -1
View File
@@ -23,7 +23,7 @@ jwt-aud = ""
jwt-role-claim-key = ".\"role\""
jwt-secret = ""
jwt-secret-is-base64 = false
jwt-cache-max-lifetime = 0
jwt-cache-max-entries = 1000
log-level = "error"
log-query = "disabled"
openapi-mode = "follow-privileges"