Skip to content

Conversation

@dbnsky
Copy link

@dbnsky dbnsky commented Jan 15, 2026

Summary

This PR modifies the OIDC client initialization logic in oidc_handler.py to support Azure Active Directory's specific key discovery requirements. It implements logic to automatically normalize the Issuer URL and dynamically patch the JWKS URI with the client_id when Azure AD is detected.

Motivation
Often signs tokens with keys that are not present in the standard OpenID Connect jwks_uri. These specific keys are only exposed when querying the JWKS endpoint with an ?appid=<client_id> parameter. Without this parameter, the application fails to verify token signatures (NoSuitableSigningKeys). Additionally, strict string matching on the Issuer URL caused authentication failures if the configuration contained a trailing slash (Unknown Issuer).

Changes

  • Dynamic JWKS Patching: Implemented an interception of the OIDC metadata fetch. If the provider is detected as Microsoft/Azure, the client_id is automatically appended to the jwks_uri (e.g., .../keys?appid=xyz).

Benefits

  • Azure Single Tenant Application: Automatically handles the App-Specific key isolation common in Single Tenant Azure AD applications, ensuring the correct signing keys are found without manual configuration.
  • Backward Compatibility: The logic is conditional and does not affect non-Azure OIDC providers.

Issue #1014

Summary by CodeRabbit

  • New Features

    • Added explicit OIDC JWKS URI configuration option, enabling manual setup when auto-discovery is unavailable.
  • Improvements

    • Improved OIDC issuer URL normalization and validation.
    • Enhanced error handling with improved logging for OIDC configuration failures.

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

@coderabbitai
Copy link

coderabbitai bot commented Jan 15, 2026

Walkthrough

This PR adds support for manual OIDC JWKS URI configuration alongside existing auto-discovery. A new configuration parameter is introduced, and the OIDC handler is updated to conditionally use the provided JWKS URI or fall back to auto-discovery, with improved error handling and logging.

Changes

Cohort / File(s) Summary
OIDC Configuration
source/app/configuration.py
Added new OIDC_JWKS_URI configuration parameter with fallback to None, enabling manual specification of JWKS endpoint.
OIDC Handler Logic
source/app/iris_engine/access_control/oidc_handler.py
Replaced dynamic provider auto-discovery with conditional logic: uses manual JWKS URI if provided (with issuer normalization and explicit logging), otherwise falls back to auto-discovery. Enhanced error handling with try/except wrapper and refactored client registration to use separate variable assignments.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A JWKS URI straight from the config,
No more discovery detours to unlock!
Manual paths dance with auto-discovery,
Error handling logs our troubleshooting,
OIDC flows now have a choice sublime! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: adding OIDC JWKS URI configuration to support Azure single-tenant handling with explicit issuer and key discovery logic.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

🧹 Recent nitpick comments
source/app/iris_engine/access_control/oidc_handler.py (2)

28-34: Good normalization for issuer URL.

Stripping the trailing slash is the correct fix for "Unknown Issuer" string-matching failures. However, consider validating that issuer_url is not empty before proceeding, as an empty string would pass silently and cause confusing errors downstream.

💡 Optional validation
     # Normalize issuer URL - strip trailing slash to prevent "Unknown Issuer" errors
     issuer_url = app.config.get("OIDC_ISSUER_URL", "").rstrip('/')
+    if not issuer_url:
+        raise ValueError("OIDC_ISSUER_URL is required but not configured")
     client_id = app.config.get("OIDC_CLIENT_ID")
     client_secret = app.config.get("OIDC_CLIENT_SECRET")

37-52: Add validation for required OIDC endpoints when using explicit JWKS URI.

When using manual configuration with OIDC_JWKS_URI, the authorization_endpoint and token_endpoint default to None. According to RFC 8414, these endpoints are required for standard OIDC authorization-code flows. The oic library does not enforce this at the class level, so missing endpoints will cause failures at runtime during authentication.

Consider adding validation to ensure OIDC_AUTH_ENDPOINT and OIDC_TOKEN_ENDPOINT are configured when OIDC_JWKS_URI is set:

Suggested validation
         if jwks_uri:
             # Manual configuration with explicit JWKS URI
             app.logger.info(f"Using explicit JWKS URI: {jwks_uri}")
+
+            auth_endpoint = app.config.get("OIDC_AUTH_ENDPOINT")
+            token_endpoint = app.config.get("OIDC_TOKEN_ENDPOINT")
+            if not auth_endpoint or not token_endpoint:
+                raise ValueError(
+                    "OIDC_AUTH_ENDPOINT and OIDC_TOKEN_ENDPOINT are required when using explicit OIDC_JWKS_URI"
+                )

             op_info = ProviderConfigurationResponse(
                 issuer=issuer_url,
-                authorization_endpoint=app.config.get("OIDC_AUTH_ENDPOINT"),
-                token_endpoint=app.config.get("OIDC_TOKEN_ENDPOINT"),
+                authorization_endpoint=auth_endpoint,
+                token_endpoint=token_endpoint,
                 end_session_endpoint=app.config.get("OIDC_END_SESSION_ENDPOINT"),
                 jwks_uri=jwks_uri
             )

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a4bfeda and 051aa17.

📒 Files selected for processing (2)
  • source/app/configuration.py
  • source/app/iris_engine/access_control/oidc_handler.py
🔇 Additional comments (3)
source/app/configuration.py (1)

473-473: LGTM!

The new OIDC_JWKS_URI configuration follows the established pattern for optional OIDC endpoints and integrates well with the handler logic.

source/app/iris_engine/access_control/oidc_handler.py (2)

54-56: LGTM!

Good error handling pattern - logging the error for debugging while re-raising to ensure the application doesn't silently fail with a misconfigured OIDC setup.


58-64: LGTM!

Clean refactor using the pre-extracted variables. Note that client_id and client_secret could be None if not configured, which would cause authentication failures later - but this matches the original behavior and validation could be added upstream if desired.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.


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.

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