keycloak/keycloak · error · VerificationException
Missing expectedAudience
Error message
Missing expectedAudience
What it means
Thrown by AudienceCheck.test when the predicate was constructed with a null expectedAudience. Like RealmUrlCheck's null guard, this fails fast rather than silently passing a no-op audience check. The check requires a concrete expected audience to compare against the token's 'aud' claim.
Source
Thrown at core/src/main/java/org/keycloak/TokenVerifier.java:152
if (tokenType.equalsIgnoreCase(t.getType())) return true;
}
throw new VerificationException("Token type is incorrect. Expected '" + tokenTypes.toString() + "' but was '" + t.getType() + "'");
}
}
public static class AudienceCheck implements Predicate<JsonWebToken> {
private final String expectedAudience;
public AudienceCheck(String expectedAudience) {
this.expectedAudience = expectedAudience;
}
@Override
public boolean test(JsonWebToken t) throws VerificationException {
if (expectedAudience == null) {
throw new VerificationException("Missing expectedAudience");
}
String[] audience = t.getAudience();
if (audience == null) {
throw new VerificationException("No audience in the token");
}
if (t.hasAudience(expectedAudience)) {
return true;
}
throw new VerificationException("Expected audience not available in the token");
}
}
public static class IssuedForCheck implements Predicate<JsonWebToken> {
View on GitHub (pinned to 66c7e15a37)
Solutions
- Supply a non-null audience when constructing the check, typically the resource-server client id.
- If audience checking is not desired, do not add AudienceCheck to the verifier chain instead of passing null.
- Validate the config key for the expected audience before building the verifier.
Example fix
// before: audience config resolves to null
verifier.audience(config.get("clientId")); // null
// after: guard before applying the check
String aud = config.get("clientId");
if (aud != null) verifier.audience(aud); Defensive patterns
Strategy: validation
Validate before calling
// Validate expected audience before constructing the check
String aud = config.get("expectedAudience");
if (aud == null) {
throw new IllegalStateException("expectedAudience not configured");
}
TokenVerifier.create(token, AccessToken.class).audience(aud).verify(); Type guard
static boolean hasExpectedAudience(String aud) {
return aud != null && !aud.isBlank();
} Try / catch
try {
verifier.audience(expectedAudience).verify();
} catch (VerificationException e) {
if (e.getMessage().equals("Missing expectedAudience")) {
// configuration bug — populate the audience and retry
} else throw e;
} Prevention
- Never pass null to AudienceCheck; omit the check instead.
- Resolve the consuming client/resource id before building the verifier.
- Fail fast at startup if the expected-audience config key is missing.
When it happens
Trigger: Constructing new TokenVerifier.AudienceCheck(null) or supplying a null expected audience through a builder/config path that resolves to null while the AudienceCheck remains active.
Common situations: A resource server that loads the expected audience from config but the config key is missing/empty, or building an AudienceCheck dynamically from a client-id that was not yet resolved.
Related errors
- Realm URL not set
- No audience in the token
- Expected audience not available in the token
- Missing expectedIssuedFor
- Subject missing in token
AI-assisted analysis of keycloak/keycloak@66c7e15a37 (2026-08-14).
Data as JSON: /api/errors/559b9f91e7386889.
Report an issue: GitHub.