{"record":{"id":"ba3f1af6d811b27e","repo":"spring-projects/spring-security","slug":"invalid-request-ba3f1a","errorCode":"invalid_request","errorMessage":"OAuth 2.0 Parameter: redirect_uri","messagePattern":"OAuth 2\\.0 Parameter: redirect_uri","errorType":"error_code","errorClass":"OAuth2AuthorizationCodeRequestAuthenticationException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationValidator.java","lineNumber":134,"sourceCode":"\t\tRegisteredClient registeredClient = authenticationContext.getRegisteredClient();\n\n\t\tString requestedRedirectUri = authorizationCodeRequestAuthentication.getRedirectUri();\n\n\t\tif (StringUtils.hasText(requestedRedirectUri)) {\n\t\t\t// ***** redirect_uri is available in authorization request\n\n\t\t\tUriComponents requestedRedirect = null;\n\t\t\ttry {\n\t\t\t\trequestedRedirect = UriComponentsBuilder.fromUriString(requestedRedirectUri).build();\n\t\t\t}\n\t\t\tcatch (Exception ex) {\n\t\t\t}\n\t\t\tif (requestedRedirect == null || requestedRedirect.getFragment() != null) {\n\t\t\t\tif (LOGGER.isDebugEnabled()) {\n\t\t\t\t\tLOGGER.debug(LogMessage.format(\"Invalid request: redirect_uri is missing or contains a fragment\"\n\t\t\t\t\t\t\t+ \" for registered client '%s'\", registeredClient.getId()));\n\t\t\t\t}\n\t\t\t\tthrow createException(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.REDIRECT_URI,\n\t\t\t\t\t\tauthorizationCodeRequestAuthentication, registeredClient);\n\t\t\t}\n\n\t\t\tif (!isLoopbackAddress(requestedRedirect.getHost())) {\n\t\t\t\t// As per\n\t\t\t\t// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics-22#section-4.1.3\n\t\t\t\t// When comparing client redirect URIs against pre-registered URIs,\n\t\t\t\t// authorization servers MUST utilize exact string matching.\n\t\t\t\tif (!registeredClient.getRedirectUris().contains(requestedRedirectUri)) {\n\t\t\t\t\tthrow createException(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.REDIRECT_URI,\n\t\t\t\t\t\t\tauthorizationCodeRequestAuthentication, registeredClient);\n\t\t\t\t}\n\t\t\t}\n\t\t\telse {\n\t\t\t\t// As per\n\t\t\t\t// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-08#section-8.4.2\n\t\t\t\t// The authorization server MUST allow any port to be specified at the\n\t\t\t\t// time of the request for loopback IP redirect URIs, to accommodate","sourceCodeStart":116,"sourceCodeEnd":152,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2AuthorizationCodeRequestAuthenticationValidator.java#L116-L152","documentation":"This error is thrown when validating the redirect_uri of an authorization code request and the URI is either missing entirely (when required) or contains a fragment component. OAuth2 forbids fragments in redirect URIs because fragments are never sent to the server, so the library rejects such requests with invalid_request attributed to redirect_uri.","triggerScenarios":"OAuth2AuthorizationCodeRequestAuthenticationValidator.validateRedirectUri finds requestedRedirect == null (no valid redirect_uri could be resolved for the request) or requestedRedirect.getFragment() != null (e.g. redirect_uri=https://app.example.com/cb#section).","commonSituations":"Client omitted redirect_uri and the request is not using an exactly-one-registered-redirect-uri client; a frontend appends routing fragments (#/route) to the redirect URI; a registered or requested redirect URI copied from a SPA with hash-based routing; trailing whitespace/encoding issues causing URI parse failures.","solutions":["Remove the fragment from the redirect_uri in the authorization request and from the registered redirect URIs.","Always send redirect_uri explicitly and make sure it is a well-formed absolute URI with scheme, host, and path.","For SPAs with hash routing, use path-based callback URLs (e.g. /callback) and route in the app after the redirect.","Ensure the client has at least one registered redirect URI if redirect_uri is not provided in the request."],"exampleFix":"// before\nString url = \"/oauth2/authorize?response_type=code&client_id=my-client&redirect_uri=https://app.example.com/cb#home\";\n// after\nString url = \"/oauth2/authorize?response_type=code&client_id=my-client&redirect_uri=https://app.example.com/cb\";","handlingStrategy":"validation","validationCode":"// validate the redirect_uri before sending the request\nURI uri = URI.create(redirectUri);\nboolean valid = uri.isAbsolute()\n    && uri.getScheme() != null\n    && uri.getHost() != null\n    && uri.getFragment() == null;\nif (!valid) {\n    throw new IllegalArgumentException(\"redirect_uri must be absolute with no fragment: \" + redirectUri);\n}","typeGuard":null,"tryCatchPattern":"try {\n    authenticate(authorizationRequest);\n} catch (OAuth2AuthorizationCodeRequestAuthenticationException e) {\n    if (\"invalid_request\".equals(e.getError().getErrorCode())\n            && \"redirect_uri\".equals(e.getError().getParameterName())) {\n        log.error(\"redirect_uri missing or contains a fragment: {}\", authorizationRequest.getRedirectUri());\n    }\n    throw e;\n}","preventionTips":["Never append fragments (#) to redirect URIs; SPAs should use path-based callbacks","Always send redirect_uri explicitly rather than relying on a single registered default","Validate redirect URIs in CI by parsing them with java.net.URI","Keep registered redirect URIs fragment-free as well"],"tags":["oauth2","redirect-uri","validation","authorization-server"],"backgroundTag":"invalid-redirect-uri","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"}