Skip to content

Conversation

@WhammyLeaf
Copy link

@WhammyLeaf WhammyLeaf commented Nov 24, 2025

This PR adds support a couple of new config variables, which are useful to have available in an enterprise setting with a more complex azure setup. They are:

  • Scopes, which defaults to the currently hardcoded values when not set
  • TokenValidatonFuncs, which is a list custom validation functions to apply to the raw accces
  • SkipIssuerCheck, SkipExpiryCheck, SkipAudienceCheck, which are booleans that, when true, bypass the corresponding checks on the access token

I still have not added any documentation, but I can do that once I get the go-ahead.

Summary by CodeRabbit

  • New Features

    • Make OAuth2/OIDC scopes configurable via builder and environment with sensible defaults; propagate to handlers and discovery metadata.
    • Add flags to skip issuer, audience, and expiry checks via builder and environment.
    • Allow registering custom token validation callbacks.
  • Bug Fixes

    • Token validation and discovery now consistently respect configured scopes and skip flags across flows.
  • Documentation

    • Added guidance for configuring scopes and skip flags via environment and builder.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 24, 2025

Walkthrough

Adds configurable OIDC/OAuth2 options: Scopes, three Skip* boolean flags, and TokenValidators; exposes builder methods and FromEnv parsing, wires flags and validators into provider/validator initialization and OAuth2/discovery metadata; adds parseBoolEnv helper and necessary imports.

Changes

Cohort / File(s) Summary
Configuration layer
config.go
Added Scopes []string, SkipIssuerCheck bool, SkipAudienceCheck bool, SkipExpiryCheck bool, and TokenValidators []func(claims jwt.MapClaims) error to Config; added builder methods WithScopes, WithSkipIssuerCheck, WithSkipAudienceCheck, WithSkipExpiryCheck; added parseBoolEnv(key string, defaultVal bool) bool; wired env vars OIDC_SCOPES, OIDC_SKIP_AUDIENCE_CHECK, OIDC_SKIP_ISSUER_CHECK, OIDC_SKIP_EXPIRY_CHECK into FromEnv; updated imports (strconv, strings, github.com/golang-jwt/jwt/v5).
Provider / Validator
provider/provider.go
Added SkipIssuerCheck, SkipAudienceCheck, SkipExpiryCheck, and TokenValidators fields to provider Config and to OIDCValidator; initializer now applies cfg.Skip* flags to the verifier and assigns TokenValidators; OIDC validation path iterates and executes TokenValidators callbacks, returning errors if any fail; HMAC path adjusted (audience validation removed).
OAuth2 handler
handlers.go
Added Scopes []string to oauth.OAuth2Config; NewOAuth2Handler and NewOAuth2ConfigFromConfig use cfg.Scopes with fallback to ["openid","profile","email"] instead of hard-coded scopes.
Discovery / Metadata
metadata.go
Discovery and protected resource metadata endpoints now report scopes_supported from h.config.Scopes (replaces previous hard-coded scope list).

Sequence Diagram(s)

sequenceDiagram
    participant App as App / ConfigBuilder
    participant Env as FromEnv
    participant Prov as Provider.Init
    participant Val as OIDCValidator
    participant TF as TokenValidators

    App->>Env: FromEnv / WithScopes / WithSkipX / WithTokenValidators
    Env-->>App: Config{Scopes, Skip* flags, TokenValidators}
    App->>Prov: createProvider(cfg)
    Prov->>Val: init validator (apply Skip* flags, assign TokenValidators)
    Val->>Val: perform core checks (issuer/audience/expiry) — some may be skipped
    alt core checks pass or are skipped
        Val->>TF: for each -> TokenValidator(claims)
        TF-->>Val: error / nil
    end
    Val-->>Prov: validation result
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Focus areas:
    • Env parsing semantics for OIDC_SCOPES and boolean flags (parseBoolEnv) and defaults.
    • Propagation and nil-safety of TokenValidators through Config → Provider → OIDCValidator.
    • Correct mapping of Skip* flags into verifier configuration and ensuring checks are skipped safely.
    • OIDC vs HMAC validation divergence (audience handling) and error propagation from validators.

Possibly related PRs

Poem

🐰 I hop through fields and envs with cheer,
Scopes in a row, and flags to steer,
Validators peek at claims so sly,
Skipping what’s set, or catching a lie,
I nibble bugs and bound on high. 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'Add more config variables' is vague and generic, using non-descriptive language that doesn't convey the specific nature of the changes. Consider a more specific title like 'Add token validation and OIDC check configuration options' to better describe the core functionality being introduced.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fd401d6 and 8351f51.

