{"record":{"id":"c09b94890ced11d6","repo":"spring-projects/spring-security","slug":"invalid-token-response-c09b94","errorCode":"invalid_token_response","errorMessage":"An error occurred parsing the Access Token response: ${ex.getMessage()}","messagePattern":"An error occurred parsing the Access Token response: (.+?)","errorType":"error_code","errorClass":"OAuth2AuthorizationException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2AccessTokenResponseBodyExtractor.java","lineNumber":84,"sourceCode":"\t\treturn delegate.extract(inputMessage, context)\n\t\t\t.onErrorMap((ex) -> new OAuth2AuthorizationException(\n\t\t\t\t\tinvalidTokenResponse(\"An error occurred parsing the Access Token response: \" + ex.getMessage()),\n\t\t\t\t\tex))\n\t\t\t.switchIfEmpty(Mono.error(() -> new OAuth2AuthorizationException(\n\t\t\t\t\tinvalidTokenResponse(\"Empty OAuth 2.0 Access Token Response\"))))\n\t\t\t.map(OAuth2AccessTokenResponseBodyExtractor::parse)\n\t\t\t.flatMap(OAuth2AccessTokenResponseBodyExtractor::oauth2AccessTokenResponse)\n\t\t\t.map(OAuth2AccessTokenResponseBodyExtractor::oauth2AccessTokenResponse);\n\t}\n\n\tprivate static TokenResponse parse(Map<String, Object> json) {\n\t\ttry {\n\t\t\treturn TokenResponse.parse(new JSONObject(json));\n\t\t}\n\t\tcatch (ParseException ex) {\n\t\t\tOAuth2Error oauth2Error = invalidTokenResponse(\n\t\t\t\t\t\"An error occurred parsing the Access Token response: \" + ex.getMessage());\n\t\t\tthrow new OAuth2AuthorizationException(oauth2Error, ex);\n\t\t}\n\t}\n\n\tprivate static OAuth2Error invalidTokenResponse(String message) {\n\t\treturn new OAuth2Error(INVALID_TOKEN_RESPONSE_ERROR_CODE, message, null);\n\t}\n\n\tprivate static Mono<AccessTokenResponse> oauth2AccessTokenResponse(TokenResponse tokenResponse) {\n\t\tif (tokenResponse.indicatesSuccess()) {\n\t\t\treturn Mono.just(tokenResponse).cast(AccessTokenResponse.class);\n\t\t}\n\t\tTokenErrorResponse tokenErrorResponse = (TokenErrorResponse) tokenResponse;\n\t\tErrorObject errorObject = tokenErrorResponse.getErrorObject();\n\t\tOAuth2Error oauth2Error = getOAuth2Error(errorObject);\n\t\treturn Mono.error(new OAuth2AuthorizationException(oauth2Error));\n\t}\n\n\tprivate static OAuth2Error getOAuth2Error(ErrorObject errorObject) {","sourceCodeStart":66,"sourceCodeEnd":102,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-core/src/main/java/org/springframework/security/oauth2/core/web/reactive/function/OAuth2AccessTokenResponseBodyExtractor.java#L66-L102","documentation":"This OAuth2AuthorizationException with code invalid_token_response is thrown by OAuth2AccessTokenResponseBodyExtractor.parse when the access token response body cannot be parsed as JSON by Nimbus's TokenResponse. A ParseException from the raw JSON string is wrapped with an OAuth2Error describing the parse failure.","triggerScenarios":"The access token response body passed to parse is not valid JSON: empty body, HTML error page, or JSON array instead of object (JSONObject constructor or TokenResponse.parse throws ParseException).","commonSituations":"Authorization server/proxy returns HTML on token endpoint errors (wrong URL, 502 page), response body is empty because content was already consumed, or a mock server returns malformed JSON in tests.","solutions":["Log the raw response body to see what was actually returned.","Catch OAuth2AuthorizationException and check getError().getErrorCode() equals invalid_token_response.","Verify the token endpoint returns application/json with token_type/access_token fields per RFC 6749 section 5.1.","Check for proxies/gateways rewriting the response (HTML 502 pages).","If the response was error-shaped, ensure the caller distinguishes OAuth2ErrorResponse handling from token response parsing."],"exampleFix":"// before\nTokenResponse response = OAuth2AccessTokenResponseBodyExtractor.parse(body); // throws\n// after\ntry {\n    TokenResponse response = OAuth2AccessTokenResponseBodyExtractor.parse(body);\n} catch (OAuth2AuthorizationException ex) {\n    if (\"invalid_token_response\".equals(ex.getError().getErrorCode())) {\n        logger.warn(\"Token endpoint returned non-JSON: {}\", body);\n    }\n}","handlingStrategy":"try-catch","validationCode":"if (body == null || body.isBlank() || !body.strip().startsWith(\"{\")) {\n    throw new IllegalArgumentException(\"Access token response must be a JSON object\");\n}","typeGuard":null,"tryCatchPattern":"try {\n    TokenResponse response = OAuth2AccessTokenResponseBodyExtractor.parse(body);\n} catch (OAuth2AuthorizationException ex) {\n    if (\"invalid_token_response\".equals(ex.getError().getErrorCode())) {\n        logger.warn(\"Unparseable token response: {}\", body);\n    }\n}","preventionTips":["Log raw token endpoint bodies to detect HTML/proxy responses.","Confirm Content-Type is application/json before parsing.","Treat empty bodies (already-consumed streams) as a failure before parsing.","Use MockWebServer tests to cover malformed token responses."],"tags":["oauth2","json","reactive","token-response","spring-security"],"backgroundTag":"invalid-token-response","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}