package traefikoidc import ( "testing" "time" ) // ============================================================================= // TOKEN TYPE DETECTION BENCHMARKS // ============================================================================= func BenchmarkDetectTokenType(b *testing.B) { tr := &TraefikOidc{ clientID: "test-client-id", suppressDiagnosticLogs: true, tokenTypeCache: NewTestCache(), } // Create various JWT test cases jwtWithNonce := &JWT{ Header: map[string]interface{}{"alg": "RS256"}, Claims: map[string]interface{}{ "nonce": "test-nonce", "aud": "test-client-id", "exp": time.Now().Add(1 * time.Hour).Unix(), }, } jwtWithScope := &JWT{ Header: map[string]interface{}{"alg": "RS256"}, Claims: map[string]interface{}{ "scope": "openid profile email", "aud": "some-api", "exp": time.Now().Add(1 * time.Hour).Unix(), }, } jwtComplexDetection := &JWT{ Header: map[string]interface{}{"alg": "RS256", "typ": "JWT"}, Claims: map[string]interface{}{ "aud": []interface{}{"test-client-id", "another-aud"}, "exp": time.Now().Add(1 * time.Hour).Unix(), "sub": "user123", "token_type": "Bearer", "custom_claim": "value", }, } testCases := []struct { name string jwt *JWT token string }{ {"WithNonce", jwtWithNonce, "token-with-nonce-for-benchmark-testing-12345678901234567890"}, {"WithScope", jwtWithScope, "token-with-scope-for-benchmark-testing-12345678901234567890"}, {"ComplexDetection", jwtComplexDetection, "token-complex-for-benchmark-testing-12345678901234567890"}, } for _, tc := range testCases { b.Run(tc.name+"_FirstCall", func(b *testing.B) { // Benchmark first call (uncached) for i := 0; i < b.N; i++ { // Clear cache before each iteration tr.tokenTypeCache.Clear() _ = tr.detectTokenType(tc.jwt, tc.token) } }) b.Run(tc.name+"_Cached", func(b *testing.B) { // Prime the cache _ = tr.detectTokenType(tc.jwt, tc.token) // Benchmark cached calls b.ResetTimer() for i := 0; i < b.N; i++ { _ = tr.detectTokenType(tc.jwt, tc.token) } }) } } // BenchmarkOldDetectionLogic provides comparison with the old implementation logic func BenchmarkOldDetectionLogic(b *testing.B) { clientID := "test-client-id" jwt := &JWT{ Header: map[string]interface{}{"alg": "RS256", "typ": "JWT"}, Claims: map[string]interface{}{ "aud": []interface{}{"test-client-id", "another-aud"}, "exp": time.Now().Add(1 * time.Hour).Unix(), "sub": "user123", "token_type": "Bearer", "custom_claim": "value", }, } b.Run("OldLogic", func(b *testing.B) { for i := 0; i < b.N; i++ { // Simulate the old detection logic (all 6 sequential checks) isIDToken := false isAccessToken := false // Step 1: Check typ header if typ, ok := jwt.Header["typ"].(string); ok { if typ == "at+jwt" { isAccessToken = true } } // Step 2: Check token_use claim if !isAccessToken && !isIDToken { if tokenUse, ok := jwt.Claims["token_use"].(string); ok { if tokenUse == "access" { isAccessToken = true } else if tokenUse == "id" { isIDToken = true } } } // Step 3: Check token_type claim if !isAccessToken && !isIDToken { if tokenType, ok := jwt.Claims["token_type"].(string); ok { if tokenType == "access_token" || tokenType == "Bearer" { isAccessToken = true } else if tokenType == "id_token" { isIDToken = true } } } // Step 4: Check scope claim if !isAccessToken && !isIDToken { if scope, ok := jwt.Claims["scope"]; ok { if _, ok := scope.(string); ok { isAccessToken = true } } } // Step 5: Check nonce claim if !isAccessToken && !isIDToken { if nonce, ok := jwt.Claims["nonce"]; ok { if _, ok := nonce.(string); ok { isIDToken = true } } } // Step 6: Check audience if !isAccessToken && !isIDToken { if aud, ok := jwt.Claims["aud"]; ok { if audStr, ok := aud.(string); ok && audStr == clientID { isIDToken = true } if audArr, ok := aud.([]interface{}); ok { for _, v := range audArr { if str, ok := v.(string); ok && str == clientID { if len(audArr) == 1 { isIDToken = true } break } } } } } // Step 7: Default to access token if !isIDToken { isAccessToken = true } _ = isAccessToken } }) }