瀏覽代碼

OAuth2AuthorizationCodeGrantWebFilter works with /{action}/

This ensures that the same URL can work for both log in and
authorization code which prevents having to create additional registrations
on the client and potentially on the server (GitHub only allows a single
valid redirect URL).

Fixes: gh-5856
Rob Winch 7 年之前
父節點
當前提交
385bdfc055

+ 1 - 0
config/src/main/java/org/springframework/security/config/web/server/SecurityWebFiltersOrder.java

@@ -48,6 +48,7 @@ public enum SecurityWebFiltersOrder {
 	 */
 	FORM_LOGIN,
 	AUTHENTICATION,
+	OAUTH2_AUTHORIZATION_CODE,
 	LOGIN_PAGE_GENERATING,
 	LOGOUT_PAGE_GENERATING,
 	/**

+ 10 - 2
config/src/main/java/org/springframework/security/config/web/server/ServerHttpSecurity.java

@@ -28,6 +28,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.springframework.security.core.context.ReactiveSecurityContextHolder;
 import reactor.core.publisher.Mono;
 import reactor.util.context.Context;
 
@@ -552,7 +553,7 @@ public class ServerHttpSecurity {
 			}
 
 			AuthenticationWebFilter authenticationFilter = new OAuth2LoginAuthenticationWebFilter(manager, authorizedClientRepository);
-			authenticationFilter.setRequiresAuthenticationMatcher(new PathPatternParserServerWebExchangeMatcher("/login/oauth2/code/{registrationId}"));
+			authenticationFilter.setRequiresAuthenticationMatcher(createAttemptAuthenticationRequestMatcher());
 			authenticationFilter.setServerAuthenticationConverter(new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter(clientRegistrationRepository));
 
 			RedirectServerAuthenticationSuccessHandler redirectHandler = new RedirectServerAuthenticationSuccessHandler();
@@ -581,6 +582,13 @@ public class ServerHttpSecurity {
 			http.addFilterAt(authenticationFilter, SecurityWebFiltersOrder.AUTHENTICATION);
 		}
 
+		private ServerWebExchangeMatcher createAttemptAuthenticationRequestMatcher() {
+			PathPatternParserServerWebExchangeMatcher loginPathMatcher = new PathPatternParserServerWebExchangeMatcher("/login/oauth2/code/{registrationId}");
+			ServerWebExchangeMatcher notAuthenticatedMatcher = e  -> ReactiveSecurityContextHolder.getContext()
+					.flatMap(p -> ServerWebExchangeMatcher.MatchResult.notMatch())
+					.switchIfEmpty(ServerWebExchangeMatcher.MatchResult.match());
+			return new AndServerWebExchangeMatcher(loginPathMatcher, notAuthenticatedMatcher);
+		}
 		private Map<String, String> getLinks() {
 			Iterable<ClientRegistration> registrations = getBeanOrNull(ResolvableType.forClassWithGenerics(Iterable.class, ClientRegistration.class));
 			if (registrations == null) {
@@ -686,7 +694,7 @@ public class ServerHttpSecurity {
 
 			OAuth2AuthorizationRequestRedirectWebFilter oauthRedirectFilter = new OAuth2AuthorizationRequestRedirectWebFilter(
 					clientRegistrationRepository);
-			http.addFilterAt(codeGrantWebFilter, SecurityWebFiltersOrder.AUTHENTICATION);
+			http.addFilterAt(codeGrantWebFilter, SecurityWebFiltersOrder.OAUTH2_AUTHORIZATION_CODE);
 			http.addFilterAt(oauthRedirectFilter, SecurityWebFiltersOrder.HTTP_BASIC);
 		}
 

+ 1 - 1
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/server/OAuth2AuthorizationCodeGrantWebFilter.java

@@ -109,7 +109,7 @@ public class OAuth2AuthorizationCodeGrantWebFilter implements WebFilter {
 		Assert.notNull(authorizedClientRepository, "authorizedClientRepository cannot be null");
 		this.authenticationManager = authenticationManager;
 		this.authorizedClientRepository = authorizedClientRepository;
-		this.requiresAuthenticationMatcher = new PathPatternParserServerWebExchangeMatcher("/authorize/oauth2/code/{registrationId}");
+		this.requiresAuthenticationMatcher = new PathPatternParserServerWebExchangeMatcher("/{action}/oauth2/code/{registrationId}");
 		this.authenticationConverter = new ServerOAuth2AuthorizationCodeAuthenticationTokenConverter(clientRegistrationRepository);
 		this.authenticationSuccessHandler = new RedirectServerAuthenticationSuccessHandler();
 		this.authenticationFailureHandler = (webFilterExchange, exception) -> Mono.error(exception);