Files
traefikoidc/review_r128_test.go
T
lukaszraczylo 6d96e8869b test: add R-round regression and security suite
- fail-on-old regression tests for every shipped fix (R-rounds)
- fuzz targets (parseJWT, bearer), concurrency-stress, shuffle-flake guards
- coverage-closing contract tests (health-check backend, TLS-posture reuse)
- r154 ID-token fixture built from parts to avoid false-positive secret scan
2026-08-14 16:22:39 +01:00

62 lines
2.5 KiB
Go

package traefikoidc
import (
"testing"
"time"
"github.com/alicebob/miniredis/v2"
"github.com/lukaszraczylo/traefikoidc/internal/cache/backends"
"github.com/stretchr/testify/require"
)
// TestBlacklist_TokenCacheNamespaceIsolation_Redis guards the R128 fix:
// the blacklist cache shared CacheTypeToken with the token cache, and both
// compose their Redis key from c.config.Type (prefixKey). In shared
// backend (Redis) mode the two caches therefore used IDENTICAL keys
// (token:<raw>) for the same raw token, so a cached verified token's
// claims made the blacklist report it as blacklisted, and a token-cache
// write clobbered a real blacklist marker — defeating the revoke
// feature. The blacklist must live in its own namespace.
func TestBlacklist_TokenCacheNamespaceIsolation_Redis(t *testing.T) {
t.Parallel()
mr, err := miniredis.Run()
require.NoError(t, err)
defer mr.Close()
redisConfig := backends.DefaultRedisConfig(mr.Addr())
redisConfig.RedisPrefix = "iso:"
backend, err := backends.NewRedisBackend(redisConfig)
require.NoError(t, err)
defer backend.Close()
blacklist := NewUniversalCacheWithBackend(newBlacklistCacheConfig(nil), backend)
t.Cleanup(func() { _ = blacklist.Close() })
tokenCache := NewUniversalCacheWithBackend(UniversalCacheConfig{
Type: CacheTypeToken,
MaxSize: 1000,
DefaultTTL: time.Hour,
}, backend)
t.Cleanup(func() { _ = tokenCache.Close() })
// Direction A: a valid token with its claims cached must NOT be seen as
// blacklisted. OLD: blacklist and token share "token:", so Get returns
// the cached claims (non-nil) and reports the valid token blacklisted.
tok := "valid.signed.token"
require.NoError(t, tokenCache.Set(tok, []string{"cid"}, time.Hour))
if _, found := blacklist.Get(tok); found {
t.Fatal("valid token whose claims are cached must not be reported blacklisted")
}
// Direction B: a real blacklist marker must survive a token-cache write of
// the same raw token. OLD: the token-cache write clobbers the shared key,
// turning the marker into claims (not a bool) or dropping it.
revoked := "revoked.signed.token"
require.NoError(t, blacklist.Set(revoked, true, time.Hour))
require.NoError(t, tokenCache.Set(revoked, []string{"cid"}, time.Hour))
v, found := blacklist.Get(revoked)
require.True(t, found, "blacklist entry must survive a same-token cache write")
isBool, ok := v.(bool)
require.True(t, ok, "blacklist value must remain a bool, got %T", v)
require.True(t, isBool, "revoked token must remain blacklisted")
}