Skip to content

[CHORE]: Consolidate OIDC discovery + JWKS caching between sso_service and verify_credentials #4133

@jonpspri

Description

@jonpspri

Context

PR #3715 (OAuth access-token JWKS verification for virtual-server MCP endpoints) added OIDC discovery and JWKS client caches to mcpgateway/utils/verify_credentials.py:

  • _oauth_oidc_metadata_cache + _discover_oidc_metadata()
  • _oauth_jwks_client_cache
  • Used by verify_oauth_access_token() during MCP access-token verification

A structurally identical pair already exists in mcpgateway/services/sso_service.py for id_token verification during SSO callback. The two caches:

  • Serve different request paths (SSO callback vs MCP transport)
  • Have different lifecycles (one is used during interactive login, the other on every MCP request)
  • Implement the same discovery + JWKS retrieval pattern

This duplication was acknowledged in the PR #3715 description as a deliberate short-term decision so the access-token path could land without touching the SSO code path. This issue tracks the follow-up consolidation.

Proposal

Extract a shared module (e.g. mcpgateway/utils/oidc_discovery.py) that exposes:

  • async def discover_oidc_metadata(issuer: str) -> Optional[dict] — shared success/negative-TTL cache
  • get_jwks_client(jwks_uri: str) -> jwt.PyJWKClient — shared lazy client cache
  • Helpers to verify an RS/ES/PS/EdDSA-signed JWT against a discovered issuer

Callers:

  1. mcpgateway/utils/verify_credentials.py::verify_oauth_access_token — OAuth access-token path (PR feat(auth): verify OAuth access tokens via JWKS for virtual server MCP #3715).
  2. mcpgateway/services/sso_service.py — SSO id_token verification path.

Acceptance criteria

  • Single implementation of OIDC discovery with configurable success / negative TTL.
  • Single JWKS client cache keyed on jwks_uri.
  • Both callers delegate to the shared module; no duplicate dict/function definitions remain.
  • Unit tests for the shared module cover: successful discovery, 5xx / malformed JSON failures, negative-result caching, trailing-slash normalization, JWKS client reuse.
  • Existing tests in tests/unit/mcpgateway/test_auth.py::TestVerifyOauthAccessToken and the SSO id_token test suites continue to pass unchanged.

Non-goals

  • No behaviour change for existing auth paths.
  • No change to the allowlist logic (stays per-virtual-server for OAuth access tokens, per-SSO-provider for id_tokens).

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    choreLinting, formatting, dependency hygiene, or project maintenance choresenhancementNew feature or requesttriageIssues / Features awaiting triage

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions