{"record":{"id":"b37600b7f008e42a","repo":"quarkusio/quarkus","slug":"access-token-does-not-contain-a-confirmation-cnf","errorCode":null,"errorMessage":"Access token does not contain a confirmation 'cnf' claim with the certificate thumbprint","messagePattern":"Access token does not contain a confirmation 'cnf' claim with the certificate thumbprint","errorType":"exception","errorClass":"AuthenticationFailedException","httpStatus":401,"severity":"error","filePath":"extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java","lineNumber":232,"sourceCode":"            } else {\n                return verifySelfSignedTokenUni(resolvedContext, request.getToken().getToken());\n            }\n        } else {\n            final boolean idToken = isIdToken(request);\n            final TokenType tokenType = idToken ? TokenType.ID_TOKEN : TokenType.BEARER_ACCESS_TOKEN;\n            Uni<TokenVerificationResult> result = verifyTokenUni(requestData, resolvedContext, request.getToken(), tokenType,\n                    idToken, userInfo);\n            if (!idToken) {\n                if (resolvedContext.oidcConfig().token().binding().certificate()) {\n                    result = result.onItem().transform(new Function<TokenVerificationResult, TokenVerificationResult>() {\n\n                        @Override\n                        public TokenVerificationResult apply(TokenVerificationResult t) {\n                            String tokenCertificateThumbprint = getTokenCertThumbprint(requestData, t);\n                            if (tokenCertificateThumbprint == null) {\n                                LOG.warn(\n                                        \"Access token does not contain a confirmation 'cnf' claim with the certificate thumbprint\");\n                                throw new AuthenticationFailedException(tokenMap(request.getToken()));\n                            }\n                            String clientCertificateThumbprint = (String) requestData.get(OidcConstants.X509_SHA256_THUMBPRINT);\n                            if (clientCertificateThumbprint == null) {\n                                LOG.warn(\"Client certificate thumbprint is not available\");\n                                throw new AuthenticationFailedException(tokenMap(request.getToken()));\n                            }\n                            if (!clientCertificateThumbprint.equals(tokenCertificateThumbprint)) {\n                                LOG.warn(\"Client certificate thumbprint does not match the token certificate thumbprint\");\n                                throw new AuthenticationFailedException(tokenMap(request.getToken()));\n                            }\n                            return t;\n                        }\n\n                    });\n                }\n\n                if (requestData.containsKey(OidcUtils.DPOP_PROOF_JWT_HEADERS)) {\n                    result = result.onItem().transform(new Function<TokenVerificationResult, TokenVerificationResult>() {","sourceCodeStart":214,"sourceCodeEnd":250,"githubUrl":"https://github.com/quarkusio/quarkus/blob/e1c734241f34c7919086ceb4c9262b4a58f6de44/extensions/oidc/runtime/src/main/java/io/quarkus/oidc/runtime/OidcIdentityProvider.java#L214-L250","documentation":"During mTLS token-binding verification (OAuth2 certificate-bound tokens / RFC 8705), OidcIdentityProvider checks the verified access token for a 'cnf' claim containing the x5t#S256 certificate thumbprint. If getTokenCertThumbprint() returns null the token is not certificate-bound, a warning is logged and AuthenticationFailedException is thrown.","triggerScenarios":"quarkus.oidc.token.binding=verify (certificate-bound tokens required) but the IdP-issued access token lacks a cnf/x5t#S256 claim - e.g. the Authorization Server does not bind tokens to the client certificate, or the access token was issued without mTLS key confirmation.","commonSituations":"Enabling token binding verification while the OAuth2 provider never issues cnf claims; tokens minted by a different issuer or flow without client-certificate binding; proxies terminating TLS so the certificate thumbprint never reaches the IdP.","solutions":["Configure your Authorization Server to issue certificate-bound access tokens (mtls 'cnf' claim, RFC 8705) for mTLS client-authenticated clients.","If binding is not required, set quarkus.oidc.token.binding (token-binding) to 'none' so the thumbprint check is skipped.","Verify end-to-end mTLS (no TLS offloading losing the client certificate) so the IdP can include the certificate thumbprint in the token."],"exampleFix":"// before (application.properties)\nquarkus.oidc.token.binding=verify\n// IdP issues tokens without cnf => AuthenticationFailedException\n\n// after - either fix IdP to bind tokens, or disable verification\nquarkus.oidc.token.binding=none","handlingStrategy":"try-catch","validationCode":"// Pre-flight: confirm IdP issues bound tokens before enabling verification\n// Decode the access token payload and check the cnf claim\nboolean certificateBound = jwtClaims.contains(\"cnf\")\n    && jwtClaims.getJsonObject(\"cnf\").containsKey(\"x5t#S256\");\nif (!certificateBound && bindingRequired) { warn(\"IdP does not bind tokens to certificates\"); }","typeGuard":"boolean hasCnfThumbprint(jakarta.json.JsonObject claims) {\n    return claims.containsKey(\"cnf\")\n        && claims.getJsonObject(\"cnf\").containsKey(\"x5t#S256\");\n}","tryCatchPattern":"try {\n    identity = identityProvider.authenticate(event, identityManager);\n} catch (AuthenticationFailedException e) {\n    if (e.getMessage() != null && e.getMessage().contains(\"cnf\")) {\n        // token not certificate-bound: review quarkus.oidc.token.binding or IdP config\n    }\n    throw e;\n}","preventionTips":["Only set quarkus.oidc.token.binding=verify when the IdP supports RFC 8705 certificate-bound tokens","Keep mTLS end-to-end; avoid TLS termination that strips the client certificate","Decode a sample access token to verify the cnf/x5t#S256 claim before enabling verification","Align token binding settings for every named tenant, not just the default"],"tags":["oidc","mtls","token-binding","authentication-failed"],"backgroundTag":"certificate-bound-token-mismatch","analyzedSha":"e1c734241f34c7919086ceb4c9262b4a58f6de44","analyzedAt":"2026-09-05T17:01:29.979Z","contentChangedAt":"2026-09-05T17:01:29.979Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}