|
@@ -16,8 +16,13 @@
|
|
|
|
|
|
package org.springframework.security.config.annotation.web.configurers.openid;
|
|
package org.springframework.security.config.annotation.web.configurers.openid;
|
|
|
|
|
|
|
|
+import okhttp3.mockwebserver.MockResponse;
|
|
|
|
+import okhttp3.mockwebserver.MockWebServer;
|
|
import org.junit.Rule;
|
|
import org.junit.Rule;
|
|
import org.junit.Test;
|
|
import org.junit.Test;
|
|
|
|
+import org.openid4java.consumer.ConsumerManager;
|
|
|
|
+import org.openid4java.discovery.DiscoveryInformation;
|
|
|
|
+import org.openid4java.message.AuthRequest;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.context.annotation.Bean;
|
|
import org.springframework.context.annotation.Bean;
|
|
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
|
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
|
@@ -26,13 +31,23 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
|
import org.springframework.security.config.test.SpringTestRule;
|
|
import org.springframework.security.config.test.SpringTestRule;
|
|
|
|
+import org.springframework.security.openid.OpenIDAttribute;
|
|
import org.springframework.security.openid.OpenIDAuthenticationFilter;
|
|
import org.springframework.security.openid.OpenIDAuthenticationFilter;
|
|
import org.springframework.security.openid.OpenIDAuthenticationProvider;
|
|
import org.springframework.security.openid.OpenIDAuthenticationProvider;
|
|
import org.springframework.test.web.servlet.MockMvc;
|
|
import org.springframework.test.web.servlet.MockMvc;
|
|
|
|
+import org.springframework.test.web.servlet.MvcResult;
|
|
|
|
|
|
|
|
+import java.util.List;
|
|
|
|
+
|
|
|
|
+import static org.assertj.core.api.Assertions.assertThat;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
import static org.mockito.ArgumentMatchers.any;
|
|
|
|
+import static org.mockito.ArgumentMatchers.anyBoolean;
|
|
|
|
+import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.spy;
|
|
import static org.mockito.Mockito.spy;
|
|
import static org.mockito.Mockito.verify;
|
|
import static org.mockito.Mockito.verify;
|
|
|
|
+import static org.mockito.Mockito.when;
|
|
|
|
+import static org.openid4java.discovery.yadis.YadisResolver.YADIS_XRDS_LOCATION;
|
|
|
|
+import static org.springframework.security.config.Customizer.withDefaults;
|
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
|
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
|
@@ -128,4 +143,167 @@ public class OpenIDLoginConfigurerTests {
|
|
// @formatter:on
|
|
// @formatter:on
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ public void requestWhenOpenIdLoginPageInLambdaThenRedirectsToLoginPAge() throws Exception {
|
|
|
|
+ this.spring.register(OpenIdLoginPageInLambdaConfig.class).autowire();
|
|
|
|
+
|
|
|
|
+ this.mvc.perform(get("/"))
|
|
|
|
+ .andExpect(status().isFound())
|
|
|
|
+ .andExpect(redirectedUrl("http://localhost/login/custom"));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @EnableWebSecurity
|
|
|
|
+ static class OpenIdLoginPageInLambdaConfig extends WebSecurityConfigurerAdapter {
|
|
|
|
+ @Override
|
|
|
|
+ protected void configure(HttpSecurity http) throws Exception {
|
|
|
|
+ // @formatter:off
|
|
|
|
+ http
|
|
|
|
+ .authorizeRequests(authorizeRequests ->
|
|
|
|
+ authorizeRequests
|
|
|
|
+ .anyRequest().authenticated()
|
|
|
|
+ )
|
|
|
|
+ .openidLogin(openIdLogin ->
|
|
|
|
+ openIdLogin
|
|
|
|
+ .loginPage("/login/custom")
|
|
|
|
+ );
|
|
|
|
+ // @formatter:on
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ public void requestWhenAttributeExchangeConfiguredThenFetchAttributesMatchAttributeList() throws Exception {
|
|
|
|
+ OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
|
|
|
|
+ AuthRequest mockAuthRequest = mock(AuthRequest.class);
|
|
|
|
+ DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class);
|
|
|
|
+ when(mockAuthRequest.getDestinationUrl(anyBoolean())).thenReturn("mockUrl");
|
|
|
|
+ when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.associate(any()))
|
|
|
|
+ .thenReturn(mockDiscoveryInformation);
|
|
|
|
+ when(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(), any()))
|
|
|
|
+ .thenReturn(mockAuthRequest);
|
|
|
|
+ this.spring.register(OpenIdAttributesInLambdaConfig.class).autowire();
|
|
|
|
+
|
|
|
|
+ try ( MockWebServer server = new MockWebServer() ) {
|
|
|
|
+ String endpoint = server.url("/").toString();
|
|
|
|
+
|
|
|
|
+ server.enqueue(new MockResponse()
|
|
|
|
+ .addHeader(YADIS_XRDS_LOCATION, endpoint));
|
|
|
|
+ server.enqueue(new MockResponse()
|
|
|
|
+ .setBody(String.format("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", endpoint)));
|
|
|
|
+
|
|
|
|
+ MvcResult mvcResult = this.mvc.perform(get("/login/openid")
|
|
|
|
+ .param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint))
|
|
|
|
+ .andExpect(status().isFound())
|
|
|
|
+ .andReturn();
|
|
|
|
+
|
|
|
|
+ Object attributeObject = mvcResult.getRequest().getSession().getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST");
|
|
|
|
+ assertThat(attributeObject).isInstanceOf(List.class);
|
|
|
|
+ List<OpenIDAttribute> attributeList = (List<OpenIDAttribute>) attributeObject;
|
|
|
|
+ assertThat(attributeList.stream().anyMatch(attribute ->
|
|
|
|
+ "nickname".equals(attribute.getName())
|
|
|
|
+ && "https://schema.openid.net/namePerson/friendly".equals(attribute.getType())))
|
|
|
|
+ .isTrue();
|
|
|
|
+ assertThat(attributeList.stream().anyMatch(attribute ->
|
|
|
|
+ "email".equals(attribute.getName())
|
|
|
|
+ && "https://schema.openid.net/contact/email".equals(attribute.getType())
|
|
|
|
+ && attribute.isRequired()
|
|
|
|
+ && attribute.getCount() == 2))
|
|
|
|
+ .isTrue();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @EnableWebSecurity
|
|
|
|
+ static class OpenIdAttributesInLambdaConfig extends WebSecurityConfigurerAdapter {
|
|
|
|
+ static ConsumerManager CONSUMER_MANAGER;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected void configure(HttpSecurity http) throws Exception {
|
|
|
|
+ // @formatter:off
|
|
|
|
+ http
|
|
|
|
+ .authorizeRequests(authorizeRequests ->
|
|
|
|
+ authorizeRequests
|
|
|
|
+ .anyRequest().permitAll()
|
|
|
|
+ )
|
|
|
|
+ .openidLogin(openIdLogin ->
|
|
|
|
+ openIdLogin
|
|
|
|
+ .consumerManager(CONSUMER_MANAGER)
|
|
|
|
+ .attributeExchange(attributeExchange ->
|
|
|
|
+ attributeExchange
|
|
|
|
+ .identifierPattern(".*")
|
|
|
|
+ .attribute(nicknameAttribute ->
|
|
|
|
+ nicknameAttribute
|
|
|
|
+ .name("nickname")
|
|
|
|
+ .type("https://schema.openid.net/namePerson/friendly")
|
|
|
|
+ )
|
|
|
|
+ .attribute(emailAttribute ->
|
|
|
|
+ emailAttribute
|
|
|
|
+ .name("email")
|
|
|
|
+ .type("https://schema.openid.net/contact/email")
|
|
|
|
+ .required(true)
|
|
|
|
+ .count(2)
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ );
|
|
|
|
+ // @formatter:on
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ public void requestWhenAttributeNameNotSpecifiedThenAttributeNameDefaulted()
|
|
|
|
+ throws Exception {
|
|
|
|
+ OpenIdAttributesNullNameConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
|
|
|
|
+ AuthRequest mockAuthRequest = mock(AuthRequest.class);
|
|
|
|
+ DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class);
|
|
|
|
+ when(mockAuthRequest.getDestinationUrl(anyBoolean())).thenReturn("mockUrl");
|
|
|
|
+ when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.associate(any()))
|
|
|
|
+ .thenReturn(mockDiscoveryInformation);
|
|
|
|
+ when(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(), any()))
|
|
|
|
+ .thenReturn(mockAuthRequest);
|
|
|
|
+ this.spring.register(OpenIdAttributesNullNameConfig.class).autowire();
|
|
|
|
+
|
|
|
|
+ try ( MockWebServer server = new MockWebServer() ) {
|
|
|
|
+ String endpoint = server.url("/").toString();
|
|
|
|
+
|
|
|
|
+ server.enqueue(new MockResponse()
|
|
|
|
+ .addHeader(YADIS_XRDS_LOCATION, endpoint));
|
|
|
|
+ server.enqueue(new MockResponse()
|
|
|
|
+ .setBody(String.format("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", endpoint)));
|
|
|
|
+
|
|
|
|
+ MvcResult mvcResult = this.mvc.perform(get("/login/openid")
|
|
|
|
+ .param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint))
|
|
|
|
+ .andExpect(status().isFound())
|
|
|
|
+ .andReturn();
|
|
|
|
+
|
|
|
|
+ Object attributeObject = mvcResult.getRequest().getSession().getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST");
|
|
|
|
+ assertThat(attributeObject).isInstanceOf(List.class);
|
|
|
|
+ List<OpenIDAttribute> attributeList = (List<OpenIDAttribute>) attributeObject;
|
|
|
|
+ assertThat(attributeList).hasSize(1);
|
|
|
|
+ assertThat(attributeList.get(0).getName()).isEqualTo("default-attribute");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @EnableWebSecurity
|
|
|
|
+ static class OpenIdAttributesNullNameConfig extends WebSecurityConfigurerAdapter {
|
|
|
|
+ static ConsumerManager CONSUMER_MANAGER;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ protected void configure(HttpSecurity http) throws Exception {
|
|
|
|
+ // @formatter:off
|
|
|
|
+ http
|
|
|
|
+ .authorizeRequests(authorizeRequests ->
|
|
|
|
+ authorizeRequests
|
|
|
|
+ .anyRequest().permitAll()
|
|
|
|
+ )
|
|
|
|
+ .openidLogin(openIdLogin ->
|
|
|
|
+ openIdLogin
|
|
|
|
+ .consumerManager(CONSUMER_MANAGER)
|
|
|
|
+ .attributeExchange(attributeExchange ->
|
|
|
|
+ attributeExchange
|
|
|
|
+ .identifierPattern(".*")
|
|
|
|
+ .attribute(withDefaults())
|
|
|
|
+ )
|
|
|
|
+ );
|
|
|
|
+ // @formatter:on
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|