The Audience (aud) Claim in Keycloak

The Audience (aud) Claim in Keycloak

A tiny field inside every token that answers one make-or-break question: "who is this token actually for?" — and why getting it wrong is one of the most common ways OAuth deployments get breached.

Picture a sealed envelope with someone’s name written on the front. The postal worker delivering it doesn’t need to open the envelope to know who it belongs to — the name on the front is enough to decide whether to hand it over or refuse. The audience claim, written as aud inside a token, is exactly that name on the envelope. Keycloak writes it onto every token it issues, and every application receiving that token is supposed to check the name before accepting what’s inside. This guide walks through what the audience claim is, how Keycloak decides what to put in it, what happens internally when a token is checked, and the very real security mistakes that happen when this one small field is ignored. No prior background in tokens or security is assumed.

1Core Concepts

Before the audience claim makes sense, you need a quick picture of what a token is and why Keycloak hands them out in the first place.

What is a token, in plain terms?

When you log into an application protected by Keycloak, Keycloak doesn’t hand your username and password to that application. Instead, it hands the application a token — a compact, digitally signed piece of text (usually in a format called JWT, JSON Web Token) that says “this person is who they claim to be, and here are some facts about them.” A JWT is built from small labeled facts called claims — think of each claim as one filled-in field on a form: who the user is, when the token expires, what permissions they have, and so on.

What exactly is the aud claim?

The audience claim, written as aud, is one specific field on that form. It lists which application or applications the token is meant to be used with. When Keycloak issues a token after a successful login, it stamps the token with the identifier of the application (called a client in Keycloak’s vocabulary) that requested it, or with a set of resource servers the token is authorized to be presented to. Any application receiving the token is expected to check: “does the aud claim in this token actually name me?” If it doesn’t, the receiving application should refuse the token outright, even if the token is otherwise perfectly valid and correctly signed.

Analogy

Think of a concert wristband. The band that puts it on your wrist is trustworthy (it’s genuinely a real wristband, not a fake), but a wristband for the Saturday night show does not get you into the Sunday matinee, even though it’s a perfectly genuine wristband from the same venue. The venue name and date printed on the band is the audience claim — the bouncer at each door checks that printed detail, not just whether the wristband looks real.

Why does the audience claim exist?

Without an audience claim, a single valid, correctly signed token could be replayed against any application trusting the same identity provider. An application that only checks “is this signature genuine?” but never checks “was this token meant for me?” opens the door to a serious attack called token substitution or confused deputy attack: a token legitimately issued for a low-security application could be stolen and reused against a high-security one, since both trust the same Keycloak signature. The audience claim exists specifically to close this gap by making the token itself declare its intended destination.

i
Where you’d meet this

Any time a Keycloak-protected microservice, API gateway, or backend receives a bearer token and has to decide “should I trust and process this request,” the audience claim is one of the very first things well-written verification code checks — before it even looks at what permissions the token claims to grant.

Key vocabulary, explained simply

Term

Client

Keycloak’s name for a registered application — could be a web frontend, a mobile app, or a backend API — that is allowed to request tokens from a given realm.

Term

Access Token

A short-lived token an application presents to prove the request is authorized; this is where the aud claim is most operationally important.

Term

ID Token

A token that tells the application who the logged-in user is; here, the aud claim identifies which client the login was performed for.

Term

Resource Server

Keycloak’s term for a backend API that consumes tokens and must be listed in the audience claim to legitimately accept them.

Term

Protocol Mapper

A configurable rule inside Keycloak that decides what value gets written into a specific claim, including aud, when a token is generated.

Term

Client Scope

A reusable, named bundle of protocol mapper rules (including audience mappers) that can be attached to one or many clients at once.

2Architecture & Components

