{"record":{"id":"fe3b2bae31ac1319","repo":"prestodb/presto","slug":"cannot-validate-tokens","errorCode":null,"errorMessage":"Cannot validate tokens","messagePattern":"Cannot validate tokens","errorType":"http","errorClass":"ChallengeFailedException","httpStatus":401,"severity":"error","filePath":"presto-main/src/main/java/com/facebook/presto/server/security/oauth2/NimbusOAuth2Client.java","lineNumber":419,"sourceCode":"            }\n        }\n\n        private void validateTokens(OIDCTokens tokens, Optional<String> nonce)\n                throws ChallengeFailedException\n        {\n            try {\n                IDTokenClaimsSet idToken = idTokenValidator.validate(\n                        tokens.getIDToken(),\n                        nonce.map(this::hashNonce)\n                                .map(Nonce::new)\n                                .orElse(null));\n                AccessTokenHash accessTokenHash = idToken.getAccessTokenHash();\n                if (accessTokenHash != null) {\n                    AccessTokenValidator.validate(tokens.getAccessToken(), ((JWSHeader) tokens.getIDToken().getHeader()).getAlgorithm(), accessTokenHash);\n                }\n            }\n            catch (BadJOSEException | JOSEException | InvalidHashException e) {\n                throw new ChallengeFailedException(\"Cannot validate tokens\", e);\n            }\n        }\n\n        private void validateTokens(OIDCTokens tokens)\n                throws ChallengeFailedException\n        {\n            validateTokens(tokens, Optional.empty());\n        }\n\n        private String hashNonce(String nonce)\n        {\n            return sha256()\n                    .hashString(nonce, UTF_8)\n                    .toString();\n        }\n    }\n\n    private <T extends AccessTokenResponse> T getTokenResponse(String code, URI callbackUri, NimbusAirliftHttpClient.Parser<T> parser)","sourceCodeStart":401,"sourceCodeEnd":437,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-main/src/main/java/com/facebook/presto/server/security/oauth2/NimbusOAuth2Client.java#L401-L437","documentation":"After fetching OIDC tokens, validateTokens verifies the ID token signature and claims with Nimbus JOSE+JWT and optionally the access token hash; any BadJOSEException, JOSEException, or InvalidHashException is wrapped in ChallengeFailedException('Cannot validate tokens').","triggerScenarios":"ID token signed by an untrusted/unconfigured key (JWKS mismatch), token expired or wrong issuer/audience, at_hash mismatch between access token and ID token, or malformed JWT from the IdP.","commonSituations":"IdP rotated signing keys and the coordinator cached stale JWKS, clock skew making tokens appear expired, wrong issuer-url or principal-field config, IdP updated to a signing algorithm the local configuration rejects, RS256 vs HS256 surprises.","solutions":["Verify oauth2.issuer-url, oauth2.principal-field and client id match the IdP exactly","Refresh/restart so the JWKS is re-fetched after an IdP key rotation","Check clock skew (NTP) on the coordinator against IdP token timestamps","Confirm the IdP signs ID tokens with an algorithm the Nimbus processor accepts (typically RS256) and at_hash matches the access token"],"exampleFix":"// before\n// issuer-url = https://old-idp.example.com (rotated)\n// after\n// issuer-url = https://new-idp.example.com ; restart coordinator to reload JWKS","handlingStrategy":"try-catch","validationCode":"// Pre-check: decode ID token JWT, verify iss == configured issuer-url and exp > now before calling validateTokens","typeGuard":"boolean claimsMatchConfig(com.nimbusds.jwt.JWTClaimsSet claims, java.net.URI issuer, String clientId) { return issuer.toString().equals(claims.getIssuer()) && java.util.Arrays.asList(claims.getAudience()).contains(clientId); }","tryCatchPattern":"try { client.getOAuth2Response(code, callbackUri, nonce); } catch (ChallengeFailedException e) { if (e.getCause() instanceof com.nimbusds.jose.JOSEException) { refreshJwksAndRetry(); } throw e; }","preventionTips":["Keep issuer-url, client-id and principal-field in sync with the IdP","Restart/reload JWKS after IdP key rotations","Run NTP on coordinators to limit clock-skew false expirations","Pin acceptable signing algorithms in IdP and Presto config"],"tags":["oauth2","oidc","jwt","token-validation"],"backgroundTag":"jwt-token-validation-failed","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}