|  | @@ -15,6 +15,7 @@
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  package org.springframework.security.config.annotation.web.configurers.oauth2.client;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +import org.apache.http.HttpHeaders;
 | 
	
		
			
				|  |  |  import org.junit.After;
 | 
	
		
			
				|  |  |  import org.junit.Before;
 | 
	
		
			
				|  |  |  import org.junit.Test;
 | 
	
	
		
			
				|  | @@ -22,6 +23,7 @@ import org.springframework.beans.PropertyAccessorFactory;
 | 
	
		
			
				|  |  |  import org.springframework.beans.factory.annotation.Autowired;
 | 
	
		
			
				|  |  |  import org.springframework.context.ConfigurableApplicationContext;
 | 
	
		
			
				|  |  |  import org.springframework.context.annotation.Bean;
 | 
	
		
			
				|  |  | +import org.springframework.http.MediaType;
 | 
	
		
			
				|  |  |  import org.springframework.mock.web.MockFilterChain;
 | 
	
		
			
				|  |  |  import org.springframework.mock.web.MockHttpServletRequest;
 | 
	
		
			
				|  |  |  import org.springframework.mock.web.MockHttpServletResponse;
 | 
	
	
		
			
				|  | @@ -81,14 +83,19 @@ import static org.assertj.core.api.Assertions.assertThat;
 | 
	
		
			
				|  |  |   * Tests for {@link OAuth2LoginConfigurer}.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   * @author Kazuki Shimizu
 | 
	
		
			
				|  |  | + * @author Joe Grandja
 | 
	
		
			
				|  |  |   * @since 5.0.1
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  public class OAuth2LoginConfigurerTests {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -	private static final ClientRegistration CLIENT_REGISTRATION = CommonOAuth2Provider.GOOGLE
 | 
	
		
			
				|  |  | +	private static final ClientRegistration GOOGLE_CLIENT_REGISTRATION = CommonOAuth2Provider.GOOGLE
 | 
	
		
			
				|  |  |  			.getBuilder("google").clientId("clientId").clientSecret("clientSecret")
 | 
	
		
			
				|  |  |  			.build();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	private static final ClientRegistration GITHUB_CLIENT_REGISTRATION = CommonOAuth2Provider.GITHUB
 | 
	
		
			
				|  |  | +			.getBuilder("github").clientId("clientId").clientSecret("clientSecret")
 | 
	
		
			
				|  |  | +			.build();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	private ConfigurableApplicationContext context;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	@Autowired
 | 
	
	
		
			
				|  | @@ -239,6 +246,62 @@ public class OAuth2LoginConfigurerTests {
 | 
	
		
			
				|  |  |  		assertThat(this.response.getRedirectedUrl()).matches("https://accounts.google.com/o/oauth2/v2/auth\\?response_type=code&client_id=clientId&scope=openid\\+profile\\+email&state=.{15,}&redirect_uri=http%3A%2F%2Flocalhost%2Flogin%2Foauth2%2Fcode%2Fgoogle&custom-param1=custom-value1");
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	// gh-5347
 | 
	
		
			
				|  |  | +	@Test
 | 
	
		
			
				|  |  | +	public void oauth2LoginWithOneClientConfiguredThenRedirectForAuthorization() throws Exception {
 | 
	
		
			
				|  |  | +		loadConfig(OAuth2LoginConfig.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		String requestUri = "/";
 | 
	
		
			
				|  |  | +		this.request = new MockHttpServletRequest("GET", requestUri);
 | 
	
		
			
				|  |  | +		this.request.setServletPath(requestUri);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		assertThat(this.response.getRedirectedUrl()).matches("http://localhost/oauth2/authorization/google");
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// gh-5347
 | 
	
		
			
				|  |  | +	@Test
 | 
	
		
			
				|  |  | +	public void oauth2LoginWithOneClientConfiguredAndRequestFaviconNotAuthenticatedThenRedirectDefaultLoginPage() throws Exception {
 | 
	
		
			
				|  |  | +		loadConfig(OAuth2LoginConfig.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		String requestUri = "/favicon.ico";
 | 
	
		
			
				|  |  | +		this.request = new MockHttpServletRequest("GET", requestUri);
 | 
	
		
			
				|  |  | +		this.request.setServletPath(requestUri);
 | 
	
		
			
				|  |  | +		this.request.addHeader(HttpHeaders.ACCEPT, new MediaType("image", "*").toString());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		assertThat(this.response.getRedirectedUrl()).matches("http://localhost/login");
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// gh-5347
 | 
	
		
			
				|  |  | +	@Test
 | 
	
		
			
				|  |  | +	public void oauth2LoginWithMultipleClientsConfiguredThenRedirectDefaultLoginPage() throws Exception {
 | 
	
		
			
				|  |  | +		loadConfig(OAuth2LoginConfigMultipleClients.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		String requestUri = "/";
 | 
	
		
			
				|  |  | +		this.request = new MockHttpServletRequest("GET", requestUri);
 | 
	
		
			
				|  |  | +		this.request.setServletPath(requestUri);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		assertThat(this.response.getRedirectedUrl()).matches("http://localhost/login");
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	@Test
 | 
	
		
			
				|  |  | +	public void oauth2LoginWithCustomLoginPageThenRedirectCustomLoginPage() throws Exception {
 | 
	
		
			
				|  |  | +		loadConfig(OAuth2LoginConfigCustomLoginPage.class);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		String requestUri = "/";
 | 
	
		
			
				|  |  | +		this.request = new MockHttpServletRequest("GET", requestUri);
 | 
	
		
			
				|  |  | +		this.request.setServletPath(requestUri);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		this.springSecurityFilterChain.doFilter(this.request, this.response, this.filterChain);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		assertThat(this.response.getRedirectedUrl()).matches("http://localhost/custom-login");
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	@Test
 | 
	
		
			
				|  |  |  	public void oidcLogin() throws Exception {
 | 
	
		
			
				|  |  |  		// setup application context
 | 
	
	
		
			
				|  | @@ -348,15 +411,19 @@ public class OAuth2LoginConfigurerTests {
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	private OAuth2AuthorizationRequest createOAuth2AuthorizationRequest(String... scopes) {
 | 
	
		
			
				|  |  | +		return this.createOAuth2AuthorizationRequest(GOOGLE_CLIENT_REGISTRATION, scopes);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	private OAuth2AuthorizationRequest createOAuth2AuthorizationRequest(ClientRegistration registration, String... scopes) {
 | 
	
		
			
				|  |  |  		return OAuth2AuthorizationRequest.authorizationCode()
 | 
	
		
			
				|  |  | -				.authorizationUri(CLIENT_REGISTRATION.getProviderDetails().getAuthorizationUri())
 | 
	
		
			
				|  |  | -				.clientId(CLIENT_REGISTRATION.getClientId())
 | 
	
		
			
				|  |  | +				.authorizationUri(registration.getProviderDetails().getAuthorizationUri())
 | 
	
		
			
				|  |  | +				.clientId(registration.getClientId())
 | 
	
		
			
				|  |  |  				.state("state123")
 | 
	
		
			
				|  |  |  				.redirectUri("http://localhost")
 | 
	
		
			
				|  |  |  				.additionalParameters(
 | 
	
		
			
				|  |  | -					Collections.singletonMap(
 | 
	
		
			
				|  |  | -						OAuth2ParameterNames.REGISTRATION_ID,
 | 
	
		
			
				|  |  | -						CLIENT_REGISTRATION.getRegistrationId()))
 | 
	
		
			
				|  |  | +						Collections.singletonMap(
 | 
	
		
			
				|  |  | +								OAuth2ParameterNames.REGISTRATION_ID,
 | 
	
		
			
				|  |  | +								registration.getRegistrationId()))
 | 
	
		
			
				|  |  |  				.scope(scopes)
 | 
	
		
			
				|  |  |  				.build();
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -368,7 +435,7 @@ public class OAuth2LoginConfigurerTests {
 | 
	
		
			
				|  |  |  			http
 | 
	
		
			
				|  |  |  				.oauth2Login()
 | 
	
		
			
				|  |  |  					.clientRegistrationRepository(
 | 
	
		
			
				|  |  | -						new InMemoryClientRegistrationRepository(CLIENT_REGISTRATION));
 | 
	
		
			
				|  |  | +						new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION));
 | 
	
		
			
				|  |  |  			super.configure(http);
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
	
		
			
				|  | @@ -380,7 +447,7 @@ public class OAuth2LoginConfigurerTests {
 | 
	
		
			
				|  |  |  			http
 | 
	
		
			
				|  |  |  				.oauth2Login()
 | 
	
		
			
				|  |  |  					.clientRegistrationRepository(
 | 
	
		
			
				|  |  | -							new InMemoryClientRegistrationRepository(CLIENT_REGISTRATION))
 | 
	
		
			
				|  |  | +							new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION))
 | 
	
		
			
				|  |  |  					.userInfoEndpoint()
 | 
	
		
			
				|  |  |  						.userAuthoritiesMapper(createGrantedAuthoritiesMapper());
 | 
	
		
			
				|  |  |  			super.configure(http);
 | 
	
	
		
			
				|  | @@ -398,7 +465,7 @@ public class OAuth2LoginConfigurerTests {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		@Bean
 | 
	
		
			
				|  |  |  		ClientRegistrationRepository clientRegistrationRepository() {
 | 
	
		
			
				|  |  | -			return new InMemoryClientRegistrationRepository(CLIENT_REGISTRATION);
 | 
	
		
			
				|  |  | +			return new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION);
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		@Bean
 | 
	
	
		
			
				|  | @@ -414,7 +481,7 @@ public class OAuth2LoginConfigurerTests {
 | 
	
		
			
				|  |  |  			http
 | 
	
		
			
				|  |  |  				.oauth2Login()
 | 
	
		
			
				|  |  |  					.clientRegistrationRepository(
 | 
	
		
			
				|  |  | -						new InMemoryClientRegistrationRepository(CLIENT_REGISTRATION))
 | 
	
		
			
				|  |  | +						new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION))
 | 
	
		
			
				|  |  |  					.loginProcessingUrl("/login/oauth2/*");
 | 
	
		
			
				|  |  |  			super.configure(http);
 | 
	
		
			
				|  |  |  		}
 | 
	
	
		
			
				|  | @@ -423,7 +490,7 @@ public class OAuth2LoginConfigurerTests {
 | 
	
		
			
				|  |  |  	@EnableWebSecurity
 | 
	
		
			
				|  |  |  	static class OAuth2LoginConfigCustomAuthorizationRequestResolver extends CommonWebSecurityConfigurerAdapter {
 | 
	
		
			
				|  |  |  		private ClientRegistrationRepository clientRegistrationRepository =
 | 
	
		
			
				|  |  | -				new InMemoryClientRegistrationRepository(CLIENT_REGISTRATION);
 | 
	
		
			
				|  |  | +				new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  		@Override
 | 
	
		
			
				|  |  |  		protected void configure(HttpSecurity http) throws Exception {
 | 
	
	
		
			
				|  | @@ -449,10 +516,39 @@ public class OAuth2LoginConfigurerTests {
 | 
	
		
			
				|  |  |  		}
 | 
	
		
			
				|  |  |  	}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	@EnableWebSecurity
 | 
	
		
			
				|  |  | +	static class OAuth2LoginConfigMultipleClients extends CommonWebSecurityConfigurerAdapter {
 | 
	
		
			
				|  |  | +		@Override
 | 
	
		
			
				|  |  | +		protected void configure(HttpSecurity http) throws Exception {
 | 
	
		
			
				|  |  | +			http
 | 
	
		
			
				|  |  | +					.oauth2Login()
 | 
	
		
			
				|  |  | +					.clientRegistrationRepository(
 | 
	
		
			
				|  |  | +							new InMemoryClientRegistrationRepository(
 | 
	
		
			
				|  |  | +									GOOGLE_CLIENT_REGISTRATION, GITHUB_CLIENT_REGISTRATION));
 | 
	
		
			
				|  |  | +			super.configure(http);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	@EnableWebSecurity
 | 
	
		
			
				|  |  | +	static class OAuth2LoginConfigCustomLoginPage extends CommonWebSecurityConfigurerAdapter {
 | 
	
		
			
				|  |  | +		@Override
 | 
	
		
			
				|  |  | +		protected void configure(HttpSecurity http) throws Exception {
 | 
	
		
			
				|  |  | +			http
 | 
	
		
			
				|  |  | +					.oauth2Login()
 | 
	
		
			
				|  |  | +					.clientRegistrationRepository(
 | 
	
		
			
				|  |  | +							new InMemoryClientRegistrationRepository(GOOGLE_CLIENT_REGISTRATION))
 | 
	
		
			
				|  |  | +					.loginPage("/custom-login");
 | 
	
		
			
				|  |  | +			super.configure(http);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	private static abstract class CommonWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
 | 
	
		
			
				|  |  |  		@Override
 | 
	
		
			
				|  |  |  		protected void configure(HttpSecurity http) throws Exception {
 | 
	
		
			
				|  |  |  			http
 | 
	
		
			
				|  |  | +				.authorizeRequests()
 | 
	
		
			
				|  |  | +					.anyRequest().authenticated()
 | 
	
		
			
				|  |  | +					.and()
 | 
	
		
			
				|  |  |  				.securityContext()
 | 
	
		
			
				|  |  |  					.securityContextRepository(securityContextRepository())
 | 
	
		
			
				|  |  |  					.and()
 |