1
0
mirror of synced 2026-07-19 17:45:11 +00:00

Polish redirect flows

This commit is contained in:
Joe Grandja
2026-04-30 09:42:07 -04:00
parent c50e4c02bb
commit e4a78c26d6
5 changed files with 51 additions and 34 deletions
@@ -489,7 +489,8 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationProvider implemen
registeredClient);
if (error.getErrorCode().equals(OAuth2ErrorCodes.INVALID_REQUEST)
&& (parameterName.equals(OAuth2ParameterNames.CLIENT_ID)
|| parameterName.equals(OAuth2ParameterNames.STATE))) {
|| parameterName.equals(OAuth2ParameterNames.STATE)
|| parameterName.equals(OAuth2ParameterNames.REQUEST_URI))) {
redirectUri = null; // Prevent redirects
}
@@ -293,8 +293,10 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationValidator
String redirectUri = StringUtils.hasText(authorizationCodeRequestAuthentication.getRedirectUri())
? authorizationCodeRequestAuthentication.getRedirectUri()
: registeredClient.getRedirectUris().iterator().next();
if (error.getErrorCode().equals(OAuth2ErrorCodes.INVALID_REQUEST)
&& parameterName.equals(OAuth2ParameterNames.REDIRECT_URI)) {
if ((error.getErrorCode().equals(OAuth2ErrorCodes.INVALID_REQUEST)
|| error.getErrorCode().equals(OAuth2ErrorCodes.UNAUTHORIZED_CLIENT))
&& (parameterName.equals(OAuth2ParameterNames.CLIENT_ID)
|| parameterName.equals(OAuth2ParameterNames.REDIRECT_URI))) {
redirectUri = null; // Prevent redirects
}
@@ -123,46 +123,60 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationConverter impleme
principal = ANONYMOUS_AUTHENTICATION;
}
// redirect_uri (OPTIONAL)
String redirectUri = parameters.getFirst(OAuth2ParameterNames.REDIRECT_URI);
if (StringUtils.hasText(redirectUri) && parameters.get(OAuth2ParameterNames.REDIRECT_URI).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.REDIRECT_URI);
String redirectUri = null;
if (!StringUtils.hasText(requestUri)) {
// redirect_uri (OPTIONAL)
redirectUri = parameters.getFirst(OAuth2ParameterNames.REDIRECT_URI);
if (StringUtils.hasText(redirectUri) && parameters.get(OAuth2ParameterNames.REDIRECT_URI).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.REDIRECT_URI);
}
}
// scope (OPTIONAL)
Set<String> scopes = null;
String scope = parameters.getFirst(OAuth2ParameterNames.SCOPE);
if (StringUtils.hasText(scope) && parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.SCOPE);
}
if (StringUtils.hasText(scope)) {
scopes = new HashSet<>(Arrays.asList(StringUtils.delimitedListToStringArray(scope, " ")));
if (!StringUtils.hasText(requestUri)) {
// scope (OPTIONAL)
String scope = parameters.getFirst(OAuth2ParameterNames.SCOPE);
if (StringUtils.hasText(scope) && parameters.get(OAuth2ParameterNames.SCOPE).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.SCOPE);
}
if (StringUtils.hasText(scope)) {
scopes = new HashSet<>(Arrays.asList(StringUtils.delimitedListToStringArray(scope, " ")));
}
}
// state (RECOMMENDED)
String state = parameters.getFirst(OAuth2ParameterNames.STATE);
if (StringUtils.hasText(state) && parameters.get(OAuth2ParameterNames.STATE).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.STATE);
String state = null;
if (!StringUtils.hasText(requestUri)) {
// state (RECOMMENDED)
state = parameters.getFirst(OAuth2ParameterNames.STATE);
if (StringUtils.hasText(state) && parameters.get(OAuth2ParameterNames.STATE).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, OAuth2ParameterNames.STATE);
}
}
// code_challenge (REQUIRED for public clients) - RFC 7636 (PKCE)
String codeChallenge = parameters.getFirst(PkceParameterNames.CODE_CHALLENGE);
if (StringUtils.hasText(codeChallenge) && parameters.get(PkceParameterNames.CODE_CHALLENGE).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, PkceParameterNames.CODE_CHALLENGE, PKCE_ERROR_URI);
if (!StringUtils.hasText(requestUri)) {
// code_challenge (REQUIRED for public clients) - RFC 7636 (PKCE)
String codeChallenge = parameters.getFirst(PkceParameterNames.CODE_CHALLENGE);
if (StringUtils.hasText(codeChallenge) && parameters.get(PkceParameterNames.CODE_CHALLENGE).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, PkceParameterNames.CODE_CHALLENGE, PKCE_ERROR_URI);
}
}
// code_challenge_method (OPTIONAL for public clients) - RFC 7636 (PKCE)
String codeChallengeMethod = parameters.getFirst(PkceParameterNames.CODE_CHALLENGE_METHOD);
if (StringUtils.hasText(codeChallengeMethod)
&& parameters.get(PkceParameterNames.CODE_CHALLENGE_METHOD).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, PkceParameterNames.CODE_CHALLENGE_METHOD, PKCE_ERROR_URI);
if (!StringUtils.hasText(requestUri)) {
// code_challenge_method (OPTIONAL for public clients) - RFC 7636 (PKCE)
String codeChallengeMethod = parameters.getFirst(PkceParameterNames.CODE_CHALLENGE_METHOD);
if (StringUtils.hasText(codeChallengeMethod)
&& parameters.get(PkceParameterNames.CODE_CHALLENGE_METHOD).size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, PkceParameterNames.CODE_CHALLENGE_METHOD, PKCE_ERROR_URI);
}
}
// prompt (OPTIONAL for OpenID Connect 1.0 Authentication Request)
if (!CollectionUtils.isEmpty(scopes) && scopes.contains(OidcScopes.OPENID)) {
String prompt = parameters.getFirst("prompt");
if (StringUtils.hasText(prompt) && parameters.get("prompt").size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, "prompt");
if (!StringUtils.hasText(requestUri)) {
// prompt (OPTIONAL for OpenID Connect 1.0 Authentication Request)
if (!CollectionUtils.isEmpty(scopes) && scopes.contains(OidcScopes.OPENID)) {
String prompt = parameters.getFirst("prompt");
if (StringUtils.hasText(prompt) && parameters.get("prompt").size() != 1) {
throwError(OAuth2ErrorCodes.INVALID_REQUEST, "prompt");
}
}
}
@@ -311,7 +311,7 @@ public class OAuth2AuthorizationCodeRequestAuthenticationProviderTests {
assertThatExceptionOfType(OAuth2AuthorizationCodeRequestAuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.satisfies((ex) -> assertAuthenticationException(ex, OAuth2ErrorCodes.UNAUTHORIZED_CLIENT,
OAuth2ParameterNames.CLIENT_ID, authentication.getRedirectUri()));
OAuth2ParameterNames.CLIENT_ID, null));
}
@Test
@@ -128,7 +128,7 @@ public class OAuth2PushedAuthorizationRequestAuthenticationProviderTests {
assertThatExceptionOfType(OAuth2AuthorizationCodeRequestAuthenticationException.class)
.isThrownBy(() -> this.authenticationProvider.authenticate(authentication))
.satisfies((ex) -> assertAuthenticationException(ex, OAuth2ErrorCodes.UNAUTHORIZED_CLIENT,
OAuth2ParameterNames.CLIENT_ID, authentication.getRedirectUri()));
OAuth2ParameterNames.CLIENT_ID, null));
}
@Test