spring-projects/spring-security · error · OAuth2AuthenticationException

invalid_redirect_uri

invalid_redirect_uri

Error message

Invalid Client Registration: redirect_uris

What it means

During dynamic client registration, validateRedirectUris parses each registered redirect_uris value as a URI; when new URI(redirectUri) throws URISyntaxException the validator throws invalid_redirect_uri for the redirect_uris claim. The registration request is rejected because an unparseable redirect URI can never be validated safely in authorization flows.

Solutions

  1. Fix the offending redirect URI so it is a fully-qualified, syntactically valid absolute URI (scheme + host, properly percent-encoded)
  2. Check the debug log line 'Invalid request: redirect_uri is not parseable' to identify the exact malformed value
  3. Validate URIs client-side before submitting the registration request

Example fix

// before
{"redirect_uris": ["/callback"]}
// after
{"redirect_uris": ["https://client.example.org/callback"]}
Defensive patterns

Strategy: validation

Validate before calling

try { new java.net.URI(redirectUri).toURL(); } catch (Exception e) { throw new IllegalArgumentException("redirect_uris entry is not a valid absolute URI: " + redirectUri); }

Type guard

boolean isValidRedirectUri(String uri) {
    try { return new java.net.URI(uri).isAbsolute(); } catch (Exception e) { return false; }
}

Try / catch

catch (OAuth2ErrorResponseException e) { if ("invalid_redirect_uri".equals(e.getError().getErrorCode())) { log.error("Malformed redirect URI: {}", e.getError().getParameters()); } }

Prevention

When it happens

Trigger: POSTing a client-registration request whose redirect_uris array contains a string that is not a syntactically valid URI (e.g. missing scheme/host, illegal characters, spaces, or a relative path like '/callback').

Common situations: Copy-pasted URIs with typos or unencoded characters; forgetting 'https://' prefix; building URIs by string concatenation with unencoded query values; YAML/JSON config holding a bare path instead of an absolute URL.

Understand the failure class

Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.

Related errors


AI-assisted analysis of spring-projects/spring-security@96852e8860 (2026-09-10). Data as JSON: /api/errors/98abe9a78dba6578. Report an issue: GitHub.

Appendix: source

Thrown at oauth2/oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/authentication/OAuth2ClientRegistrationAuthenticationValidator.java:144

	private static void validateRedirectUris(OAuth2ClientRegistrationAuthenticationContext authenticationContext) {
		OAuth2ClientRegistrationAuthenticationToken clientRegistrationAuthentication = authenticationContext
			.getAuthentication();
		List<String> redirectUris = clientRegistrationAuthentication.getClientRegistration().getRedirectUris();
		if (CollectionUtils.isEmpty(redirectUris)) {
			return;
		}
		for (String redirectUri : redirectUris) {
			URI parsed;
			try {
				parsed = new URI(redirectUri);
			}
			catch (URISyntaxException ex) {
				if (LOGGER.isDebugEnabled()) {
					LOGGER
						.debug(LogMessage.format("Invalid request: redirect_uri is not parseable ('%s')", redirectUri));
				}
				throw createException(OAuth2ErrorCodes.INVALID_REDIRECT_URI,
						OAuth2ClientMetadataClaimNames.REDIRECT_URIS);
			}
			if (parsed.getFragment() != null) {
				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug(
							LogMessage.format("Invalid request: redirect_uri contains a fragment ('%s')", redirectUri));
				}
				throw createException(OAuth2ErrorCodes.INVALID_REDIRECT_URI,
						OAuth2ClientMetadataClaimNames.REDIRECT_URIS);
			}
			String scheme = parsed.getScheme();
			if (scheme == null) {
				if (LOGGER.isDebugEnabled()) {
					LOGGER.debug(LogMessage.format("Invalid request: redirect_uri has no scheme ('%s')", redirectUri));
				}
				throw createException(OAuth2ErrorCodes.INVALID_REDIRECT_URI,
						OAuth2ClientMetadataClaimNames.REDIRECT_URIS);
			}

View on GitHub (pinned to 96852e8860)