Browse Source

Polish gh-1874

pull/1923/head
Joe Grandja 10 months ago
parent
commit
629239fde1
  1. 2
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationEndpointFilter.java
  2. 13
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AuthorizationCodeRequestAuthenticationConverter.java
  3. 20
      oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AuthorizationConsentAuthenticationConverter.java
  4. 38
      oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationEndpointFilterTests.java

2
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationEndpointFilter.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2024 the original author or authors.
* Copyright 2020-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.

13
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AuthorizationCodeRequestAuthenticationConverter.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2024 the original author or authors.
* Copyright 2020-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -38,6 +38,7 @@ import org.springframework.security.oauth2.server.authorization.authentication.O @@ -38,6 +38,7 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationEndpointFilter;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.CollectionUtils;
import org.springframework.util.MultiValueMap;
@ -64,11 +65,11 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationConverter impleme @@ -64,11 +65,11 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationConverter impleme
private static final Authentication ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken("anonymous",
"anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
private static final RequestMatcher POST_WITH_RESPONSE_TYPE_REQUEST_MATCHER = createPostWithResponseTypeRequestMatcher();
private final RequestMatcher requestMatcher = createDefaultRequestMatcher();
@Override
public Authentication convert(HttpServletRequest request) {
if (!"GET".equals(request.getMethod()) && !POST_WITH_RESPONSE_TYPE_REQUEST_MATCHER.matches(request)) {
if (!this.requestMatcher.matches(request)) {
return null;
}
@ -153,11 +154,13 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationConverter impleme @@ -153,11 +154,13 @@ public final class OAuth2AuthorizationCodeRequestAuthenticationConverter impleme
state, scopes, additionalParameters);
}
private static RequestMatcher createPostWithResponseTypeRequestMatcher() {
private static RequestMatcher createDefaultRequestMatcher() {
RequestMatcher getMethodMatcher = (request) -> "GET".equals(request.getMethod());
RequestMatcher postMethodMatcher = (request) -> "POST".equals(request.getMethod());
RequestMatcher responseTypeParameterMatcher = (
request) -> request.getParameter(OAuth2ParameterNames.RESPONSE_TYPE) != null;
return new AndRequestMatcher(postMethodMatcher, responseTypeParameterMatcher);
return new OrRequestMatcher(getMethodMatcher,
new AndRequestMatcher(postMethodMatcher, responseTypeParameterMatcher));
}
private static void throwError(String errorCode, String parameterName) {

20
oauth2-authorization-server/src/main/java/org/springframework/security/oauth2/server/authorization/web/authentication/OAuth2AuthorizationConsentAuthenticationConverter.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2023 the original author or authors.
* Copyright 2020-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -33,6 +33,9 @@ import org.springframework.security.oauth2.server.authorization.authentication.O @@ -33,6 +33,9 @@ import org.springframework.security.oauth2.server.authorization.authentication.O
import org.springframework.security.oauth2.server.authorization.authentication.OAuth2AuthorizationConsentAuthenticationToken;
import org.springframework.security.oauth2.server.authorization.web.OAuth2AuthorizationEndpointFilter;
import org.springframework.security.web.authentication.AuthenticationConverter;
import org.springframework.security.web.util.matcher.AndRequestMatcher;
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
@ -55,14 +58,16 @@ public final class OAuth2AuthorizationConsentAuthenticationConverter implements @@ -55,14 +58,16 @@ public final class OAuth2AuthorizationConsentAuthenticationConverter implements
private static final Authentication ANONYMOUS_AUTHENTICATION = new AnonymousAuthenticationToken("anonymous",
"anonymousUser", AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
private final RequestMatcher requestMatcher = createDefaultRequestMatcher();
@Override
public Authentication convert(HttpServletRequest request) {
MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getFormParameters(request);
if (!"POST".equals(request.getMethod()) || parameters.getFirst(OAuth2ParameterNames.RESPONSE_TYPE) != null) {
if (!this.requestMatcher.matches(request)) {
return null;
}
MultiValueMap<String, String> parameters = OAuth2EndpointUtils.getFormParameters(request);
String authorizationUri = request.getRequestURL().toString();
// client_id (REQUIRED)
@ -100,6 +105,13 @@ public final class OAuth2AuthorizationConsentAuthenticationConverter implements @@ -100,6 +105,13 @@ public final class OAuth2AuthorizationConsentAuthenticationConverter implements
additionalParameters);
}
private static RequestMatcher createDefaultRequestMatcher() {
RequestMatcher postMethodMatcher = (request) -> "POST".equals(request.getMethod());
RequestMatcher responseTypeParameterMatcher = (
request) -> request.getParameter(OAuth2ParameterNames.RESPONSE_TYPE) != null;
return new AndRequestMatcher(postMethodMatcher, new NegatedRequestMatcher(responseTypeParameterMatcher));
}
private static void throwError(String errorCode, String parameterName) {
OAuth2Error error = new OAuth2Error(errorCode, "OAuth 2.0 Parameter: " + parameterName, DEFAULT_ERROR_URI);
throw new OAuth2AuthorizationCodeRequestAuthenticationException(error, null);

38
oauth2-authorization-server/src/test/java/org/springframework/security/oauth2/server/authorization/web/OAuth2AuthorizationEndpointFilterTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2020-2024 the original author or authors.
* Copyright 2020-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -609,9 +609,41 @@ public class OAuth2AuthorizationEndpointFilterTests { @@ -609,9 +609,41 @@ public class OAuth2AuthorizationEndpointFilterTests {
.isEqualTo("https://example.com?param=encoded%20parameter%20value&code=code&state=client%20state");
}
@Test
public void doFilterWhenPostAuthorizationRequestAuthenticatedThenAuthorizationResponse() throws Exception {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().redirectUris((redirectUris) -> {
redirectUris.clear();
redirectUris.add("https://example.com?param=encoded%20parameter%20value");
}).build();
OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthenticationResult = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, this.authorizationCode,
registeredClient.getRedirectUris().iterator().next(), "client state", registeredClient.getScopes());
authorizationCodeRequestAuthenticationResult.setAuthenticated(true);
given(this.authenticationManager.authenticate(any())).willReturn(authorizationCodeRequestAuthenticationResult);
MockHttpServletRequest request = createAuthorizationRequest(registeredClient);
request.setMethod("POST");
request.setQueryString(null);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);
this.filter.doFilter(request, response, filterChain);
verify(this.authenticationManager).authenticate(any());
verifyNoInteractions(filterChain);
assertThat(response.getStatus()).isEqualTo(HttpStatus.FOUND.value());
assertThat(response.getRedirectedUrl())
.isEqualTo("https://example.com?param=encoded%20parameter%20value&code=code&state=client%20state");
}
@Test
public void doFilterWhenAuthenticationRequestAuthenticatedThenAuthorizationResponse() throws Exception {
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().scopes(Set::clear).build();
// Setup OpenID Connect request
RegisteredClient registeredClient = TestRegisteredClients.registeredClient().scopes((scopes) -> {
scopes.clear();
scopes.add(OidcScopes.OPENID);
}).build();
OAuth2AuthorizationCodeRequestAuthenticationToken authorizationCodeRequestAuthenticationResult = new OAuth2AuthorizationCodeRequestAuthenticationToken(
AUTHORIZATION_URI, registeredClient.getClientId(), this.principal, this.authorizationCode,
registeredClient.getRedirectUris().iterator().next(), STATE, registeredClient.getScopes());
@ -619,7 +651,7 @@ public class OAuth2AuthorizationEndpointFilterTests { @@ -619,7 +651,7 @@ public class OAuth2AuthorizationEndpointFilterTests {
given(this.authenticationManager.authenticate(any())).willReturn(authorizationCodeRequestAuthenticationResult);
MockHttpServletRequest request = createAuthorizationRequest(registeredClient);
request.setMethod("POST");
request.setMethod("POST"); // OpenID Connect supports POST method
request.setQueryString(null);
MockHttpServletResponse response = new MockHttpServletResponse();
FilterChain filterChain = mock(FilterChain.class);

Loading…
Cancel
Save