quarkusio/quarkus · error · OIDCException
Access token values are not equal
Error message
Access token values are not equal
What it means
A test invariant check in the /protected/access endpoint. When an access token is present, the injected TokenCredential must match both the injected AccessToken annotation's raw token and the SecurityIdentity attribute under OidcConstants.ACCESS_TOKEN_VALUE. Any mismatch means Quarkus OIDC injected inconsistent token representations, so OIDCException is thrown.
Source
Thrown at integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/ProtectedResource.java:217
@GET
@Path("callback-jwt-not-used-before-redirect")
public String getNameCallbackJwtNotUsedBeforeRedirect() {
throw new InternalServerErrorException("This method must not be invoked");
}
@GET
@Path("callback-jwt-not-used-after-redirect")
public String getNameCallbackJwtNotUsedAfterRedirect() {
throw new InternalServerErrorException("This method must not be invoked");
}
@GET
@Path("access")
public String getAccessToken() {
if (accessToken.getRawToken() != null &&
(!accessTokenCredential.getToken().equals(accessToken.getRawToken())
|| !identity.getAttribute(OidcConstants.ACCESS_TOKEN_VALUE).equals(accessToken.getRawToken()))) {
throw new OIDCException("Access token values are not equal");
}
return accessToken.getRawToken() != null && !accessToken.getRawToken().isEmpty()
? "AT injected, active: " + isTokenActive()
: "no access";
}
private boolean isTokenActive() {
return oidcProviderClient.introspectAccessToken(accessTokenCredential.getToken()).await().indefinitely().isActive();
}
@GET
@Path("access/tenant-idtoken-only")
public String getAccessTokenIdTokenOnly() {
return "tenant-idtoken-only:" + getAccessToken();
}
@GETView on GitHub (pinned to e1c734241f)
Solutions
- Check that token refresh is not concurrently mutating the session during the request; serialize refresh or re-authenticate
- Verify no custom SecurityIdentityAugmentor drops or rewrites the ACCESS_TOKEN_VALUE attribute
- For split-token scenarios, confirm quarkus.oidc.token.refresh-token and related split-tokens properties are consistent across tenants
- If it reproduces on stock config, debug OidcIdentityProvider attribute population — likely a framework regression
Example fix
// before (mismatch tolerant)
String raw = accessToken.getRawToken();
String cred = accessTokenCredential.getToken();
// after (guard before comparing)
if (raw != null && cred != null && !cred.equals(raw)) {
throw new OIDCException("Access token values are not equal");
} Defensive patterns
Strategy: validation
Validate before calling
if (accessToken.getRawToken() != null && !accessTokenCredential.getToken().equals(accessToken.getRawToken())) { throw new IllegalStateException("injected access token mismatch"); } Type guard
boolean tokensConsistent(AccessToken at, TokenCredential cred, SecurityIdentity id) { return at.getRawToken() == null || (cred != null && at.getRawToken().equals(cred.getToken()) && at.getRawToken().equals(id.getAttribute("access_token"))); } Try / catch
try { return getAccessToken(); } catch (OIDCException e) { log.warnf("token mismatch: %s", e.getMessage()); reauthenticate(); } Prevention
- Avoid concurrent refresh during a request on the same session
- Do not register augmentors that rewrite the access_token attribute
- Test split-token tenants with dedicated endpoints
- Pin Quarkus OIDC version and review its changelog for token-propagation changes
When it happens
Trigger: GET /protected/access with a non-null access token where accessTokenCredential.getToken() != accessToken.getRawToken(), or identity.getAttribute(OidcConstants.ACCESS_TOKEN_VALUE) != accessToken.getRawToken().
Common situations: Token refresh raced with the request so identity holds a stale token; a custom augmentor replaced the identity without updating the ACCESS_TOKEN_VALUE attribute; multiple tenants with split-token storage producing mismatched attributes; regression in the OIDC token propagation code.
Related errors
- SecurityIdentity must have a RoutingContext attribute
- This method must not be invoked
- Refresh token values are not equal
- UserInfo is not required but '%s' is enabled
- The '%s' property can only be set to 'idtoken' for WEB_APP a
AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05).
Data as JSON: /api/errors/ec60214ebf8b3d4b.
Report an issue: GitHub.