Deciding what goes into the aud claim is not automatic magic — it runs through a specific, configurable pipeline inside Keycloak, with several pieces an administrator can tune.
graph TB
    C[Client requests token] --> RE[Realm Token Endpoint]
    RE --> DA["Default audience:
requesting client ID"] RE --> PM[Protocol Mappers on
Client Scopes] PM --> AM["Audience Mapper
adds resource-server client IDs"] PM --> CM["Custom Audience Mapper
adds arbitrary string values"] DA --> TB[Token Builder] AM --> TB CM --> TB TB --> T["Signed JWT
with final aud claim"] T --> RS[Resource Server verifies aud]
FIG 1 — How Keycloak assembles the audience claim before signing a token

Component breakdown

Component

Token Endpoint

The realm’s OpenID Connect endpoint that actually issues tokens after a successful login or token exchange; it runs the full mapper pipeline before signing anything.

Component

Default Audience Behavior

By default, Keycloak’s access token includes the requesting client’s own client ID in the aud claim — a sensible starting point, but often insufficient once a separate backend API needs to verify the token too.

Component

Audience Protocol Mapper

A built-in mapper type an administrator adds to a client scope, explicitly listing one or more client IDs (typically resource-server clients) that should be added to aud.

Component

Custom Audience Mapper

A variant of the same mapper that lets an admin add an arbitrary string value to aud, useful when the consuming service isn’t itself registered as a Keycloak client (for example, an external third-party API).

Where this is configured in the admin console

Inside the Keycloak Admin Console, an administrator opens a client’s Client Scopes tab, selects the dedicated scope (or a shared one), and adds a mapper under Mappers → Add mapper → By configuration → Audience. From there, the admin picks either “Included Client Audience” (pointing at another registered client) or “Included Custom Audience” (a free-text value), and decides whether this mapper applies to the access token, the ID token, or both.

A common real setup

A single-page application client (“web-frontend”) logs users in, but the actual API calls go to a separate backend client (“orders-api”). Without any extra configuration, tokens issued to “web-frontend” would only carry “web-frontend” in aud — useless to “orders-api.” An audience mapper is added to explicitly include “orders-api” in the token’s aud claim, so the backend can legitimately accept it.

Why doesn’t Keycloak just include everything by default?

It would be simpler for Keycloak to stamp every registered client’s ID into every token’s audience claim — but that would defeat the entire purpose. A token meant only for a low-trust marketing widget would then also be valid against a sensitive payments API, exactly the confused-deputy risk the claim exists to prevent. Keycloak deliberately requires an administrator to explicitly opt a resource server into a token’s audience, forcing a conscious security decision rather than a convenient default.

3Internal Working

There are two separate moments where the audience claim matters: when Keycloak builds it into a token, and when a receiving application checks it. Both steps have their own internal logic.

How Keycloak builds the claim

When a token request reaches Keycloak’s token endpoint, the server first determines the requesting client and, where applicable, the granted scopes. It then runs through every protocol mapper attached to those scopes, in order. Any mapper of type “Audience” contributes its configured value — either another client’s ID or a custom string — to a running list. Once all mappers have run, Keycloak deduplicates the list, adds the requesting client’s own ID if the default audience behavior applies, and writes the final list into the token’s aud field before signing the whole token with the realm’s private signing key.

Single value or a list?

The aud claim, per the underlying JWT specification, can hold either a single string or an array of strings. Keycloak reflects this directly: a token intended for exactly one audience carries aud as a plain string, while a token meant for multiple resource servers carries it as an array. This matters for the code on the receiving end — a naive audience check that only handles the single-string case will silently misbehave once a token starts carrying multiple audiences.

!
Gotcha

Some libraries default to checking “is aud exactly equal to my expected value,” which breaks the moment the claim becomes an array. Correct verification code should check “does my expected value appear anywhere in the aud list,” regardless of whether it’s a single string or an array.

How a receiving application should check it

On the receiving side, a resource server that gets a bearer token should, as one of its very first verification steps, extract the aud claim and confirm that its own known client ID or resource identifier appears in it. This check happens independently of, and in addition to, checking the token’s digital signature and expiry time. A token can be genuinely signed by Keycloak, genuinely unexpired, and still be entirely wrong to accept — if its audience does not name the service receiving it.

“A valid signature proves who issued the token. The audience claim proves who it was issued for.”

Step-by-step: audience handling from login to API call

1

Login request arrives

A user authenticates through a client application, which requests a token from Keycloak’s token endpoint.

2

Mapper pipeline runs

Keycloak evaluates every attached protocol mapper, including any audience mappers, gathering the intended recipients.

3

Token signed and returned

The finished token, with its aud claim populated, is signed and handed back to the requesting client.

4

Client presents token to API

The frontend application attaches the access token to an API call, typically in an Authorization header.

5

Resource server verifies audience

The backend checks the signature, expiry, and crucially, whether its own identifier is present in aud.

6

Request accepted or rejected

Only if every check, including the audience match, passes does the backend proceed to process the request.

4Data Flow & Lifecycle

Seeing where the audience claim sits inside the larger login-to-API-call journey makes it clear exactly which party is responsible for checking it, and when.
sequenceDiagram
    participant User
    participant Frontend as Client App
    participant Keycloak
    participant API as Resource Server

    User->>Frontend: Logs in
    Frontend->>Keycloak: Requests token
    Keycloak->>Keycloak: Runs audience mappers
    Keycloak->>Frontend: Issues token with aud claim set
    Frontend->>API: Calls API with token
    API->>API: Verifies signature and expiry
    API->>API: Checks own ID is inside aud claim
    alt aud matches
        API->>Frontend: Processes request normally
    else aud does not match
        API->>Frontend: Rejects with 401/403
    end
    
FIG 2 — The audience check as a gate the resource server enforces independently of Keycloak

Notice that Keycloak’s job ends the moment it signs and hands over the token. Keycloak never sees, and cannot control, whether a downstream resource server actually bothers to check the audience claim once the token is in circulation. This is a crucial architectural point: the audience claim is only as strong as the verification code written by every team building a resource server. A misconfigured or lazily written backend that skips the audience check entirely reopens exactly the confused-deputy risk the claim was designed to close, no matter how correctly Keycloak populated the field.

Lifecycle of the audience claim within one token

A

Determined at issuance

The audience value is fixed the moment Keycloak signs the token — it cannot change afterward without invalidating the signature.

B

Carried unchanged in transit

As the token travels from client to API, sometimes through several hops or a gateway, the audience claim rides along inside the signed payload, untouched.

C

Checked at every consuming service

Each resource server that receives the token independently re-checks the audience — there is no shared, central enforcement point unless a gateway is explicitly built to do it.

D

Expires with the token

Once the token’s expiry time passes, the audience claim (like every other claim) becomes irrelevant, since the whole token is rejected on expiry grounds first.

i
Worth noting

Refresh tokens and access tokens issued from the same login can carry different audience values, since a refresh token’s purpose (getting a new access token from Keycloak) is different from an access token’s purpose (being presented to a resource server), and Keycloak’s mapper configuration can reflect that difference.

5Advantages, Disadvantages & Trade-offs

Using the audience claim well is a trade-off between tight, explicit security boundaries and the extra configuration work of maintaining them.

Advantages

  • Directly prevents confused-deputy and token substitution attacks between applications sharing the same Keycloak realm
  • Gives each resource server a simple, self-contained check it can perform without calling back to Keycloak
  • Scales naturally to many microservices — each just checks for its own identifier in the list
  • Works entirely offline once the token is issued, since the claim travels inside the signed token itself

Disadvantages & Trade-offs

  • Requires deliberate, per-client mapper configuration — nothing is automatically correct as an organization’s number of services grows
  • Easy to forget when adding a new backend service, silently leaving it unable to accept otherwise-valid tokens
  • Verification is only as good as the code every individual team writes — Keycloak cannot force a lazy backend to actually check aud
  • Overly broad audience lists (adding every client “just in case”) quietly recreate the exact risk the claim was meant to prevent
Analogy

Configuring audience mappers is like addressing a set of physical keys to specific doors. It takes real effort to cut and label each key correctly, and if you get lazy and cut a master key that opens every door “to save time,” you’ve quietly removed the whole point of having separate locks in the first place.

6Security

The audience claim is, first and foremost, a security control — but only when the party receiving the token actually enforces it. This chapter covers the failure modes to defend against.

The confused-deputy attack, concretely

Suppose an organization runs two Keycloak clients: a low-security internal “employee-directory” app and a high-security “payroll-api.” If a token issued for employee-directory happens to also be accepted by payroll-api (because payroll-api never checks aud), an attacker who compromises the low-security app — or simply intercepts a token meant for it — can replay that same token against the payroll API and be treated as authorized. Enforcing the audience claim on payroll-api’s side closes this gap completely, since a token honestly issued for employee-directory will never list payroll-api in its aud claim.

SEC-02Recommended
Context

Teams frequently build resource servers using off-the-shelf JWT libraries that validate the signature and expiry by default but leave audience checking as an optional, easily-missed configuration flag.

Decision

Every resource server must explicitly configure and enable audience validation against its own known client identifier as a mandatory part of token verification, never relying on library defaults alone.

Consequence

Tokens genuinely issued for other applications are rejected automatically, closing the confused-deputy gap without requiring any change to how Keycloak itself issues tokens.

Audience versus authorization — a common confusion

Passing the audience check only proves a token was meant for this service — it says nothing about what the user is allowed to do once inside. Roles, scopes, and permissions are separate claims and separate checks. A well-built resource server treats the audience check as a first gate, and role or scope checks as a second, independent gate that runs afterward.

!
Common mistake

Treating a matching audience claim as proof the user is authorized for a specific action. The audience claim only answers “was this token meant for me,” never “is this specific user allowed to do this specific thing.”

Multi-tenant and shared-realm considerations

In a realm shared by many unrelated applications, keeping audience mappers scoped tightly is especially important, since the “blast radius” of a missing check grows with every additional client sharing that realm’s trust. Organizations running multi-tenant Keycloak setups often adopt a strict rule: every new resource-server client must ship with its audience mapper reviewed as part of onboarding, not added as an afterthought once something breaks.

7Monitoring, Logging & Metrics

Audience mismatches are exactly the kind of subtle failure that stays invisible until someone is actively looking for it — so building visibility around them is worth deliberate effort.

What to watch for

401
typical HTTP status a resource server should return on an audience mismatch
2
separate checks every token deserves: signature/expiry, and audience
1
missing mapper is often all it takes to silently break a new integration
Metric

Audience rejection rate

How often a resource server rejects an otherwise-valid, correctly signed token purely on an audience mismatch — a rising trend usually points to a misconfigured client or mapper.

Metric

New-client onboarding checklist completion

Tracking whether every newly registered resource-server client has a reviewed audience mapper attached before going live, as a process metric rather than a runtime one.

Metric

Cross-service token reuse attempts

Logging and alerting whenever a token whose audience names Service A is presented to Service B, since this is a strong indicator of either misconfiguration or an active attack.

Where to look

Keycloak’s own event log records token issuance events but does not, by itself, tell you whether a downstream resource server later accepted or rejected a token based on its audience — that check happens entirely outside Keycloak, inside each application’s own code. This means audience-specific monitoring has to be built on the resource-server side: logging every rejected request along with the reason (signature failure versus expiry versus audience mismatch) so the three failure types can be told apart during an investigation.

A practical debugging habit

When an integration between a new frontend and a backend API mysteriously returns “unauthorized” despite a seemingly valid login, decoding the access token’s claims (most JWT debugging tools display claims in plain readable JSON) and simply checking whether the backend’s client ID appears in aud is often the fastest way to find the root cause — far faster than assuming the problem lies in roles or permissions.

8Design Patterns & Anti-patterns

Teams that manage many Keycloak clients tend to settle on a few dependable ways of organizing audience mappers, and repeatedly stumble into the same handful of traps.

Proven patterns

Pattern

Shared client scope for common APIs

Bundle an audience mapper for a widely used internal API into a reusable client scope, then attach that scope to every frontend client that needs to call it, instead of repeating the mapper configuration per client.

Pattern

One resource-server client, one purpose

Register each meaningfully distinct backend as its own Keycloak client, so audience lists stay short, specific, and easy to reason about.

Pattern

Audience as onboarding checklist item

Make “register an audience mapper for this new service” a mandatory step in the standard process for connecting any new backend to the identity platform.

Pattern

Gateway-level pre-check

Have an API gateway perform an initial audience check for common services before requests even reach individual backends, as a defense-in-depth layer on top of each service’s own check.

Anti-patterns to avoid

Anti-pattern

  • Adding every registered client to every token’s audience “to avoid configuration headaches”
  • Skipping audience validation in a resource server because “the signature check is enough”
  • Relying on the requesting client’s own ID as the sole audience, even after a separate backend API is introduced
  • Hard-coding an expected audience string in application code without documenting which Keycloak client it corresponds to, causing confusion during later rotations or renames

Instead, do this

  • Add only the specific resource servers a token genuinely needs to reach
  • Always validate audience as a separate, mandatory check alongside signature and expiry
  • Add explicit audience mappers as soon as a token needs to reach more than the requesting client
  • Keep the expected audience value alongside clear documentation of which Keycloak client it maps to

9Best Practices & Common Mistakes

Getting the audience claim right long-term is less about clever configuration and more about consistent, disciplined habits across every team touching Keycloak.

Best practices

1

Enforce audience checks in a shared library

Rather than trusting every team to remember to check aud correctly, bake the check into a shared authentication middleware used across all services.

2

Review audience mappers during security audits

Periodically list every client’s audience mapper configuration and confirm each one is still scoped as narrowly as intended, since org charts and integrations change over time.

3

Document the expected audience per service

Keep a simple, accessible reference of which Keycloak client ID each backend expects to see in its incoming tokens’ aud claim.

4

Test the negative case, not just the positive one

Include an automated test that deliberately presents a token with the wrong audience and confirms the service correctly rejects it, not just tests that a correct token is accepted.

Common mistakes

!
Mistake

Assuming that because a token came from the “same trusted Keycloak instance,” it must be safe to accept regardless of audience — trust in the issuer and correctness of the destination are two entirely separate questions.

!
Mistake

Forgetting that ID tokens and access tokens can, and often should, carry different audience configurations, and accidentally applying an access-token audience mapper to the ID token as well, confusing frontend code that expects a specific single value there.

!
Mistake

Leaving default audience behavior unexamined after introducing a new backend API, assuming Keycloak will “figure it out,” when in fact an explicit mapper is required for the new service to appear in the claim at all.

10Real-world & Industry Examples

The audience claim is not a Keycloak-specific curiosity — it is part of the same OpenID Connect standard used across the industry, and organizations running Keycloak apply the same defensive pattern seen everywhere else.
Industry

Microservice platforms

Companies running dozens of internal microservices behind Keycloak commonly enforce audience checks at both an API gateway layer and inside each individual service, as layered defense against token misuse.

Industry

Banking and fintech

Financial platforms separating customer-facing apps from sensitive internal transaction APIs rely heavily on tightly scoped audience claims to ensure a customer-facing token can never be replayed against internal transaction-processing services.

Industry

SaaS platforms with public APIs

Software vendors exposing a public developer API alongside an internal admin API use distinct audience values to guarantee that a token issued to a third-party developer integration cannot accidentally be valid against internal administrative endpoints.

Industry

Healthcare data systems

Systems handling patient records under strict regulatory obligations often mandate explicit audience validation as a documented, auditable control precisely because a confused-deputy failure there carries serious compliance consequences.

A representative scenario

An engineering team splitting a monolithic application into a frontend and a separate orders microservice discovered, during a security review, that the orders service accepted any token signed by their Keycloak realm without checking its audience — meaning a token issued for an unrelated internal reporting tool would also work against the orders API. Adding an explicit audience mapper for the orders client, combined with a mandatory audience check in the orders service’s authentication middleware, closed the gap without requiring any change to how users logged in.

11FAQ

Q1What does Keycloak put in aud by default?
By default, Keycloak’s access token includes the ID of the client that requested it. Additional audiences must be added explicitly through protocol mappers.
Q2Can a token have more than one audience?
Yes. The aud claim can be an array of values when a token is meant to be accepted by more than one resource server, each of which independently checks that its own identifier is present.
Q3Does Keycloak enforce the audience check itself?
No. Keycloak only writes the claim into the token when it’s issued. Checking the claim afterward is the responsibility of whichever resource server receives the token.
Q4What happens if my backend never checks the audience claim?
Your backend will accept any correctly signed, unexpired token from the same Keycloak realm, regardless of which application it was actually issued for — opening the door to confused-deputy style token misuse.
Q5Is the audience claim the same as a role or a scope?
No. The audience claim only answers “was this token meant for me.” Roles and scopes are separate claims that answer “what is this user allowed to do,” and should be checked independently.
Q6How do I add a resource server to a token’s audience?
In the Keycloak Admin Console, add an “Audience” protocol mapper to the relevant client scope, pointing it at the resource server’s client ID (or a custom value for non-Keycloak-registered services).

12Summary and Key Takeaways

Key Takeaways

  • The audience (aud) claim names which application or applications a token is meant to be presented to — it is the “who this envelope is addressed to” field.
  • Keycloak fills this claim through a configurable protocol mapper pipeline, defaulting to the requesting client’s own ID unless additional mappers are explicitly added.
  • The claim exists specifically to prevent confused-deputy and token substitution attacks, where a token meant for one service is replayed against another.
  • Keycloak’s role ends at issuing the claim correctly; enforcing it is entirely the responsibility of each resource server receiving the token.
  • The claim can be a single string or an array, and verification code must handle both forms correctly.
  • Audience checks and authorization checks (roles, scopes) are separate concerns — passing one says nothing about the other.
  • Best practice is to keep audience lists as narrow as possible, add mappers deliberately during onboarding, and bake the check into shared authentication code rather than trusting every team to remember it.
  • Weak or missing audience validation is one of the most common, and most dangerous, oversights in real-world OpenID Connect deployments.