Skip to content

authService sends the ID token as API bearer credential, not the access token #3077

Description

@jpgough-ms

calm-hub-ui/src/authService.tsx:82 sends the ID token (id_token), not the access token, as the Authorization: Bearer credential for every configured OIDC provider — not just Entra ID. PluginAuthResource's VS Code plugin callback page reuses the same preference (data.id_token||data.access_token).

An ID token is an authentication receipt scoped to the client that requested it, consumed once at login — not an authorization credential for a resource server. Sending it as a bearer token on every API call is the anti-pattern the OAuth 2.0 Security Best Current Practice (RFC 9700) specifically warns against: its aud claim identifies the client, not the API.

This works today only because quarkus.oidc.token.audience/calm.oidc.token.audience in application-oidc.properties are pinned to the OIDC client ID, which happens to match the aud claim Entra ID and most generic OIDC providers put on an ID token. That match is provider behavior, not a spec guarantee — an IdP that scopes ID-token audience differently (or restricts ID-token issuance to endpoints that never see it) breaks this silently, and "does this token work" becomes "did this happen to work for the one IdP we tested."

Flagged in review on #3001 and again on #3065 (comment); scoped out of both slices to avoid redesigning the token flow mid-stack.

Fix

  • Switch to access_token as the bearer credential for calm-hub API calls; keep id_token only for populating the signed-in user's display identity in the UI.
  • Confirm every configured/tested IdP (Entra ID, Keycloak, generic OIDC) issues an access token actually scoped to calm-hub's API — some generic-OIDC setups need an explicit scope/audience configured to get one, rather than an opaque or narrowly-scoped default.
  • Apply the same fix to PluginAuthResource's callback page.

Out of scope

  • Redesigning the token-exchange flow itself (PKCE, server-side vs browser-side exchange).
  • Per-provider scope/audience configuration UX.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions