| 
					
				 | 
			
			
				@@ -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() 
			 |