{"record":{"id":"ec60214ebf8b3d4b","repo":"quarkusio/quarkus","slug":"access-token-values-are-not-equal","errorCode":null,"errorMessage":"Access token values are not equal","messagePattern":"Access token values are not equal","errorType":"http","errorClass":"OIDCException","httpStatus":500,"severity":"error","filePath":"integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/ProtectedResource.java","lineNumber":217,"sourceCode":"    @GET\n    @Path(\"callback-jwt-not-used-before-redirect\")\n    public String getNameCallbackJwtNotUsedBeforeRedirect() {\n        throw new InternalServerErrorException(\"This method must not be invoked\");\n    }\n\n    @GET\n    @Path(\"callback-jwt-not-used-after-redirect\")\n    public String getNameCallbackJwtNotUsedAfterRedirect() {\n        throw new InternalServerErrorException(\"This method must not be invoked\");\n    }\n\n    @GET\n    @Path(\"access\")\n    public String getAccessToken() {\n        if (accessToken.getRawToken() != null &&\n                (!accessTokenCredential.getToken().equals(accessToken.getRawToken())\n                        || !identity.getAttribute(OidcConstants.ACCESS_TOKEN_VALUE).equals(accessToken.getRawToken()))) {\n            throw new OIDCException(\"Access token values are not equal\");\n        }\n\n        return accessToken.getRawToken() != null && !accessToken.getRawToken().isEmpty()\n                ? \"AT injected, active: \" + isTokenActive()\n                : \"no access\";\n    }\n\n    private boolean isTokenActive() {\n        return oidcProviderClient.introspectAccessToken(accessTokenCredential.getToken()).await().indefinitely().isActive();\n    }\n\n    @GET\n    @Path(\"access/tenant-idtoken-only\")\n    public String getAccessTokenIdTokenOnly() {\n        return \"tenant-idtoken-only:\" + getAccessToken();\n    }\n\n    @GET","sourceCodeStart":199,"sourceCodeEnd":235,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/integration-tests/oidc-code-flow/src/main/java/io/quarkus/it/keycloak/ProtectedResource.java#L199-L235","documentation":"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.","triggerScenarios":"GET /protected/access with a non-null access token where accessTokenCredential.getToken() != accessToken.getRawToken(), or identity.getAttribute(OidcConstants.ACCESS_TOKEN_VALUE) != accessToken.getRawToken().","commonSituations":"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.","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"],"exampleFix":"// before (mismatch tolerant)\nString raw = accessToken.getRawToken();\nString cred = accessTokenCredential.getToken();\n// after (guard before comparing)\nif (raw != null && cred != null && !cred.equals(raw)) {\n    throw new OIDCException(\"Access token values are not equal\");\n}","handlingStrategy":"validation","validationCode":"if (accessToken.getRawToken() != null && !accessTokenCredential.getToken().equals(accessToken.getRawToken())) { throw new IllegalStateException(\"injected access token mismatch\"); }","typeGuard":"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\"))); }","tryCatchPattern":"try { return getAccessToken(); } catch (OIDCException e) { log.warnf(\"token mismatch: %s\", e.getMessage()); reauthenticate(); }","preventionTips":["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"],"tags":["oidc","access-token","quarkus","test-assertion"],"backgroundTag":"token-injection-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-12T22:17:10.623Z"}