Skip to content

[BUG]: Virtual server OAuth audience auto-learn cannot bootstrap with Authentik (aud == client_id) #4609

@kimsehwan96

Description

@kimsehwan96

🐞 Bug Summary

After v1.0.0 (which includes #4404 / #4410), virtual-server OAuth still fails with Audience doesn't match when using Authentik. The auto-learn mechanism never engages on the first request, and a manual DB write is still required.

The fallback path builds expected_audiences = [canonical_url, oauth_config.client_id], but the virtual-server admin form doesn't expose client_id. With client_id empty, the list collapses to [canonical_url], which never matches an Authentik token whose aud == client_id. Verification fails before _persist_learned_server_audience runs, so auto-learn cannot bootstrap.

This is a follow-up to #4171, which was closed assuming #4404/#4410 fully resolved the Authentik case ("No UI change needed, no manual DB manipulation"). In practice it doesn't, because there is no path to seed client_id for virtual servers.


🧩 Affected Component

Select the area of the project impacted:

  • mcpgateway - API
  • mcpgateway - UI (admin panel)
  • mcpgateway.wrapper - stdio wrapper
  • Federation or Transports
  • CLI, Makefiles, or shell scripts
  • Container setup (Docker/Podman/Compose)
  • Other (explain below)

🔁 Steps to Reproduce

  1. Deploy v1.0.0 with Authentik (or any IdP without RFC 8707 support that mints aud == client_id).
  2. Register a virtual server via the admin UI with oauth_enabled = true. The form has no client_id field, so oauth_config ends up with neither client_id nor resource set.
  3. Connect a client (e.g. Claude.ai custom connector) and complete the OAuth flow. Authentik issues a valid token with aud = "<authentik-client-id>".
  4. Client sends the token → 401 Audience doesn't match. Auto-learn never fires.
  5. Workaround: UPDATE servers SET oauth_config = jsonb_set(oauth_config, '{client_id}', '"<authentik-client-id>"') WHERE id = '<vs-id>'; After this, the next request matches via the client_id fallback, auto-learn runs, and resource is persisted.

🤔 Expected Behavior

Either approach closes the gap:


📓 Logs / Error Output

WARN [mcpgateway.utils.verify_credentials] OAuth access token verification failed: Audience doesn't match

🧠 Environment Info

You can retrieve most of this from the /version endpoint.

Key Value
Version or commit v1.0.0
Runtime Python 3.12, uvicorn
Platform / OS Linux (UBI 10), AWS EKS, linux/arm64
Container Docker

🧩 Additional Context (optional)

  • Reproduces with any IdP that mints aud == client_id and ignores the resource parameter from the OAuth authorization request.
  • The gateway-side OAuth form already accepts client_id. The asymmetry between gateway and virtual-server forms is the root cause.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingtriageIssues / 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