mirror of
				https://github.com/spring-projects/spring-security.git
				synced 2025-10-30 22:28:46 +00:00 
			
		
		
		
	Make the loginProcessingUrl configurable for saml2Login()
Fixes gh-7565 https://github.com/spring-projects/spring-security/issues/7565
This commit is contained in:
		
							parent
							
								
									5f17032ffd
								
							
						
					
					
						commit
						0cafcf37e2
					
				| @ -164,7 +164,10 @@ public final class Saml2LoginConfigurer<B extends HttpSecurityBuilder<B>> extend | ||||
| 			this.relyingPartyRegistrationRepository = getSharedOrBean(http, RelyingPartyRegistrationRepository.class); | ||||
| 		} | ||||
| 
 | ||||
| 		Saml2WebSsoAuthenticationFilter webSsoFilter = new Saml2WebSsoAuthenticationFilter(this.relyingPartyRegistrationRepository); | ||||
| 		Saml2WebSsoAuthenticationFilter webSsoFilter = new Saml2WebSsoAuthenticationFilter( | ||||
| 				this.relyingPartyRegistrationRepository, | ||||
| 				this.loginProcessingUrl | ||||
| 		); | ||||
| 		setAuthenticationFilter(webSsoFilter); | ||||
| 		super.loginProcessingUrl(this.loginProcessingUrl); | ||||
| 
 | ||||
|  | ||||
| @ -44,9 +44,21 @@ public class Saml2WebSsoAuthenticationFilter extends AbstractAuthenticationProce | ||||
| 	private final RelyingPartyRegistrationRepository relyingPartyRegistrationRepository; | ||||
| 
 | ||||
| 	public Saml2WebSsoAuthenticationFilter(RelyingPartyRegistrationRepository relyingPartyRegistrationRepository) { | ||||
| 		super(DEFAULT_FILTER_PROCESSES_URI); | ||||
| 		this(relyingPartyRegistrationRepository, DEFAULT_FILTER_PROCESSES_URI); | ||||
| 	} | ||||
| 
 | ||||
| 	public Saml2WebSsoAuthenticationFilter( | ||||
| 			RelyingPartyRegistrationRepository relyingPartyRegistrationRepository, | ||||
| 			String filterProcessesUrl) { | ||||
| 		super(filterProcessesUrl); | ||||
| 		Assert.notNull(relyingPartyRegistrationRepository, "relyingPartyRegistrationRepository cannot be null"); | ||||
| 		this.matcher = new AntPathRequestMatcher(DEFAULT_FILTER_PROCESSES_URI); | ||||
| 		Assert.hasText(filterProcessesUrl, "filterProcessesUrl must contain a URL pattern"); | ||||
| 		Assert.isTrue( | ||||
| 				filterProcessesUrl.contains("{registrationId}"), | ||||
| 				"filterProcessesUrl must contain a {registrationId} match variable" | ||||
| 		); | ||||
| 		this.matcher = new AntPathRequestMatcher(filterProcessesUrl); | ||||
| 		setRequiresAuthenticationRequestMatcher(this.matcher); | ||||
| 		this.relyingPartyRegistrationRepository = relyingPartyRegistrationRepository; | ||||
| 		setAllowSessionCreation(true); | ||||
| 		setSessionAuthenticationStrategy(new ChangeSessionIdAuthenticationStrategy()); | ||||
|  | ||||
| @ -0,0 +1,75 @@ | ||||
| /* | ||||
|  * Copyright 2002-2019 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 | ||||
|  * | ||||
|  *      https://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.saml2.provider.service.servlet.filter; | ||||
| 
 | ||||
| import org.junit.Assert; | ||||
| import org.junit.Before; | ||||
| import org.junit.Rule; | ||||
| import org.junit.Test; | ||||
| import org.junit.rules.ExpectedException; | ||||
| import org.springframework.mock.web.MockHttpServletRequest; | ||||
| import org.springframework.mock.web.MockHttpServletResponse; | ||||
| import org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository; | ||||
| 
 | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| 
 | ||||
| import static org.mockito.Mockito.mock; | ||||
| 
 | ||||
| public class Saml2WebSsoAuthenticationFilterTests { | ||||
| 
 | ||||
| 	private Saml2WebSsoAuthenticationFilter filter; | ||||
| 	private RelyingPartyRegistrationRepository repository = mock(RelyingPartyRegistrationRepository.class); | ||||
| 	private MockHttpServletRequest request = new MockHttpServletRequest(); | ||||
| 	private HttpServletResponse response = new MockHttpServletResponse(); | ||||
| 
 | ||||
| 	@Rule | ||||
| 	public ExpectedException exception = ExpectedException.none(); | ||||
| 
 | ||||
| 	@Before | ||||
| 	public void setup() { | ||||
| 		filter = new Saml2WebSsoAuthenticationFilter(repository); | ||||
| 		request.setPathInfo("/login/saml2/sso/idp-registration-id"); | ||||
| 		request.setParameter("SAMLResponse", "xml-data-goes-here"); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void constructingFilterWithMissingRegistrationIdVariableThenThrowsException() { | ||||
| 		exception.expect(IllegalArgumentException.class); | ||||
| 		exception.expectMessage("filterProcessesUrl must contain a {registrationId} match variable"); | ||||
| 		filter = new Saml2WebSsoAuthenticationFilter(repository, "/url/missing/variable"); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void constructingFilterWithValidRegistrationIdVariableThenSucceeds() { | ||||
| 		filter = new Saml2WebSsoAuthenticationFilter(repository, "/url/variable/is/present/{registrationId}"); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void requiresAuthenticationWhenHappyPathThenReturnsTrue() { | ||||
| 		Assert.assertTrue(filter.requiresAuthentication(request, response)); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void requiresAuthenticationWhenCustomProcessingUrlThenReturnsTrue() { | ||||
| 		filter = new Saml2WebSsoAuthenticationFilter(repository, "/some/other/path/{registrationId}"); | ||||
| 		request.setPathInfo("/some/other/path/idp-registration-id"); | ||||
| 		request.setParameter("SAMLResponse", "xml-data-goes-here"); | ||||
| 		Assert.assertTrue(filter.requiresAuthentication(request, response)); | ||||
| 	} | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
| @ -51,7 +51,6 @@ import org.springframework.boot.SpringBootConfiguration; | ||||
| import org.springframework.boot.autoconfigure.EnableAutoConfiguration; | ||||
| import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||||
| import org.springframework.boot.test.context.SpringBootTest; | ||||
| import org.springframework.context.annotation.ComponentScan; | ||||
| import org.springframework.http.MediaType; | ||||
| import org.springframework.security.saml2.provider.service.authentication.Saml2AuthenticationException; | ||||
| import org.springframework.test.context.junit4.SpringRunner; | ||||
| @ -111,7 +110,6 @@ public class Saml2LoginIntegrationTests { | ||||
| 
 | ||||
| 	@SpringBootConfiguration | ||||
| 	@EnableAutoConfiguration | ||||
| 	@ComponentScan(basePackages = "sample") | ||||
| 	public static class SpringBootApplicationTestConfig { | ||||
| 
 | ||||
| 	} | ||||
|  | ||||
| @ -76,6 +76,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { | ||||
| 							getSaml2AuthenticationConfiguration() | ||||
| 					) | ||||
| 				) | ||||
| 				.loginProcessingUrl("/sample/jc/saml2/sso/{registrationId}") | ||||
| 		; | ||||
| 		// @formatter:on | ||||
| 	} | ||||
|  | ||||
| @ -15,17 +15,46 @@ | ||||
|  */ | ||||
| package org.springframework.security.samples.config; | ||||
| 
 | ||||
| import org.springframework.test.context.ContextConfiguration; | ||||
| import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||||
| 
 | ||||
| import org.junit.Assert; | ||||
| import org.junit.Test; | ||||
| import org.junit.runner.RunWith; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.context.ApplicationContext; | ||||
| import org.springframework.security.saml2.provider.service.servlet.filter.Saml2WebSsoAuthenticationFilter; | ||||
| import org.springframework.security.web.FilterChainProxy; | ||||
| import org.springframework.test.context.ContextConfiguration; | ||||
| import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; | ||||
| import org.springframework.test.util.ReflectionTestUtils; | ||||
| 
 | ||||
| import java.util.List; | ||||
| import javax.servlet.Filter; | ||||
| 
 | ||||
| @RunWith(SpringJUnit4ClassRunner.class) | ||||
| @ContextConfiguration(classes = SecurityConfig.class) | ||||
| public class SecurityConfigTests { | ||||
| 
 | ||||
| 	@Autowired | ||||
| 	ApplicationContext context; | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void securityConfigurationLoads() { | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	public void filterWhenLoginProcessingUrlIsSetInJavaConfigThenTheFilterHasIt() { | ||||
| 		FilterChainProxy filterChain = context.getBean(FilterChainProxy.class); | ||||
| 		Assert.assertNotNull(filterChain); | ||||
| 		final List<Filter> filters = filterChain.getFilters("/sample/jc/saml2/sso/test-id"); | ||||
| 		Assert.assertNotNull(filters); | ||||
| 		Saml2WebSsoAuthenticationFilter filter = (Saml2WebSsoAuthenticationFilter) filters | ||||
| 				.stream() | ||||
| 				.filter( | ||||
| 						f -> f instanceof Saml2WebSsoAuthenticationFilter | ||||
| 				) | ||||
| 				.findFirst() | ||||
| 				.get(); | ||||
| 		final Object matcher = ReflectionTestUtils.getField(filter, "requiresAuthenticationRequestMatcher"); | ||||
| 		final Object pattern = ReflectionTestUtils.getField(matcher, "pattern"); | ||||
| 		Assert.assertEquals("loginProcessingUrl mismatch", "/sample/jc/saml2/sso/{registrationId}", pattern); | ||||
| 	} | ||||
| } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user