Skip to content

THREESCALE-15279: Add an "audience" protocol mapper to Keycloak integration#597

Open
jlledom wants to merge 2 commits into
masterfrom
THREESCALE-15279-token-introspection
Open

THREESCALE-15279: Add an "audience" protocol mapper to Keycloak integration#597
jlledom wants to merge 2 commits into
masterfrom
THREESCALE-15279-token-introspection

Conversation

@jlledom

@jlledom jlledom commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Jira Issue:

https://redhat.atlassian.net/browse/THREESCALE-15279

Description:

As the issue describes, after a breaking change in a recent RHBK release, the token introspection feature stopped working. In order to fix it, we need to ensure the access token received from keycloak includes the client id in the aud field.

Keycloak provides a way to write on this field, which is installing a protocol mapper type oidc-audiende-mapper in all clients.

This PR modifies the Keycloak integration in Zync to add such mapper in the requests to the client registration service in Keycloak.

Verification steps:

  1. Ensure the server allows the oidc-audience-mapper for client registration
    • Keycloak: Realm Settings -> Client Registration -> Client Registration Policies
    • RHBK: Clients -> Client Registration
    • In both cases, add oidc-audience-mapper to the Allowed Protocol Mapper Types policy for both Anonymous and Authenticated clients
  2. Sync an application from porta. The fastest way is to regenerate the client secret.
  3. You should see the mapper in the server UI
    • Keycloak: Clients -> [client id] -> Mappers
    • RHBK: Clients -> [client id] -> Client Scopes -> [client id]-dedicated -> Mappers
  4. Get an access token
ACCESS_TOKEN=`curl   -d "client_id=[client_id]"   -d "client_secret=[client_secret]"   -d "grant_type=client_credentials"   "[endpoint]/auth/realms/[realm]/protocol/openid-connect/token" | jq -r '.access_token'`
  1. Get the introspection token
curl -X POST     [endpoint]/auth/realms/joan/protocol/openid-connect/token/introspect     -u "[client_id]:[client_secret]"     -d "token=$ACCESS_TOKEN"
  1. You should get a valid token. If you get {"active": false} then it's not working.

RHBK 26.6.2+ rejects token introspection when the calling client is
not in the token's aud claim. Previously, Zync created OIDC clients
without an audience mapper, so tokens only contained aud: "account".
This caused introspection to fail with "Client '<client_id>' is not
in the token audience".

Add an oidc-audience-mapper protocol mapper to every client created
or updated by Zync. The mapper injects the client's own ID into the
aud claim of access tokens, satisfying RHBK's new validation
requirement while leaving ID tokens unchanged.

Assisted-by: Claude Code
@jlledom jlledom self-assigned this Jul 1, 2026
The audience mapper feature added protocolMappers to the client
payload sent to Keycloak. WebMock stubs in integration tests were
matching on exact request bodies without this field, causing 5 test
failures. Update all affected stubs to include the audience mapper
in their expected request bodies.

Assisted-by: Claude Code
@akostadinov-bot

Copy link
Copy Markdown

Compatibility & Correctness Review

The code change itself is clean and correct for the target use case (RHBK 26.6.2+). The oidc-audience-mapper type has been available since Keycloak 4.0 (2018), and the RESTAdapter for generic OIDC providers is untouched, so non-Keycloak services are not affected.

However, there are two operational risks worth discussing before merge:

1. "Allowed Protocol Mapper Types" policy will reject clients with 403

By default, Keycloak's Client Registration Policies do not whitelist oidc-audience-mapper. Any existing deployment that upgrades Zync without first adding oidc-audience-mapper to the "Allowed Protocol Mapper Types" policy (for both Anonymous and Authenticated clients) will get 403 Forbidden on every client create/update.

The PR description documents this as verification step 1, but it's actually a hard prerequisite — not a verification step. This should be surfaced prominently in release notes or a migration guide. Ideally, Zync would detect the 403 and log a clear message pointing at the policy configuration.

Ref: keycloak/keycloak#27558

2. Potential overwrite of existing protocol mappers

Previously, to_h omitted protocolMappers entirely, so Keycloak's Client Registration API left any existing mappers untouched on PUT. Now protocolMappers: [audience_mapper] is always sent, which — depending on Keycloak version — may replace all existing protocol mappers on the client with just this one. If an admin had manually added other mappers (e.g., group mappers, custom claim mappers), they could be wiped on the next Zync sync.

Worth verifying this behavior against the target Keycloak version, or consider reading the existing client's mappers and merging.

Test coverage gaps

  • No stubs updated for the create_client (POST) path — to_h is shared, so create requests also now include the mapper. If there are WebMock stubs matching POST bodies, they may silently not match.
  • No test for the 403 scenario when the mapper type is not whitelisted — this is the most likely failure mode in production.

Suggestion

Consider making the mapper configurable via Rails.application.config.x.keycloak (same pattern as self.attributes), so deployments on older Keycloak that don't need it can skip the policy prerequisite.

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