mirror of
https://github.com/lukaszraczylo/traefikoidc.git
synced 2026-11-04 07:53:59 +00:00
fix(security): scope introspection cache keys to the middleware instance
The introspection cache used the raw token as key in a shared cache. Two instances with different providers or clients shared results. Keys now use the same instance prefix as the verified-token cache.
This commit is contained in:
@@ -309,6 +309,15 @@ func (tc *TokenCache) SetNamespace(ns string) {
|
|||||||
tc.ns.Store(ns)
|
tc.ns.Store(ns)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Namespace returns the scope set by SetNamespace, or "" when none is set.
|
||||||
|
func (tc *TokenCache) Namespace() string {
|
||||||
|
if tc == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
ns, _ := tc.ns.Load().(string)
|
||||||
|
return ns
|
||||||
|
}
|
||||||
|
|
||||||
func (tc *TokenCache) key(token string) string {
|
func (tc *TokenCache) key(token string) string {
|
||||||
if ns, _ := tc.ns.Load().(string); ns != "" {
|
if ns, _ := tc.ns.Load().(string); ns != "" {
|
||||||
return "t-" + ns + "|" + token
|
return "t-" + ns + "|" + token
|
||||||
|
|||||||
@@ -54,3 +54,16 @@ func TestTokenCacheEmptyNamespaceKeepsLegacyKey(t *testing.T) {
|
|||||||
t.Fatal("namespace-less caches must keep sharing the legacy key")
|
t.Fatal("namespace-less caches must keep sharing the legacy key")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIntrospectionKeyScopedPerInstance(t *testing.T) {
|
||||||
|
a := &TraefikOidc{tokenCache: &TokenCache{}}
|
||||||
|
b := &TraefikOidc{tokenCache: &TokenCache{}}
|
||||||
|
a.tokenCache.SetNamespace("p|app-a|app-a")
|
||||||
|
b.tokenCache.SetNamespace("p|app-b|app-b")
|
||||||
|
if a.introspectionKey("tok") == b.introspectionKey("tok") {
|
||||||
|
t.Fatal("different instances share an introspection cache key")
|
||||||
|
}
|
||||||
|
if got := (&TraefikOidc{}).introspectionKey("tok"); got != "tok" {
|
||||||
|
t.Fatalf("namespace-less key = %q, want raw token", got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+11
-2
@@ -53,7 +53,7 @@ type IntrospectionResponse struct {
|
|||||||
func (t *TraefikOidc) introspectToken(token string) (*IntrospectionResponse, error) {
|
func (t *TraefikOidc) introspectToken(token string) (*IntrospectionResponse, error) {
|
||||||
// Check cache first
|
// Check cache first
|
||||||
if t.introspectionCache != nil {
|
if t.introspectionCache != nil {
|
||||||
if cached, found := t.introspectionCache.Get(token); found {
|
if cached, found := t.introspectionCache.Get(t.introspectionKey(token)); found {
|
||||||
if response, ok := cached.(*IntrospectionResponse); ok {
|
if response, ok := cached.(*IntrospectionResponse); ok {
|
||||||
t.logger.Debugf("Using cached introspection result for token")
|
t.logger.Debugf("Using cached introspection result for token")
|
||||||
return response, nil
|
return response, nil
|
||||||
@@ -173,7 +173,7 @@ func (t *TraefikOidc) introspectToken(token string) (*IntrospectionResponse, err
|
|||||||
cacheDuration = untilExp
|
cacheDuration = untilExp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.introspectionCache.Set(token, &introspectionResp, cacheDuration)
|
t.introspectionCache.Set(t.introspectionKey(token), &introspectionResp, cacheDuration)
|
||||||
t.logger.Debugf("Cached introspection result for %v", cacheDuration)
|
t.logger.Debugf("Cached introspection result for %v", cacheDuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,3 +280,12 @@ func (t *TraefikOidc) validateOpaqueToken(token string) error {
|
|||||||
t.logger.Debugf("Opaque token validation successful via introspection")
|
t.logger.Debugf("Opaque token validation successful via introspection")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// introspectionKey scopes an introspection verdict to this instance's
|
||||||
|
// provider, client and audience, like the verified-token cache.
|
||||||
|
func (t *TraefikOidc) introspectionKey(token string) string {
|
||||||
|
if ns := t.tokenCache.Namespace(); ns != "" {
|
||||||
|
return ns + "|" + token
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|||||||
+1
-1
@@ -812,7 +812,7 @@ func (t *TraefikOidc) RevokeToken(token string) {
|
|||||||
// from the introspection cache after revocation. Next request
|
// from the introspection cache after revocation. Next request
|
||||||
// re-introspects and sees active=false.
|
// re-introspects and sees active=false.
|
||||||
if t.introspectionCache != nil {
|
if t.introspectionCache != nil {
|
||||||
t.introspectionCache.Delete(token)
|
t.introspectionCache.Delete(t.introspectionKey(token))
|
||||||
}
|
}
|
||||||
|
|
||||||
d := blacklistDuration(token)
|
d := blacklistDuration(token)
|
||||||
|
|||||||
Reference in New Issue
Block a user