Allow configuration of openid login through nested builder

Issue: gh-5557
This commit is contained in:
Eleftheria Stein
2019-07-09 10:03:29 -04:00
parent c3dad06ea6
commit bf1bbd14e9
3 changed files with 370 additions and 2 deletions

View File

@@ -16,8 +16,13 @@
package org.springframework.security.config.annotation.web.configurers.openid;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.Rule;
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.context.annotation.Bean;
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.WebSecurityConfigurerAdapter;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.openid.OpenIDAttribute;
import org.springframework.security.openid.OpenIDAuthenticationFilter;
import org.springframework.security.openid.OpenIDAuthenticationProvider;
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.anyBoolean;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
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.result.MockMvcResultMatchers.redirectedUrl;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@@ -128,4 +143,167 @@ public class OpenIDLoginConfigurerTests {
// @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
}
}
}