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();
    }

    @GET

View on GitHub (pinned to e1c734241f)

Solutions

  1. Check that token refresh is not concurrently mutating the session during the request; serialize refresh or re-authenticate
  2. Verify no custom SecurityIdentityAugmentor drops or rewrites the ACCESS_TOKEN_VALUE attribute
  3. For split-token scenarios, confirm quarkus.oidc.token.refresh-token and related split-tokens properties are consistent across tenants
  4. 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

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


AI-assisted analysis of quarkusio/quarkus@e1c734241f (2026-09-05). Data as JSON: /api/errors/ec60214ebf8b3d4b. Report an issue: GitHub.