📒 Files selected for processing (4)
  • config.go (7 hunks)
  • handlers.go (4 hunks)
  • metadata.go (3 hunks)
  • provider/provider.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • config.go
🧰 Additional context used
📓 Path-based instructions (1)
**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Never log raw OAuth tokens; only log SHA-256 hash of token formatted as fmt.Sprintf("%x", sha256.Sum256([]byte(token)))[:16]

Files:

  • handlers.go
  • metadata.go
  • provider/provider.go
🧠 Learnings (3)
📚 Learning: 2025-12-13T17:03:53.298Z
Learnt from: CR
Repo: tuannvm/oauth-mcp-proxy PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:03:53.298Z
Learning: Providers implement TokenValidator interface and all token validation happens in provider/provider.go

Applied to files:

  • metadata.go
  • provider/provider.go
📚 Learning: 2025-12-13T17:03:53.298Z
Learnt from: CR
Repo: tuannvm/oauth-mcp-proxy PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:03:53.298Z
Learning: Audience (aud) claim must be explicitly validated in both HMAC and OIDC validators

Applied to files:

  • provider/provider.go
📚 Learning: 2025-12-13T17:03:53.298Z
Learnt from: CR
Repo: tuannvm/oauth-mcp-proxy PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:03:53.298Z
Learning: Applies to **/*.go : Never log raw OAuth tokens; only log SHA-256 hash of token formatted as fmt.Sprintf("%x", sha256.Sum256([]byte(token)))[:16]

Applied to files:

  • provider/provider.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: code-review
🔇 Additional comments (4)
metadata.go (1)

141-141: Dynamic scopes configuration looks good.

The metadata endpoints now correctly use h.config.Scopes instead of hardcoded values. The default scopes are handled in NewOAuth2ConfigFromConfig (handlers.go lines 181-184), which ensures non-empty scopes.

Also applies to: 246-246, 286-286

handlers.go (2)

49-49: Clean integration of dynamic scopes.

The Scopes field is properly added to OAuth2Config and correctly wired into the oauth2.Config initialization.

Also applies to: 100-100


181-195: Proper defaults for scopes configuration.

The default scopes logic correctly falls back to []string{"openid", "profile", "email"} when cfg.Scopes is empty. This ensures all downstream code (metadata endpoints, OAuth2 flows) always has valid scopes.

provider/provider.go (1)

211-213: Redundant audience validation when SkipAudienceCheck is false.

The code performs audience validation in two places:

  1. Line 211: SkipClientIDCheck: cfg.SkipAudienceCheck tells go-oidc's Verify() to validate audience (when false)
  2. Lines 221-223: Manually adds validateAudience to TokenValidators when !cfg.SkipAudienceCheck

This means when SkipAudienceCheck is false (the default), audience is validated twice - once by go-oidc during Verify() and once again in your custom validators loop.

Based on learnings, audience must be explicitly validated. Since go-oidc already handles this via SkipClientIDCheck, remove the manual addition to avoid redundancy:

 	v.logger.Info("OAuth: OIDC validator initialized with audience validation: %s", cfg.Audience)
 
 	v.provider = provider
 	v.verifier = verifier
 	v.TokenValidators = cfg.TokenValidators
-	if !cfg.SkipAudienceCheck {
-		v.TokenValidators = append(v.TokenValidators, v.validateAudience)
-	}
 	return nil

Note: Removing this is safe because go-oidc's Verify() already validates audience when SkipClientIDCheck is false. The validateAudience method can remain for potential future use or testing purposes.

Also applies to: 221-223

⛔ Skipped due to learnings
Learnt from: CR
Repo: tuannvm/oauth-mcp-proxy PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-13T17:03:53.298Z
Learning: Audience (aud) claim must be explicitly validated in both HMAC and OIDC validators

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 14f9009 and 65f35e5.

📒 Files selected for processing (2)
  • config.go (4 hunks)
  • provider/provider.go (2 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
config.go (2)
provider/provider.go (1)
  • Logger (24-29)
logger.go (1)
  • Logger (22-27)
🔇 Additional comments (4)
provider/provider.go (2)

33-40: LGTM with security caveat.

The new configuration fields are correctly defined. However, these flags bypass critical security validations.

Ensure these flags are:

  1. Documented with clear security warnings
  2. Used only in development/testing environments
  3. Never enabled in production

Consider adding runtime warnings when these checks are disabled.


209-211: LGTM!

The validator configuration correctly maps the new config flags to the OIDC verifier settings, replacing the previously hardcoded false values.

config.go (2)

34-38: LGTM!

The configuration fields are correctly defined with appropriate documentation.


318-320: Missing test coverage for security bypass flags.

Verification confirms no tests exist for the new skip flags. Critical test coverage gaps:

  • Environment variable parsing tests (OIDC_SKIP_AUDIENCE_CHECK, OIDC_SKIP_ISSUER_CHECK, OIDC_SKIP_EXPIRY_CHECK)
  • Validation that flags default to false (secure-by-default)
  • Independent flag behavior verification
  • Combined flag scenarios

Add tests covering all above cases before merging, particularly to ensure security defaults are maintained.

@WhammyLeaf WhammyLeaf force-pushed the add-more-custom-config-vars branch from bd04072 to 8d50963 Compare November 24, 2025 14:44
@WhammyLeaf WhammyLeaf changed the title Add more custom config vars Support skipping OIDC validation checks Nov 24, 2025
@WhammyLeaf WhammyLeaf force-pushed the add-more-custom-config-vars branch 2 times, most recently from 31b7df3 to 5fbe515 Compare November 24, 2025 15:23
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
config.go (2)

36-39: LGTM: Skip validation flags added correctly.

The three boolean fields are well-named and properly integrated into the Config struct. They default to false (validation enabled), which is the safe default.

Optional: Consider adding doc comments to each field explaining the security implications of skipping these validation checks, especially for users who may not fully understand OIDC security requirements.


327-338: LGTM: Robust boolean parsing with safe defaults.

The parseBoolEnv helper correctly uses strconv.ParseBool to handle standard boolean representations and safely falls back to the default value on parse errors or empty values. This fail-safe approach ensures validation remains enabled by default.

Optional: Consider logging parse errors to aid debugging when users provide invalid boolean values (e.g., "yes" instead of "true"). However, the current silent fallback is safe and acceptable.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd04072 and 5fbe515.

📒 Files selected for processing (2)
  • config.go (5 hunks)
  • provider/provider.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • provider/provider.go
🧰 Additional context used
🧬 Code graph analysis (1)
config.go (2)
provider/provider.go (1)
  • Logger (24-29)
logger.go (1)
  • Logger (22-27)
🔇 Additional comments (4)
config.go (4)

5-5: LGTM: Import added for boolean parsing.

The strconv import is necessary for the parseBoolEnv helper and is correctly placed.


127-135: LGTM: Skip flags correctly propagated to provider config.

The mapping from Config to provider.Config is correct, including the previously identified copy-paste error on line 135 which has been properly fixed (now correctly maps SkipExpiryCheck to cfg.SkipExpiryCheck).


235-251: LGTM: Builder methods follow the pattern correctly.

The three new builder methods are properly implemented following the fluent builder pattern. Documentation comments are correct and consistent (previous typos have been fixed).


319-321: LGTM: Environment variable parsing implemented correctly.

The skip flags are properly initialized from environment variables using the parseBoolEnv helper, which correctly handles boolean values. Safe defaults (false = validation enabled) are used, and the environment variable names follow clear naming conventions.

@WhammyLeaf WhammyLeaf force-pushed the add-more-custom-config-vars branch from 5fbe515 to 4d5a1f7 Compare November 27, 2025 09:09
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
provider/provider.go (1)

264-267: Explicit audience validation runs even when SkipAudienceCheck is true.

When cfg.SkipAudienceCheck is set to true, the go-oidc library skips its audience check (via SkipClientIDCheck at line 211), but validateAudience() at line 265 still runs unconditionally. This makes the skip flag ineffective.

-	// Validate audience claim for security (explicit check)
-	if err := v.validateAudience(rawClaims); err != nil {
-		return nil, fmt.Errorf("audience validation failed: %w", err)
-	}
+	// Validate audience claim for security (explicit check) unless skipped
+	if !v.skipAudienceCheck {
+		if err := v.validateAudience(rawClaims); err != nil {
+			return nil, fmt.Errorf("audience validation failed: %w", err)
+		}
+	}

You'll need to store cfg.SkipAudienceCheck in OIDCValidator during initialization.

🧹 Nitpick comments (4)
metadata.go (1)

245-245: Inconsistent scopes in metadata endpoints.

HandleOIDCDiscovery now uses dynamic h.config.Scopes, but GetAuthorizationServerMetadata() (lines 285 and 317) still uses hardcoded []string{"openid", "profile", "email"}. This inconsistency could confuse clients depending on which metadata endpoint they query.

Consider updating GetAuthorizationServerMetadata() to also use h.config.Scopes for consistency:

 // In native mode (line 285):
-	"scopes_supported":                      []string{"openid", "profile", "email"},
+	"scopes_supported":                      h.config.Scopes,

 // In proxy mode (line 317):
-	"scopes_supported":                      []string{"openid", "profile", "email"},
+	"scopes_supported":                      h.config.Scopes,
config.go (2)

234-262: Consider adding builder method for TokenValidationFuncs.

For consistency with the fluent builder pattern, consider adding a WithTokenValidationFuncs method:

// WithTokenValidationFuncs sets custom token validation functions
func (b *ConfigBuilder) WithTokenValidationFuncs(funcs []func(claims jwt.MapClaims) error) *ConfigBuilder {
	b.config.TokenValidationFuncs = funcs
	return b
}

This allows users to configure custom validation functions via the builder API.


38-43: Add security warnings for skip flags.

Skipping issuer, audience, or expiry checks significantly weakens token security and should only be used in development/testing. Consider logging warnings in Validate() or during initialization when these flags are enabled:

// In Validate() or SetupOAuth():
if c.SkipIssuerCheck {
    logger.Warn("SECURITY: Issuer check disabled - not recommended for production")
}
if c.SkipAudienceCheck {
    logger.Warn("SECURITY: Audience check disabled - not recommended for production")
}
if c.SkipExpiryCheck {
    logger.Warn("SECURITY: Expiry check disabled - tokens may be accepted after expiration")
}
provider/provider.go (1)

66-82: HMACValidator doesn't respect skip flags.

The new skip flags (SkipIssuerCheck, SkipAudienceCheck, SkipExpiryCheck) and TokenValidatorFuncs are only implemented for OIDCValidator. HMACValidator still performs audience validation unconditionally (line 117) and expiry validation (line 112 via validateTokenClaims).

For API consistency, consider implementing these flags for HMACValidator as well, or document that these flags only apply to OIDC providers.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5fbe515 and 4d5a1f7.

📒 Files selected for processing (4)
  • config.go (7 hunks)
  • handlers.go (4 hunks)
  • metadata.go (1 hunks)
  • provider/provider.go (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
config.go (2)
provider/provider.go (1)
  • Logger (24-29)
logger.go (1)
  • Logger (22-27)
🔇 Additional comments (2)
handlers.go (1)

181-195: LGTM!

The scopes configuration with sensible defaults is well implemented. The fallback to ["openid", "profile", "email"] when no scopes are provided ensures backward compatibility.

provider/provider.go (1)

269-275: LGTM!

The custom token validation function execution is correctly implemented. Ranging over a nil slice is safe in Go, so no nil check is needed.

@WhammyLeaf WhammyLeaf force-pushed the add-more-custom-config-vars branch from 4d5a1f7 to 8beec21 Compare November 27, 2025 09:12
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
config.go (1)

321-321: Empty OIDC_SCOPES produces [""] instead of empty slice.

When OIDC_SCOPES is unset or empty, strings.Split("", " ") returns [""] (a slice with one empty string), not an empty slice. This bypasses the default scopes fallback in NewOAuth2ConfigFromConfig (which checks len(scopes) == 0).

Use strings.Fields which handles empty strings correctly:

-	scopes := strings.Split(getEnv("OIDC_SCOPES", ""), " ")
+	scopesEnv := getEnv("OIDC_SCOPES", "")
+	var scopes []string
+	if scopesEnv != "" {
+		scopes = strings.Fields(scopesEnv)
+	}

Alternatively, using strings.Fields directly works because it returns nil for empty/whitespace-only input:

-	scopes := strings.Split(getEnv("OIDC_SCOPES", ""), " ")
+	scopes := strings.Fields(getEnv("OIDC_SCOPES", ""))
🧹 Nitpick comments (1)
metadata.go (1)

271-322: Inconsistent scopes handling between discovery endpoints.

HandleOIDCDiscovery (line 245) now uses dynamic h.config.Scopes, while GetAuthorizationServerMetadata (lines 285 and 317) still uses hardcoded []string{"openid", "profile", "email"}.

This inconsistency could confuse clients querying different metadata endpoints. Consider using h.config.Scopes consistently across both methods.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4d5a1f7 and 8beec21.

📒 Files selected for processing (4)
  • config.go (7 hunks)
  • handlers.go (4 hunks)
  • metadata.go (1 hunks)
  • provider/provider.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • provider/provider.go
🧰 Additional context used
🧬 Code graph analysis (1)
config.go (2)
provider/provider.go (1)
  • Logger (24-29)
logger.go (1)
  • Logger (22-27)
🔇 Additional comments (8)
config.go (5)

3-10: LGTM on imports.

The new imports (strconv, strings, and jwt/v5) are correctly added to support the new boolean parsing, scope handling, and token validation functions.


24-44: LGTM on new configuration fields.

The new Scopes, Skip*Check, and TokenValidationFuncs fields are well-structured and provide the flexibility needed for customizable OIDC validation.


131-141: LGTM on provider config mapping.

The field mappings are now correct. The previously reported copy-paste error (where SkipExpiryCheck was incorrectly mapped to cfg.SkipAudienceCheck) has been fixed.


234-262: LGTM on builder methods.

The new fluent builder methods follow the established pattern and the documentation comments have been corrected.


339-351: LGTM on parseBoolEnv helper.

The implementation correctly uses strconv.ParseBool to handle standard boolean values (true, false, 1, 0, t, f, etc.) and provides sensible defaults for empty or invalid values.

handlers.go (3)

49-49: LGTM on new Scopes field.

The new Scopes field in OAuth2Config properly supports dynamic scope configuration.


96-101: LGTM on OAuth2 config initialization.

The scopes are correctly passed to the underlying oauth2.Config.


181-195: LGTM on scopes initialization with default fallback.

The fallback logic is correct: if no scopes are configured, default to ["openid", "profile", "email"]. This will work correctly once the strings.Split issue in config.go line 321 is fixed (empty env should yield an empty slice, not [""]).

@WhammyLeaf WhammyLeaf force-pushed the add-more-custom-config-vars branch 2 times, most recently from 8a7df45 to 4be258d Compare November 27, 2025 09:28
@WhammyLeaf WhammyLeaf changed the title Support skipping OIDC validation checks Add more config variables Nov 27, 2025
@WhammyLeaf
Copy link
Author

@tuannvm Could be nice if you could have a look at this 😄

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
provider/provider.go (1)

265-267: Explicit audience validation doesn't respect SkipAudienceCheck flag.

When SkipAudienceCheck is true (line 211 sets SkipClientIDCheck: cfg.SkipAudienceCheck), the OIDC verifier skips audience validation. However, the explicit validateAudience call on line 265 always runs, regardless of the flag. This creates inconsistent behavior where the audience check is only partially skipped.

Apply this diff to conditionally skip the explicit audience check:

 	if err := idToken.Claims(&rawClaims); err != nil {
 		return nil, fmt.Errorf("failed to extract raw claims: %w", err)
 	}
 
-	// Validate audience claim for security (explicit check)
-	if err := v.validateAudience(rawClaims); err != nil {
-		return nil, fmt.Errorf("audience validation failed: %w", err)
+	// Validate audience claim for security (explicit check) if not skipped
+	if v.audience != "" {
+		if err := v.validateAudience(rawClaims); err != nil {
+			return nil, fmt.Errorf("audience validation failed: %w", err)
+		}
 	}

Note: This assumes that when SkipAudienceCheck is true, the audience field should be set to empty string during initialization. If that's not the case, you'll need to store the skip flag in the validator struct or pass it through another mechanism.

🧹 Nitpick comments (2)
provider/provider.go (1)

269-276: Consider adding validation function index to error message.

The error message for failed validation functions could be more informative by including which function failed. This would help with debugging when multiple validation functions are registered.

 	// Run extra validation functions
-	for _, fn := range v.TokenValidatorFuncs {
+	for i, fn := range v.TokenValidatorFuncs {
 		err := fn(rawClaims)
 		if err != nil {
-			return nil, fmt.Errorf("validation function failed with error: %w", err)
+			return nil, fmt.Errorf("validation function %d failed: %w", i, err)
 		}
 	}
config.go (1)

132-141: Consider renaming TokenValidationFuncs for consistency.

There's a naming inconsistency between the two Config structs:

  • oauth.Config.TokenValidationFuncs (line 43 in this file)
  • provider.Config.TokenValidatorFuncs (line 41 in provider/provider.go)

While the mapping on line 140 correctly uses TokenValidatorFuncs, having different names for the same concept can cause confusion. Consider renaming one to match the other for consistency across the codebase.

Suggested approach: Rename TokenValidationFuncs to TokenValidatorFuncs in this file to match the provider package:

-	TokenValidationFuncs []func(claims jwt.MapClaims) error
+	TokenValidatorFuncs []func(claims jwt.MapClaims) error

Then update line 140:

-		TokenValidatorFuncs: cfg.TokenValidationFuncs,
+		TokenValidatorFuncs: cfg.TokenValidatorFuncs,
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8beec21 and bdae26e.

📒 Files selected for processing (4)
  • config.go (7 hunks)
  • handlers.go (4 hunks)
  • metadata.go (2 hunks)
  • provider/provider.go (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • handlers.go
  • metadata.go
🧰 Additional context used
🧬 Code graph analysis (1)
config.go (2)
provider/provider.go (1)
  • Logger (24-29)
logger.go (1)
  • Logger (22-27)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: code-review
🔇 Additional comments (7)
provider/provider.go (2)

59-63: LGTM!

The OIDCValidator struct properly reflects the new configuration fields. The addition of TokenValidatorFuncs and explicit logger field storage aligns well with the validation flow enhancements.


208-214: Based on the web search results, I can now provide the verification findings:

The skip flags are properly documented and work as documented in go-oidc v3.

The search confirmed:

  • SkipClientIDCheck — exists and skips audience validation; must be true if ClientID is empty
  • SkipExpiryCheck — exists and skips token expiry check (documented for special/testing cases)
  • SkipIssuerCheck — exists and skips issuer verification (with warnings to independently verify)

However, there is one potential edge case worth noting: The go-oidc documentation states that SkipClientIDCheck must be set to true if ClientID is empty, otherwise it should be false. Since the code maps cfg.Audience to the ClientID field, verify that your configuration validates this constraint—specifically, if cfg.Audience is empty, ensure cfg.SkipAudienceCheck is true, or the verifier will fail. Check that this validation exists in your config validation logic.


The skip flags work as expected and are secure when used appropriately. The mapping from cfg.SkipAudienceCheck to SkipClientIDCheck is consistent with go-oidc's design. Ensure your config validation enforces the constraint that when audience is empty, skip-audience-check must be true.

config.go (5)

3-10: LGTM!

The new imports (strconv, strings, jwt/v5) are all properly utilized: strconv for boolean parsing, strings for splitting scopes, and jwt for the MapClaims type in validation functions.


234-262: LGTM!

The new builder methods (WithScopes, WithSkipIssuerCheck, WithSkipAudienceCheck, WithSkipExpiryCheck) correctly follow the fluent API pattern and properly set the corresponding Config fields.


322-326: LGTM!

The scopes parsing correctly handles the empty environment variable case by initializing an empty slice and only splitting when the value is non-empty. This avoids the [""] issue that would bypass default scope fallback logic.


336-339: LGTM!

The FromEnv method correctly integrates the new configuration options. The use of parseBoolEnv with false as the default is appropriate for security-sensitive skip flags, ensuring checks are enabled by default.


345-356: LGTM!

The parseBoolEnv helper properly handles boolean environment variables using strconv.ParseBool, which supports standard formats (true/false, 1/0, t/f, etc.). The fallback to default values for empty or invalid inputs is appropriate.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SkipAudienceCheck flag currently has no effect; see inline.

Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Config skip flags still enforce audience validation and HMAC never runs token callbacks. go.mod also still targets go1.24.9 while go.dev lists go1.25.5.

@WhammyLeaf WhammyLeaf force-pushed the add-more-custom-config-vars branch from 8aee3d8 to 1d569b3 Compare December 16, 2025 10:47
Signed-off-by: Christian Troelsen <christian.troelsen@tryg.dk>

fix suggestions by coderabbit

Signed-off-by: Christian Troelsen <christian.troelsen@tryg.dk>

a few more changes
@WhammyLeaf WhammyLeaf force-pushed the add-more-custom-config-vars branch from 1d569b3 to 8351f51 Compare December 16, 2025 10:49
Copy link

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TokenValidators never run for HMAC tokens, and go.mod still targets older toolchain/dependencies (Go 1.24.9, go-oidc v3.16.0, mark3labs/mcp-go v0.41.1, MCP go-sdk v1.0.0, golang.org/x/oauth2 v0.32.0) even though proxy.golang.org reports 1.25.5 / 3.17.0 / 0.43.2 / 1.1.0 / 0.34.0; please plan upgrades.

@WhammyLeaf
Copy link
Author

@tuannvm Is this something you would be interested in merging into main?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant