Browse Source

Polish OAuth Security Configurers

Joe Grandja 7 năm trước cách đây
mục cha
commit
6b16fa0d8c

+ 0 - 203
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/AuthorizationCodeAuthenticationFilterConfigurer.java

@@ -1,203 +0,0 @@
-/*
- * Copyright 2012-2017 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.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.config.annotation.web.configurers.oauth2.client;
-
-import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
-import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
-import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
-import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationProvider;
-import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationToken;
-import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticator;
-import org.springframework.security.oauth2.client.authentication.AuthorizationGrantAuthenticator;
-import org.springframework.security.oauth2.client.authentication.DelegatingAuthorizationGrantAuthenticator;
-import org.springframework.security.oauth2.client.authentication.OAuth2UserAuthenticationProvider;
-import org.springframework.security.oauth2.client.authentication.jwt.JwtDecoderRegistry;
-import org.springframework.security.oauth2.client.authentication.jwt.nimbus.NimbusJwtDecoderRegistry;
-import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
-import org.springframework.security.oauth2.client.token.SecurityTokenRepository;
-import org.springframework.security.oauth2.client.user.CustomUserTypesOAuth2UserService;
-import org.springframework.security.oauth2.client.user.DefaultOAuth2UserService;
-import org.springframework.security.oauth2.client.user.DelegatingOAuth2UserService;
-import org.springframework.security.oauth2.client.user.OAuth2UserService;
-import org.springframework.security.oauth2.client.web.AuthorizationCodeAuthenticationFilter;
-import org.springframework.security.oauth2.client.web.AuthorizationGrantTokenExchanger;
-import org.springframework.security.oauth2.client.web.nimbus.NimbusAuthorizationCodeTokenExchanger;
-import org.springframework.security.oauth2.core.AccessToken;
-import org.springframework.security.oauth2.core.user.OAuth2User;
-import org.springframework.security.oauth2.oidc.client.authentication.OidcAuthorizationCodeAuthenticator;
-import org.springframework.security.oauth2.oidc.client.user.OidcUserService;
-import org.springframework.security.web.util.matcher.RequestMatcher;
-import org.springframework.util.Assert;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * @author Joe Grandja
- */
-final class AuthorizationCodeAuthenticationFilterConfigurer<H extends HttpSecurityBuilder<H>, R extends RequestMatcher> extends
-		AbstractAuthenticationFilterConfigurer<H, AuthorizationCodeAuthenticationFilterConfigurer<H, R>, AuthorizationCodeAuthenticationFilter> {
-
-	private R authorizationResponseMatcher;
-	private AuthorizationGrantAuthenticator<AuthorizationCodeAuthenticationToken> authorizationCodeAuthenticator;
-	private AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger;
-	private SecurityTokenRepository<AccessToken> accessTokenRepository;
-	private JwtDecoderRegistry jwtDecoderRegistry;
-	private OAuth2UserService userInfoService;
-	private Map<URI, Class<? extends OAuth2User>> customUserTypes = new HashMap<>();
-	private GrantedAuthoritiesMapper userAuthoritiesMapper;
-
-	AuthorizationCodeAuthenticationFilterConfigurer() {
-		super(new AuthorizationCodeAuthenticationFilter(), null);
-	}
-
-	AuthorizationCodeAuthenticationFilterConfigurer<H, R> authorizationResponseMatcher(R authorizationResponseMatcher) {
-		Assert.notNull(authorizationResponseMatcher, "authorizationResponseMatcher cannot be null");
-		this.authorizationResponseMatcher = authorizationResponseMatcher;
-		return this;
-	}
-
-	AuthorizationCodeAuthenticationFilterConfigurer<H, R> authorizationCodeTokenExchanger(
-			AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger) {
-
-		Assert.notNull(authorizationCodeTokenExchanger, "authorizationCodeTokenExchanger cannot be null");
-		this.authorizationCodeTokenExchanger = authorizationCodeTokenExchanger;
-		return this;
-	}
-
-	AuthorizationCodeAuthenticationFilterConfigurer<H, R> accessTokenRepository(SecurityTokenRepository<AccessToken> accessTokenRepository) {
-		Assert.notNull(accessTokenRepository, "accessTokenRepository cannot be null");
-		this.accessTokenRepository = accessTokenRepository;
-		return this;
-	}
-
-	AuthorizationCodeAuthenticationFilterConfigurer<H, R> jwtDecoderRegistry(JwtDecoderRegistry jwtDecoderRegistry) {
-		Assert.notNull(jwtDecoderRegistry, "jwtDecoderRegistry cannot be null");
-		this.jwtDecoderRegistry = jwtDecoderRegistry;
-		return this;
-	}
-
-	AuthorizationCodeAuthenticationFilterConfigurer<H, R> userInfoService(OAuth2UserService userInfoService) {
-		Assert.notNull(userInfoService, "userInfoService cannot be null");
-		this.userInfoService = userInfoService;
-		return this;
-	}
-
-	AuthorizationCodeAuthenticationFilterConfigurer<H, R> customUserType(Class<? extends OAuth2User> customUserType, URI userInfoUri) {
-		Assert.notNull(customUserType, "customUserType cannot be null");
-		Assert.notNull(userInfoUri, "userInfoUri cannot be null");
-		this.customUserTypes.put(userInfoUri, customUserType);
-		return this;
-	}
-
-	AuthorizationCodeAuthenticationFilterConfigurer<H, R> userAuthoritiesMapper(GrantedAuthoritiesMapper userAuthoritiesMapper) {
-		Assert.notNull(userAuthoritiesMapper, "userAuthoritiesMapper cannot be null");
-		this.userAuthoritiesMapper = userAuthoritiesMapper;
-		return this;
-	}
-
-	AuthorizationCodeAuthenticationFilterConfigurer<H, R> clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) {
-		Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
-		this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
-		return this;
-	}
-
-	String getLoginUrl() {
-		return super.getLoginPage();
-	}
-
-	String getLoginFailureUrl() {
-		return super.getFailureUrl();
-	}
-
-	@Override
-	public void init(H http) throws Exception {
-		AuthorizationCodeAuthenticationProvider authorizationCodeAuthenticationProvider =
-			new AuthorizationCodeAuthenticationProvider(this.getAuthorizationCodeAuthenticator());
-		if (this.accessTokenRepository != null) {
-			authorizationCodeAuthenticationProvider.setAccessTokenRepository(this.accessTokenRepository);
-		}
-		authorizationCodeAuthenticationProvider = this.postProcess(authorizationCodeAuthenticationProvider);
-		http.authenticationProvider(authorizationCodeAuthenticationProvider);
-
-		OAuth2UserAuthenticationProvider oauth2UserAuthenticationProvider =
-			new OAuth2UserAuthenticationProvider(this.getUserInfoService());
-		if (this.userAuthoritiesMapper != null) {
-			oauth2UserAuthenticationProvider.setAuthoritiesMapper(this.userAuthoritiesMapper);
-		}
-		oauth2UserAuthenticationProvider = this.postProcess(oauth2UserAuthenticationProvider);
-		http.authenticationProvider(oauth2UserAuthenticationProvider);
-
-		super.init(http);
-	}
-
-	@Override
-	public void configure(H http) throws Exception {
-		AuthorizationCodeAuthenticationFilter authFilter = this.getAuthenticationFilter();
-		if (this.authorizationResponseMatcher != null) {
-			authFilter.setAuthorizationResponseMatcher(this.authorizationResponseMatcher);
-		}
-		authFilter.setClientRegistrationRepository(OAuth2LoginConfigurer.getClientRegistrationRepository(this.getBuilder()));
-		super.configure(http);
-	}
-
-	@Override
-	protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
-		return (this.authorizationResponseMatcher != null ?
-			this.authorizationResponseMatcher : this.getAuthenticationFilter().getAuthorizationResponseMatcher());
-	}
-
-	private AuthorizationGrantAuthenticator<AuthorizationCodeAuthenticationToken> getAuthorizationCodeAuthenticator() {
-		if (this.authorizationCodeAuthenticator == null) {
-			List<AuthorizationGrantAuthenticator<AuthorizationCodeAuthenticationToken>> authenticators = new ArrayList<>();
-			authenticators.add(new AuthorizationCodeAuthenticator(this.getAuthorizationCodeTokenExchanger()));
-			authenticators.add(new OidcAuthorizationCodeAuthenticator(
-				this.getAuthorizationCodeTokenExchanger(), this.getJwtDecoderRegistry()));
-			this.authorizationCodeAuthenticator = new DelegatingAuthorizationGrantAuthenticator<>(authenticators);;
-		}
-		return this.authorizationCodeAuthenticator;
-	}
-
-	private AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> getAuthorizationCodeTokenExchanger() {
-		if (this.authorizationCodeTokenExchanger == null) {
-			this.authorizationCodeTokenExchanger = new NimbusAuthorizationCodeTokenExchanger();
-		}
-		return this.authorizationCodeTokenExchanger;
-	}
-
-	private JwtDecoderRegistry getJwtDecoderRegistry() {
-		if (this.jwtDecoderRegistry == null) {
-			this.jwtDecoderRegistry = new NimbusJwtDecoderRegistry();
-		}
-		return this.jwtDecoderRegistry;
-	}
-
-	private OAuth2UserService getUserInfoService() {
-		if (this.userInfoService == null) {
-			List<OAuth2UserService> oauth2UserServices = new ArrayList<>();
-			oauth2UserServices.add(new DefaultOAuth2UserService());
-			oauth2UserServices.add(new OidcUserService());
-			if (!this.customUserTypes.isEmpty()) {
-				oauth2UserServices.add(new CustomUserTypesOAuth2UserService(this.customUserTypes));
-			}
-			this.userInfoService = new DelegatingOAuth2UserService(oauth2UserServices);
-		}
-		return this.userInfoService;
-	}
-}

+ 290 - 0
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/AuthorizationCodeGrantConfigurer.java

@@ -0,0 +1,290 @@
+/*
+ * Copyright 2012-2017 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.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.security.config.annotation.web.configurers.oauth2.client;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
+import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
+import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationProvider;
+import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationToken;
+import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticator;
+import org.springframework.security.oauth2.client.authentication.AuthorizationGrantAuthenticator;
+import org.springframework.security.oauth2.client.authentication.DelegatingAuthorizationGrantAuthenticator;
+import org.springframework.security.oauth2.client.authentication.OAuth2UserAuthenticationProvider;
+import org.springframework.security.oauth2.client.authentication.jwt.JwtDecoderRegistry;
+import org.springframework.security.oauth2.client.authentication.jwt.nimbus.NimbusJwtDecoderRegistry;
+import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
+import org.springframework.security.oauth2.client.token.SecurityTokenRepository;
+import org.springframework.security.oauth2.client.user.CustomUserTypesOAuth2UserService;
+import org.springframework.security.oauth2.client.user.DefaultOAuth2UserService;
+import org.springframework.security.oauth2.client.user.DelegatingOAuth2UserService;
+import org.springframework.security.oauth2.client.user.OAuth2UserService;
+import org.springframework.security.oauth2.client.web.AuthorizationCodeAuthenticationFilter;
+import org.springframework.security.oauth2.client.web.AuthorizationCodeRequestRedirectFilter;
+import org.springframework.security.oauth2.client.web.AuthorizationGrantTokenExchanger;
+import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
+import org.springframework.security.oauth2.client.web.AuthorizationRequestUriBuilder;
+import org.springframework.security.oauth2.client.web.nimbus.NimbusAuthorizationCodeTokenExchanger;
+import org.springframework.security.oauth2.core.AccessToken;
+import org.springframework.security.oauth2.core.user.OAuth2User;
+import org.springframework.security.oauth2.oidc.client.authentication.OidcAuthorizationCodeAuthenticator;
+import org.springframework.security.oauth2.oidc.client.user.OidcUserService;
+import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
+import org.springframework.security.web.util.matcher.RequestMatcher;
+import org.springframework.util.Assert;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A security configurer for the Authorization Code Grant type.
+ *
+ * @author Joe Grandja
+ * @since 5.0
+ */
+public class AuthorizationCodeGrantConfigurer<B extends HttpSecurityBuilder<B>> extends
+	AbstractHttpConfigurer<AuthorizationCodeGrantConfigurer<B>, B> {
+
+	// ***** Authorization Request members
+	private AuthorizationCodeRequestRedirectFilter authorizationRequestFilter;
+	private RequestMatcher authorizationRequestMatcher;
+	private AuthorizationRequestUriBuilder authorizationRequestBuilder;
+	private AuthorizationRequestRepository authorizationRequestRepository;
+
+	// ***** Authorization Response members
+	private AuthorizationCodeAuthenticationFilter authorizationResponseFilter;
+	private RequestMatcher authorizationResponseMatcher;
+	private AuthorizationGrantAuthenticator<AuthorizationCodeAuthenticationToken> authorizationCodeAuthenticator;
+	private AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger;
+	private SecurityTokenRepository<AccessToken> accessTokenRepository;
+	private JwtDecoderRegistry jwtDecoderRegistry;
+	private OAuth2UserService userService;
+	private Map<URI, Class<? extends OAuth2User>> customUserTypes = new HashMap<>();
+	private GrantedAuthoritiesMapper userAuthoritiesMapper;
+
+	public AuthorizationCodeGrantConfigurer<B> authorizationRequestMatcher(RequestMatcher authorizationRequestMatcher) {
+		Assert.notNull(authorizationRequestMatcher, "authorizationRequestMatcher cannot be null");
+		this.authorizationRequestMatcher = authorizationRequestMatcher;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> authorizationRequestBuilder(AuthorizationRequestUriBuilder authorizationRequestBuilder) {
+		Assert.notNull(authorizationRequestBuilder, "authorizationRequestBuilder cannot be null");
+		this.authorizationRequestBuilder = authorizationRequestBuilder;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> authorizationRequestRepository(AuthorizationRequestRepository authorizationRequestRepository) {
+		Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null");
+		this.authorizationRequestRepository = authorizationRequestRepository;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> authorizationResponseMatcher(RequestMatcher authorizationResponseMatcher) {
+		Assert.notNull(authorizationResponseMatcher, "authorizationResponseMatcher cannot be null");
+		this.authorizationResponseMatcher = authorizationResponseMatcher;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> authorizationCodeAuthenticator(
+		AuthorizationGrantAuthenticator<AuthorizationCodeAuthenticationToken> authorizationCodeAuthenticator) {
+
+		Assert.notNull(authorizationCodeAuthenticator, "authorizationCodeAuthenticator cannot be null");
+		this.authorizationCodeAuthenticator = authorizationCodeAuthenticator;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> authorizationCodeTokenExchanger(
+		AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger) {
+
+		Assert.notNull(authorizationCodeTokenExchanger, "authorizationCodeTokenExchanger cannot be null");
+		this.authorizationCodeTokenExchanger = authorizationCodeTokenExchanger;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> accessTokenRepository(SecurityTokenRepository<AccessToken> accessTokenRepository) {
+		Assert.notNull(accessTokenRepository, "accessTokenRepository cannot be null");
+		this.accessTokenRepository = accessTokenRepository;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> jwtDecoderRegistry(JwtDecoderRegistry jwtDecoderRegistry) {
+		Assert.notNull(jwtDecoderRegistry, "jwtDecoderRegistry cannot be null");
+		this.jwtDecoderRegistry = jwtDecoderRegistry;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> userService(OAuth2UserService userService) {
+		Assert.notNull(userService, "userService cannot be null");
+		this.userService = userService;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> customUserType(Class<? extends OAuth2User> customUserType, URI userInfoUri) {
+		Assert.notNull(customUserType, "customUserType cannot be null");
+		Assert.notNull(userInfoUri, "userInfoUri cannot be null");
+		this.customUserTypes.put(userInfoUri, customUserType);
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> userAuthoritiesMapper(GrantedAuthoritiesMapper userAuthoritiesMapper) {
+		Assert.notNull(userAuthoritiesMapper, "userAuthoritiesMapper cannot be null");
+		this.userAuthoritiesMapper = userAuthoritiesMapper;
+		return this;
+	}
+
+	public AuthorizationCodeGrantConfigurer<B> clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) {
+		Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
+		this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
+		return this;
+	}
+
+	@Override
+	public final void init(B http) throws Exception {
+		// *****************************************
+		// ***** Initialize AuthenticationProvider's
+		//
+		// 	-> AuthorizationCodeAuthenticationProvider
+		AuthorizationCodeAuthenticationProvider authorizationCodeAuthenticationProvider =
+			new AuthorizationCodeAuthenticationProvider(this.getAuthorizationCodeAuthenticator());
+		if (this.accessTokenRepository != null) {
+			authorizationCodeAuthenticationProvider.setAccessTokenRepository(this.accessTokenRepository);
+		}
+		http.authenticationProvider(this.postProcess(authorizationCodeAuthenticationProvider));
+
+		// 	-> OAuth2UserAuthenticationProvider
+		OAuth2UserAuthenticationProvider oauth2UserAuthenticationProvider =
+			new OAuth2UserAuthenticationProvider(this.getUserService());
+		if (this.userAuthoritiesMapper != null) {
+			oauth2UserAuthenticationProvider.setAuthoritiesMapper(this.userAuthoritiesMapper);
+		}
+		http.authenticationProvider(this.postProcess(oauth2UserAuthenticationProvider));
+
+		// *************************
+		// ***** Initialize Filter's
+		//
+		// 	-> AuthorizationCodeRequestRedirectFilter
+		this.authorizationRequestFilter = new AuthorizationCodeRequestRedirectFilter(
+			this.getClientRegistrationRepository());
+		if (this.authorizationRequestMatcher != null) {
+			this.authorizationRequestFilter.setAuthorizationRequestMatcher(this.authorizationRequestMatcher);
+		}
+		if (this.authorizationRequestBuilder != null) {
+			this.authorizationRequestFilter.setAuthorizationUriBuilder(this.authorizationRequestBuilder);
+		}
+		if (this.authorizationRequestRepository != null) {
+			this.authorizationRequestFilter.setAuthorizationRequestRepository(this.authorizationRequestRepository);
+		}
+
+		// 	-> AuthorizationCodeAuthenticationFilter
+		this.authorizationResponseFilter = new AuthorizationCodeAuthenticationFilter();
+		this.authorizationResponseFilter.setClientRegistrationRepository(this.getClientRegistrationRepository());
+		if (this.authorizationResponseMatcher != null) {
+			this.authorizationResponseFilter.setAuthorizationResponseMatcher(this.authorizationResponseMatcher);
+		}
+		if (this.authorizationRequestRepository != null) {
+			this.authorizationResponseFilter.setAuthorizationRequestRepository(this.authorizationRequestRepository);
+		}
+	}
+
+	@Override
+	public void configure(B http) throws Exception {
+		http.addFilter(this.postProcess(this.authorizationRequestFilter));
+
+		this.authorizationResponseFilter.setAuthenticationManager(http.getSharedObject(AuthenticationManager.class));
+		SessionAuthenticationStrategy sessionAuthenticationStrategy = http.getSharedObject(SessionAuthenticationStrategy.class);
+		if (sessionAuthenticationStrategy != null) {
+			this.authorizationResponseFilter.setSessionAuthenticationStrategy(sessionAuthenticationStrategy);
+		}
+		http.addFilter(this.postProcess(this.authorizationResponseFilter));
+	}
+
+	AuthorizationCodeRequestRedirectFilter getAuthorizationRequestFilter() {
+		return this.authorizationRequestFilter;
+	}
+
+	RequestMatcher getAuthorizationRequestMatcher() {
+		return this.authorizationRequestMatcher;
+	}
+
+	AuthorizationCodeAuthenticationFilter getAuthorizationResponseFilter() {
+		return this.authorizationResponseFilter;
+	}
+
+	RequestMatcher getAuthorizationResponseMatcher() {
+		return this.authorizationResponseMatcher;
+	}
+
+	AuthorizationRequestRepository getAuthorizationRequestRepository() {
+		return this.authorizationRequestRepository;
+	}
+
+	private AuthorizationGrantAuthenticator<AuthorizationCodeAuthenticationToken> getAuthorizationCodeAuthenticator() {
+		if (this.authorizationCodeAuthenticator == null) {
+			List<AuthorizationGrantAuthenticator<AuthorizationCodeAuthenticationToken>> authenticators = new ArrayList<>();
+			authenticators.add(new AuthorizationCodeAuthenticator(this.getAuthorizationCodeTokenExchanger()));
+			authenticators.add(new OidcAuthorizationCodeAuthenticator(
+				this.getAuthorizationCodeTokenExchanger(), this.getJwtDecoderRegistry()));
+			this.authorizationCodeAuthenticator = new DelegatingAuthorizationGrantAuthenticator<>(authenticators);;
+		}
+		return this.authorizationCodeAuthenticator;
+	}
+
+	private AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> getAuthorizationCodeTokenExchanger() {
+		if (this.authorizationCodeTokenExchanger == null) {
+			this.authorizationCodeTokenExchanger = new NimbusAuthorizationCodeTokenExchanger();
+		}
+		return this.authorizationCodeTokenExchanger;
+	}
+
+	private JwtDecoderRegistry getJwtDecoderRegistry() {
+		if (this.jwtDecoderRegistry == null) {
+			this.jwtDecoderRegistry = new NimbusJwtDecoderRegistry();
+		}
+		return this.jwtDecoderRegistry;
+	}
+
+	private OAuth2UserService getUserService() {
+		if (this.userService == null) {
+			List<OAuth2UserService> userServices = new ArrayList<>();
+			userServices.add(new DefaultOAuth2UserService());
+			userServices.add(new OidcUserService());
+			if (!this.customUserTypes.isEmpty()) {
+				userServices.add(new CustomUserTypesOAuth2UserService(this.customUserTypes));
+			}
+			this.userService = new DelegatingOAuth2UserService(userServices);
+		}
+		return this.userService;
+	}
+
+	private ClientRegistrationRepository getClientRegistrationRepository() {
+		ClientRegistrationRepository clientRegistrationRepository = this.getBuilder().getSharedObject(ClientRegistrationRepository.class);
+		if (clientRegistrationRepository == null) {
+			clientRegistrationRepository = this.getClientRegistrationRepositoryBean();
+			this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
+		}
+		return clientRegistrationRepository;
+	}
+
+	private ClientRegistrationRepository getClientRegistrationRepositoryBean() {
+		return this.getBuilder().getSharedObject(ApplicationContext.class).getBean(ClientRegistrationRepository.class);
+	}
+}

+ 0 - 78
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/AuthorizationCodeRequestRedirectFilterConfigurer.java

@@ -1,78 +0,0 @@
-/*
- * Copyright 2012-2017 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.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.security.config.annotation.web.configurers.oauth2.client;
-
-import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
-import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
-import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
-import org.springframework.security.oauth2.client.web.AuthorizationCodeRequestRedirectFilter;
-import org.springframework.security.oauth2.client.web.AuthorizationRequestUriBuilder;
-import org.springframework.security.oauth2.client.web.DefaultAuthorizationRequestUriBuilder;
-import org.springframework.security.web.util.matcher.RequestMatcher;
-import org.springframework.security.web.util.matcher.RequestVariablesExtractor;
-import org.springframework.util.Assert;
-
-/**
- * @author Joe Grandja
- */
-final class AuthorizationCodeRequestRedirectFilterConfigurer<H extends HttpSecurityBuilder<H>, R extends RequestMatcher & RequestVariablesExtractor> extends
-		AbstractHttpConfigurer<AuthorizationCodeRequestRedirectFilterConfigurer<H, R>, H> {
-
-	private R authorizationRequestMatcher;
-	private AuthorizationRequestUriBuilder authorizationRequestBuilder;
-
-	AuthorizationCodeRequestRedirectFilterConfigurer<H, R> authorizationRequestMatcher(R authorizationRequestMatcher) {
-		Assert.notNull(authorizationRequestMatcher, "authorizationRequestMatcher cannot be null");
-		this.authorizationRequestMatcher = authorizationRequestMatcher;
-		return this;
-	}
-
-	AuthorizationCodeRequestRedirectFilterConfigurer<H, R> authorizationRequestBuilder(AuthorizationRequestUriBuilder authorizationRequestBuilder) {
-		Assert.notNull(authorizationRequestBuilder, "authorizationRequestBuilder cannot be null");
-		this.authorizationRequestBuilder = authorizationRequestBuilder;
-		return this;
-	}
-
-	AuthorizationCodeRequestRedirectFilterConfigurer<H, R> clientRegistrationRepository(ClientRegistrationRepository clientRegistrationRepository) {
-		Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
-		this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
-		return this;
-	}
-
-	R getAuthorizationRequestMatcher() {
-		return this.authorizationRequestMatcher;
-	}
-
-	@Override
-	public void configure(H http) throws Exception {
-		AuthorizationCodeRequestRedirectFilter filter = new AuthorizationCodeRequestRedirectFilter(
-				OAuth2LoginConfigurer.getClientRegistrationRepository(this.getBuilder()));
-		if (this.authorizationRequestMatcher != null) {
-			filter.setAuthorizationRequestMatcher(this.authorizationRequestMatcher);
-		}
-		if (this.authorizationRequestBuilder != null) {
-			filter.setAuthorizationUriBuilder(this.authorizationRequestBuilder);
-		}
-		http.addFilter(this.postProcess(filter));
-	}
-
-	private AuthorizationRequestUriBuilder getAuthorizationRequestBuilder() {
-		if (this.authorizationRequestBuilder == null) {
-			this.authorizationRequestBuilder = new DefaultAuthorizationRequestUriBuilder();
-		}
-		return this.authorizationRequestBuilder;
-	}
-}

+ 103 - 83
config/src/main/java/org/springframework/security/config/annotation/web/configurers/oauth2/client/OAuth2LoginConfigurer.java

@@ -18,86 +18,64 @@ package org.springframework.security.config.annotation.web.configurers.oauth2.cl
 import org.springframework.context.ApplicationContext;
 import org.springframework.core.ResolvableType;
 import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
-import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
+import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
 import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
 import org.springframework.security.oauth2.client.authentication.AuthorizationCodeAuthenticationToken;
+import org.springframework.security.oauth2.client.authentication.AuthorizationGrantAuthenticator;
 import org.springframework.security.oauth2.client.registration.ClientRegistration;
 import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
 import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
 import org.springframework.security.oauth2.client.token.SecurityTokenRepository;
 import org.springframework.security.oauth2.client.user.OAuth2UserService;
+import org.springframework.security.oauth2.client.web.AuthorizationCodeAuthenticationFilter;
 import org.springframework.security.oauth2.client.web.AuthorizationCodeRequestRedirectFilter;
 import org.springframework.security.oauth2.client.web.AuthorizationGrantTokenExchanger;
+import org.springframework.security.oauth2.client.web.AuthorizationRequestRepository;
 import org.springframework.security.oauth2.client.web.AuthorizationRequestUriBuilder;
 import org.springframework.security.oauth2.core.AccessToken;
 import org.springframework.security.oauth2.core.user.OAuth2User;
-import org.springframework.security.web.authentication.AuthenticationFailureHandler;
-import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
 import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
 import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
 import org.springframework.security.web.util.matcher.RequestMatcher;
-import org.springframework.security.web.util.matcher.RequestVariablesExtractor;
 import org.springframework.util.Assert;
 
 import java.net.URI;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.stream.Stream;
 
 import static org.springframework.security.oauth2.client.web.AuthorizationCodeRequestRedirectFilter.REGISTRATION_ID_URI_VARIABLE_NAME;
 
 /**
+ * A security configurer for OAuth 2.0 / OpenID Connect 1.0 login.
+ *
  * @author Joe Grandja
+ * @since 5.0
  */
-public final class OAuth2LoginConfigurer<H extends HttpSecurityBuilder<H>> extends
-		AbstractHttpConfigurer<OAuth2LoginConfigurer<H>, H> {
+public final class OAuth2LoginConfigurer<B extends HttpSecurityBuilder<B>> extends
+	AbstractAuthenticationFilterConfigurer<B, OAuth2LoginConfigurer<B>, AuthorizationCodeAuthenticationFilter> {
 
-	private final AuthorizationCodeRequestRedirectFilterConfigurer authorizationCodeRequestRedirectFilterConfigurer;
-	private final AuthorizationCodeAuthenticationFilterConfigurer authorizationCodeAuthenticationFilterConfigurer;
-	private final AuthorizationEndpointConfig authorizationEndpointConfig;
-	private final TokenEndpointConfig tokenEndpointConfig;
-	private final RedirectionEndpointConfig redirectionEndpointConfig;
-	private final UserInfoEndpointConfig userInfoEndpointConfig;
+	private final AuthorizationCodeGrantConfigurer<B> authorizationCodeGrantConfigurer = new AuthorizationCodeGrantLoginConfigurer();
+	private final AuthorizationEndpointConfig authorizationEndpointConfig = new AuthorizationEndpointConfig();
+	private final TokenEndpointConfig tokenEndpointConfig = new TokenEndpointConfig();
+	private final RedirectionEndpointConfig redirectionEndpointConfig = new RedirectionEndpointConfig();
+	private final UserInfoEndpointConfig userInfoEndpointConfig = new UserInfoEndpointConfig();
 
 	public OAuth2LoginConfigurer() {
-		this.authorizationCodeRequestRedirectFilterConfigurer = new AuthorizationCodeRequestRedirectFilterConfigurer<>();
-		this.authorizationCodeAuthenticationFilterConfigurer = new AuthorizationCodeAuthenticationFilterConfigurer<>();
-		this.authorizationEndpointConfig = new AuthorizationEndpointConfig();
-		this.tokenEndpointConfig = new TokenEndpointConfig();
-		this.redirectionEndpointConfig = new RedirectionEndpointConfig();
-		this.userInfoEndpointConfig = new UserInfoEndpointConfig();
+		super(new AuthorizationCodeAuthenticationFilter(), null);
 	}
 
-	public OAuth2LoginConfigurer<H> clients(ClientRegistration... clientRegistrations) {
+	public OAuth2LoginConfigurer<B> clients(ClientRegistration... clientRegistrations) {
 		Assert.notEmpty(clientRegistrations, "clientRegistrations cannot be empty");
 		return this.clients(new InMemoryClientRegistrationRepository(Arrays.asList(clientRegistrations)));
 	}
 
-	public OAuth2LoginConfigurer<H> clients(ClientRegistrationRepository clientRegistrationRepository) {
+	public OAuth2LoginConfigurer<B> clients(ClientRegistrationRepository clientRegistrationRepository) {
 		Assert.notNull(clientRegistrationRepository, "clientRegistrationRepository cannot be null");
 		this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
 		return this;
 	}
 
-	public OAuth2LoginConfigurer<H> userAuthoritiesMapper(GrantedAuthoritiesMapper userAuthoritiesMapper) {
-		Assert.notNull(userAuthoritiesMapper, "userAuthoritiesMapper cannot be null");
-		this.authorizationCodeAuthenticationFilterConfigurer.userAuthoritiesMapper(userAuthoritiesMapper);
-		return this;
-	}
-
-	public OAuth2LoginConfigurer<H> successHandler(AuthenticationSuccessHandler authenticationSuccessHandler) {
-		Assert.notNull(authenticationSuccessHandler, "authenticationSuccessHandler cannot be null");
-		this.authorizationCodeAuthenticationFilterConfigurer.successHandler(authenticationSuccessHandler);
-		return this;
-	}
-
-	public OAuth2LoginConfigurer<H> failureHandler(AuthenticationFailureHandler authenticationFailureHandler) {
-		Assert.notNull(authenticationFailureHandler, "authenticationFailureHandler cannot be null");
-		this.authorizationCodeAuthenticationFilterConfigurer.failureHandler(authenticationFailureHandler);
-		return this;
-	}
-
 	public AuthorizationEndpointConfig authorizationEndpoint() {
 		return this.authorizationEndpointConfig;
 	}
@@ -107,19 +85,25 @@ public final class OAuth2LoginConfigurer<H extends HttpSecurityBuilder<H>> exten
 		private AuthorizationEndpointConfig() {
 		}
 
+		public AuthorizationEndpointConfig requestMatcher(RequestMatcher authorizationRequestMatcher) {
+			Assert.notNull(authorizationRequestMatcher, "authorizationRequestMatcher cannot be null");
+			authorizationCodeGrantConfigurer.authorizationRequestMatcher(authorizationRequestMatcher);
+			return this;
+		}
+
 		public AuthorizationEndpointConfig authorizationRequestBuilder(AuthorizationRequestUriBuilder authorizationRequestBuilder) {
 			Assert.notNull(authorizationRequestBuilder, "authorizationRequestBuilder cannot be null");
-			OAuth2LoginConfigurer.this.authorizationCodeRequestRedirectFilterConfigurer.authorizationRequestBuilder(authorizationRequestBuilder);
+			authorizationCodeGrantConfigurer.authorizationRequestBuilder(authorizationRequestBuilder);
 			return this;
 		}
 
-		public <R extends RequestMatcher & RequestVariablesExtractor> AuthorizationEndpointConfig requestMatcher(R authorizationRequestMatcher) {
-			Assert.notNull(authorizationRequestMatcher, "authorizationRequestMatcher cannot be null");
-			OAuth2LoginConfigurer.this.authorizationCodeRequestRedirectFilterConfigurer.authorizationRequestMatcher(authorizationRequestMatcher);
+		public AuthorizationEndpointConfig authorizationRequestRepository(AuthorizationRequestRepository authorizationRequestRepository) {
+			Assert.notNull(authorizationRequestRepository, "authorizationRequestRepository cannot be null");
+			authorizationCodeGrantConfigurer.authorizationRequestRepository(authorizationRequestRepository);
 			return this;
 		}
 
-		public OAuth2LoginConfigurer<H> and() {
+		public OAuth2LoginConfigurer<B> and() {
 			return OAuth2LoginConfigurer.this;
 		}
 	}
@@ -133,21 +117,29 @@ public final class OAuth2LoginConfigurer<H extends HttpSecurityBuilder<H>> exten
 		private TokenEndpointConfig() {
 		}
 
+		public TokenEndpointConfig authorizationCodeAuthenticator(
+			AuthorizationGrantAuthenticator<AuthorizationCodeAuthenticationToken> authorizationCodeAuthenticator) {
+
+			Assert.notNull(authorizationCodeAuthenticator, "authorizationCodeAuthenticator cannot be null");
+			authorizationCodeGrantConfigurer.authorizationCodeAuthenticator(authorizationCodeAuthenticator);
+			return this;
+		}
+
 		public TokenEndpointConfig authorizationCodeTokenExchanger(
 			AuthorizationGrantTokenExchanger<AuthorizationCodeAuthenticationToken> authorizationCodeTokenExchanger) {
 
 			Assert.notNull(authorizationCodeTokenExchanger, "authorizationCodeTokenExchanger cannot be null");
-			OAuth2LoginConfigurer.this.authorizationCodeAuthenticationFilterConfigurer.authorizationCodeTokenExchanger(authorizationCodeTokenExchanger);
+			authorizationCodeGrantConfigurer.authorizationCodeTokenExchanger(authorizationCodeTokenExchanger);
 			return this;
 		}
 
 		public TokenEndpointConfig accessTokenRepository(SecurityTokenRepository<AccessToken> accessTokenRepository) {
 			Assert.notNull(accessTokenRepository, "accessTokenRepository cannot be null");
-			OAuth2LoginConfigurer.this.authorizationCodeAuthenticationFilterConfigurer.accessTokenRepository(accessTokenRepository);
+			authorizationCodeGrantConfigurer.accessTokenRepository(accessTokenRepository);
 			return this;
 		}
 
-		public OAuth2LoginConfigurer<H> and() {
+		public OAuth2LoginConfigurer<B> and() {
 			return OAuth2LoginConfigurer.this;
 		}
 	}
@@ -161,13 +153,13 @@ public final class OAuth2LoginConfigurer<H extends HttpSecurityBuilder<H>> exten
 		private RedirectionEndpointConfig() {
 		}
 
-		public <R extends RequestMatcher> RedirectionEndpointConfig requestMatcher(R authorizationResponseMatcher) {
+		public RedirectionEndpointConfig requestMatcher(RequestMatcher authorizationResponseMatcher) {
 			Assert.notNull(authorizationResponseMatcher, "authorizationResponseMatcher cannot be null");
-			OAuth2LoginConfigurer.this.authorizationCodeAuthenticationFilterConfigurer.authorizationResponseMatcher(authorizationResponseMatcher);
+			authorizationCodeGrantConfigurer.authorizationResponseMatcher(authorizationResponseMatcher);
 			return this;
 		}
 
-		public OAuth2LoginConfigurer<H> and() {
+		public OAuth2LoginConfigurer<B> and() {
 			return OAuth2LoginConfigurer.this;
 		}
 	}
@@ -181,73 +173,82 @@ public final class OAuth2LoginConfigurer<H extends HttpSecurityBuilder<H>> exten
 		private UserInfoEndpointConfig() {
 		}
 
-		public UserInfoEndpointConfig userInfoService(OAuth2UserService userInfoService) {
-			Assert.notNull(userInfoService, "userInfoService cannot be null");
-			OAuth2LoginConfigurer.this.authorizationCodeAuthenticationFilterConfigurer.userInfoService(userInfoService);
+		public UserInfoEndpointConfig userService(OAuth2UserService userService) {
+			Assert.notNull(userService, "userService cannot be null");
+			authorizationCodeGrantConfigurer.userService(userService);
 			return this;
 		}
 
 		public UserInfoEndpointConfig customUserType(Class<? extends OAuth2User> customUserType, URI userInfoUri) {
 			Assert.notNull(customUserType, "customUserType cannot be null");
 			Assert.notNull(userInfoUri, "userInfoUri cannot be null");
-			OAuth2LoginConfigurer.this.authorizationCodeAuthenticationFilterConfigurer.customUserType(customUserType, userInfoUri);
+			authorizationCodeGrantConfigurer.customUserType(customUserType, userInfoUri);
+			return this;
+		}
+
+		public UserInfoEndpointConfig userAuthoritiesMapper(GrantedAuthoritiesMapper userAuthoritiesMapper) {
+			Assert.notNull(userAuthoritiesMapper, "userAuthoritiesMapper cannot be null");
+			authorizationCodeGrantConfigurer.userAuthoritiesMapper(userAuthoritiesMapper);
 			return this;
 		}
 
-		public OAuth2LoginConfigurer<H> and() {
+		public OAuth2LoginConfigurer<B> and() {
 			return OAuth2LoginConfigurer.this;
 		}
 	}
 
 	@Override
-	public void init(H http) throws Exception {
-		this.authorizationCodeRequestRedirectFilterConfigurer.setBuilder(http);
-		this.authorizationCodeAuthenticationFilterConfigurer.setBuilder(http);
-
-		this.authorizationCodeRequestRedirectFilterConfigurer.init(http);
-		this.authorizationCodeAuthenticationFilterConfigurer.init(http);
+	public void init(B http) throws Exception {
+		super.init(http);
+		this.authorizationCodeGrantConfigurer.setBuilder(http);
+		this.authorizationCodeGrantConfigurer.init(http);
 		this.initDefaultLoginFilter(http);
 	}
 
 	@Override
-	public void configure(H http) throws Exception {
-		this.authorizationCodeRequestRedirectFilterConfigurer.configure(http);
-		this.authorizationCodeAuthenticationFilterConfigurer.configure(http);
+	public void configure(B http) throws Exception {
+		this.authorizationCodeGrantConfigurer.configure(http);
+		super.configure(http);
+	}
+
+	@Override
+	protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
+		return (this.authorizationCodeGrantConfigurer.getAuthorizationResponseMatcher() != null ?
+			this.authorizationCodeGrantConfigurer.getAuthorizationResponseMatcher() :
+			this.getAuthenticationFilter().getAuthorizationResponseMatcher());
 	}
 
-	static <H extends HttpSecurityBuilder<H>> ClientRegistrationRepository getClientRegistrationRepository(H http) {
-		ClientRegistrationRepository clientRegistrationRepository = http.getSharedObject(ClientRegistrationRepository.class);
+	private ClientRegistrationRepository getClientRegistrationRepository() {
+		ClientRegistrationRepository clientRegistrationRepository = this.getBuilder().getSharedObject(ClientRegistrationRepository.class);
 		if (clientRegistrationRepository == null) {
-			clientRegistrationRepository = getDefaultClientRegistrationRepository(http);
-			http.setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
+			clientRegistrationRepository = this.getClientRegistrationRepositoryBean();
+			this.getBuilder().setSharedObject(ClientRegistrationRepository.class, clientRegistrationRepository);
 		}
 		return clientRegistrationRepository;
 	}
 
-	private static <H extends HttpSecurityBuilder<H>> ClientRegistrationRepository getDefaultClientRegistrationRepository(H http) {
-		return http.getSharedObject(ApplicationContext.class).getBean(ClientRegistrationRepository.class);
+	private ClientRegistrationRepository getClientRegistrationRepositoryBean() {
+		return this.getBuilder().getSharedObject(ApplicationContext.class).getBean(ClientRegistrationRepository.class);
 	}
 
-	private void initDefaultLoginFilter(H http) {
+	private void initDefaultLoginFilter(B http) {
 		DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http.getSharedObject(DefaultLoginPageGeneratingFilter.class);
-		if (loginPageGeneratingFilter == null || this.authorizationCodeAuthenticationFilterConfigurer.isCustomLoginPage()) {
+		if (loginPageGeneratingFilter == null || this.isCustomLoginPage()) {
 			return;
 		}
 
 		Iterable<ClientRegistration> clientRegistrations = null;
-		ClientRegistrationRepository clientRegistrationRepository = getClientRegistrationRepository(http);
+		ClientRegistrationRepository clientRegistrationRepository = this.getClientRegistrationRepository();
 		ResolvableType type = ResolvableType.forInstance(clientRegistrationRepository).as(Iterable.class);
-		if (type != ResolvableType.NONE) {
-			if (Stream.of(type.resolveGenerics()).anyMatch(ClientRegistration.class::isAssignableFrom)) {
-				clientRegistrations = (Iterable<ClientRegistration>) clientRegistrationRepository;
-			}
+		if (type != ResolvableType.NONE && ClientRegistration.class.isAssignableFrom(type.resolveGenerics()[0])) {
+			clientRegistrations = (Iterable<ClientRegistration>) clientRegistrationRepository;
 		}
 		if (clientRegistrations == null) {
 			return;
 		}
 
 		String authorizationRequestBaseUri;
-		RequestMatcher authorizationRequestMatcher = OAuth2LoginConfigurer.this.authorizationCodeRequestRedirectFilterConfigurer.getAuthorizationRequestMatcher();
+		RequestMatcher authorizationRequestMatcher = authorizationCodeGrantConfigurer.getAuthorizationRequestMatcher();
 		if (authorizationRequestMatcher != null && AntPathRequestMatcher.class.isAssignableFrom(authorizationRequestMatcher.getClass())) {
 			String authorizationRequestPattern =  ((AntPathRequestMatcher)authorizationRequestMatcher).getPattern();
 			String registrationIdTemplateVariable = "{" + REGISTRATION_ID_URI_VARIABLE_NAME + "}";
@@ -261,12 +262,31 @@ public final class OAuth2LoginConfigurer<H extends HttpSecurityBuilder<H>> exten
 			authorizationRequestBaseUri = AuthorizationCodeRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI;
 		}
 
-		Map<String, String> oauth2AuthenticationUrlToClientName = new HashMap<>();
-		clientRegistrations.forEach(registration -> oauth2AuthenticationUrlToClientName.put(
+		Map<String, String> authenticationUrlToClientName = new HashMap<>();
+		clientRegistrations.forEach(registration -> authenticationUrlToClientName.put(
 			authorizationRequestBaseUri + "/" + registration.getRegistrationId(), registration.getClientName()));
 		loginPageGeneratingFilter.setOauth2LoginEnabled(true);
-		loginPageGeneratingFilter.setOauth2AuthenticationUrlToClientName(oauth2AuthenticationUrlToClientName);
-		loginPageGeneratingFilter.setLoginPageUrl(this.authorizationCodeAuthenticationFilterConfigurer.getLoginUrl());
-		loginPageGeneratingFilter.setFailureUrl(this.authorizationCodeAuthenticationFilterConfigurer.getLoginFailureUrl());
+		loginPageGeneratingFilter.setOauth2AuthenticationUrlToClientName(authenticationUrlToClientName);
+		loginPageGeneratingFilter.setLoginPageUrl(this.getLoginPage());
+		loginPageGeneratingFilter.setFailureUrl(this.getFailureUrl());
+	}
+
+	private class AuthorizationCodeGrantLoginConfigurer extends AuthorizationCodeGrantConfigurer<B> {
+
+		@Override
+		public void configure(B http) throws Exception {
+			http.addFilter(OAuth2LoginConfigurer.this.postProcess(this.getAuthorizationRequestFilter()));
+
+			AuthorizationCodeAuthenticationFilter authorizationResponseFilter = getAuthenticationFilter();
+			authorizationResponseFilter.setClientRegistrationRepository(getClientRegistrationRepository());
+			if (authorizationCodeGrantConfigurer.getAuthorizationResponseMatcher() != null) {
+				authorizationResponseFilter.setAuthorizationResponseMatcher(
+					authorizationCodeGrantConfigurer.getAuthorizationResponseMatcher());
+			}
+			if (authorizationCodeGrantConfigurer.getAuthorizationRequestRepository() != null) {
+				authorizationResponseFilter.setAuthorizationRequestRepository(
+					authorizationCodeGrantConfigurer.getAuthorizationRequestRepository());
+			}
+		}
 	}
 }

+ 3 - 1
oauth2/oauth2-client/src/main/java/org/springframework/security/oauth2/client/web/AuthorizationCodeRequestRedirectFilter.java

@@ -77,8 +77,10 @@ public class AuthorizationCodeRequestRedirectFilter extends OncePerRequestFilter
 		this.clientRegistrationRepository = clientRegistrationRepository;
 	}
 
-	public final <T extends RequestMatcher & RequestVariablesExtractor> void setAuthorizationRequestMatcher(T authorizationRequestMatcher) {
+	public final void setAuthorizationRequestMatcher(RequestMatcher authorizationRequestMatcher) {
 		Assert.notNull(authorizationRequestMatcher, "authorizationRequestMatcher cannot be null");
+		Assert.isInstanceOf(RequestVariablesExtractor.class, authorizationRequestMatcher,
+			"authorizationRequestMatcher must also be a " + RequestVariablesExtractor.class.getName());
 		this.authorizationRequestMatcher = authorizationRequestMatcher;
 	}
 

+ 1 - 1
samples/boot/oauth2login/src/integration-test/java/org/springframework/security/samples/OAuth2LoginApplicationTests.java

@@ -351,7 +351,7 @@ public class OAuth2LoginApplicationTests {
 						.authorizationCodeTokenExchanger(this.mockAuthorizationCodeTokenExchanger())
 						.and()
 					.userInfoEndpoint()
-						.userInfoService(this.mockUserInfoService());
+						.userService(this.mockUserInfoService());
 		}
 		// @formatter:on