Skip to content

feat(auth): KEYCLOAK_ALLOWED_AZP — let additional realm clients call the API - #317

Merged
telivity-otaip merged 2 commits into
TelivityAI:mainfrom
modernitconsultants:feat/allowed-azp
Aug 13, 2026
Merged

feat(auth): KEYCLOAK_ALLOWED_AZP — let additional realm clients call the API#317
telivity-otaip merged 2 commits into
TelivityAI:mainfrom
modernitconsultants:feat/allowed-azp

Conversation

@modernitconsultants

Copy link
Copy Markdown
Contributor

The problem

Both token verifiers (the passport HTTP strategy and the WebSocket mirror) require azp === KEYCLOAK_CLIENT_ID. azp is immutably the client that obtained the token — no audience mapper changes it — so a service account authenticating with client credentials on its own realm client can never pass. An integration gets 401 Invalid token audience (azp mismatch) with no way through except sharing the browser client, which is a public client that can't hold a secret.

We hit this integrating a companion service (enquiry pipeline) against the API: audience mapper added, aud correct, still 401 — measured live before we understood the guard.

The change

KEYCLOAK_ALLOWED_AZP: a comma-separated list of realm clients allowed to call.

  • Unset, behaviour is byte-for-byte unchanged — only the primary client passes. Existing deployments notice nothing.
  • aud stays single-valued and separately validated: the list widens who may call, not what audience a token must carry (callers still add the audience via a mapper).
  • Both verifiers read the same list — otherwise a caller works over HTTP and dies on the socket.

Tests

All four properties pinned: unset = old behaviour; listed clients pass; unlisted clients still fail; tokens without azp are unaffected (unchanged semantics).

…the API

Both verifiers (the passport strategy and the WebSocket mirror) required
azp === KEYCLOAK_CLIENT_ID. azp is immutably the client that obtained the
token, so a service account on its own realm client can never pass a
single-value equality, no matter what audience mappers it carries — an
integration authenticating with client credentials gets 401 "Invalid token
audience (azp mismatch)" with no way through except impersonating the
browser client.

KEYCLOAK_ALLOWED_AZP is a comma-separated list of realm clients allowed to
call. Unset, behaviour is byte-for-byte the old one — only the primary
client passes — so existing deployments notice nothing. aud stays
single-valued and separately validated: the list widens WHO may call, not
what audience a token must carry. Both verifiers read the same list, or a
caller would work over HTTP and die on the socket.

Tests pin all four properties: unset = old behaviour, listed clients pass,
unlisted still fail, tokens without azp unaffected.
Co-authored-by: telivity-otaip <telivity-otaip@users.noreply.github.com>
@telivity-otaip
telivity-otaip merged commit 5a6ba69 into TelivityAI:main Aug 13, 2026
5 checks passed
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.

3 participants