Allow configuration of openid login through nested builder
Issue: gh-5557
This commit is contained in:
parent
c3dad06ea6
commit
bf1bbd14e9
|
@ -239,6 +239,128 @@ public final class HttpSecurity extends
|
||||||
return getOrApply(new OpenIDLoginConfigurer<>());
|
return getOrApply(new OpenIDLoginConfigurer<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows configuring OpenID based authentication.
|
||||||
|
*
|
||||||
|
* <h2>Example Configurations</h2>
|
||||||
|
*
|
||||||
|
* A basic example accepting the defaults and not using attribute exchange:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* @Configuration
|
||||||
|
* @EnableWebSecurity
|
||||||
|
* public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
* protected void configure(HttpSecurity http) {
|
||||||
|
* http
|
||||||
|
* .authorizeRequests(authorizeRequests ->
|
||||||
|
* authorizeRequests
|
||||||
|
* .antMatchers("/**").hasRole("USER")
|
||||||
|
* )
|
||||||
|
* .openidLogin(openidLogin ->
|
||||||
|
* openidLogin
|
||||||
|
* .permitAll()
|
||||||
|
* );
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
* protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||||
|
* auth.inMemoryAuthentication()
|
||||||
|
* // the username must match the OpenID of the user you are
|
||||||
|
* // logging in with
|
||||||
|
* .withUser(
|
||||||
|
* "https://www.google.com/accounts/o8/id?id=lmkCn9xzPdsxVwG7pjYMuDgNNdASFmobNkcRPaWU")
|
||||||
|
* .password("password").roles("USER");
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* A more advanced example demonstrating using attribute exchange and providing a
|
||||||
|
* custom AuthenticationUserDetailsService that will make any user that authenticates
|
||||||
|
* a valid user.
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* @Configuration
|
||||||
|
* @EnableWebSecurity
|
||||||
|
* public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
|
||||||
|
*
|
||||||
|
* @Override
|
||||||
|
* protected void configure(HttpSecurity http) throws Exception {
|
||||||
|
* http.authorizeRequests(authorizeRequests ->
|
||||||
|
* authorizeRequests
|
||||||
|
* .antMatchers("/**").hasRole("USER")
|
||||||
|
* )
|
||||||
|
* .openidLogin(openidLogin ->
|
||||||
|
* openidLogin
|
||||||
|
* .loginPage("/login")
|
||||||
|
* .permitAll()
|
||||||
|
* .authenticationUserDetailsService(
|
||||||
|
* new AutoProvisioningUserDetailsService())
|
||||||
|
* .attributeExchange(googleExchange ->
|
||||||
|
* googleExchange
|
||||||
|
* .identifierPattern("https://www.google.com/.*")
|
||||||
|
* .attribute(emailAttribute ->
|
||||||
|
* emailAttribute
|
||||||
|
* .name("email")
|
||||||
|
* .type("https://axschema.org/contact/email")
|
||||||
|
* .required(true)
|
||||||
|
* )
|
||||||
|
* .attribute(firstnameAttribute ->
|
||||||
|
* firstnameAttribute
|
||||||
|
* .name("firstname")
|
||||||
|
* .type("https://axschema.org/namePerson/first")
|
||||||
|
* .required(true)
|
||||||
|
* )
|
||||||
|
* .attribute(lastnameAttribute ->
|
||||||
|
* lastnameAttribute
|
||||||
|
* .name("lastname")
|
||||||
|
* .type("https://axschema.org/namePerson/last")
|
||||||
|
* .required(true)
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* .attributeExchange(yahooExchange ->
|
||||||
|
* yahooExchange
|
||||||
|
* .identifierPattern(".*yahoo.com.*")
|
||||||
|
* .attribute(emailAttribute ->
|
||||||
|
* emailAttribute
|
||||||
|
* .name("email")
|
||||||
|
* .type("https://schema.openid.net/contact/email")
|
||||||
|
* .required(true)
|
||||||
|
* )
|
||||||
|
* .attribute(fullnameAttribute ->
|
||||||
|
* fullnameAttribute
|
||||||
|
* .name("fullname")
|
||||||
|
* .type("https://axschema.org/namePerson")
|
||||||
|
* .required(true)
|
||||||
|
* )
|
||||||
|
* )
|
||||||
|
* );
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public class AutoProvisioningUserDetailsService implements
|
||||||
|
* AuthenticationUserDetailsService<OpenIDAuthenticationToken> {
|
||||||
|
* public UserDetails loadUserDetails(OpenIDAuthenticationToken token)
|
||||||
|
* throws UsernameNotFoundException {
|
||||||
|
* return new User(token.getName(), "NOTUSED",
|
||||||
|
* AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @see OpenIDLoginConfigurer
|
||||||
|
*
|
||||||
|
* @param openidLoginCustomizer the {@link Customizer} to provide more options for
|
||||||
|
* the {@link OpenIDLoginConfigurer}
|
||||||
|
* @return the {@link HttpSecurity} for further customizations
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public HttpSecurity openidLogin(Customizer<OpenIDLoginConfigurer<HttpSecurity>> openidLoginCustomizer) throws Exception {
|
||||||
|
openidLoginCustomizer.customize(getOrApply(new OpenIDLoginConfigurer<>()));
|
||||||
|
return HttpSecurity.this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the Security headers to the response. This is activated by default when using
|
* Adds the Security headers to the response. This is activated by default when using
|
||||||
* {@link WebSecurityConfigurerAdapter}'s default constructor. Accepting the
|
* {@link WebSecurityConfigurerAdapter}'s default constructor. Accepting the
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2019 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -27,6 +27,7 @@ import org.openid4java.consumer.ConsumerManager;
|
||||||
|
|
||||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||||
import org.springframework.security.authentication.AuthenticationManager;
|
import org.springframework.security.authentication.AuthenticationManager;
|
||||||
|
import org.springframework.security.config.Customizer;
|
||||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||||
|
@ -148,6 +149,24 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>> exten
|
||||||
return attributeExchangeConfigurer;
|
return attributeExchangeConfigurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up OpenID attribute exchange for OpenIDs matching the specified pattern.
|
||||||
|
* The default pattern is ".*", it can be specified using
|
||||||
|
* {@link AttributeExchangeConfigurer#identifierPattern(String)}
|
||||||
|
*
|
||||||
|
* @param attributeExchangeCustomizer the {@link Customizer} to provide more options for
|
||||||
|
* the {@link AttributeExchangeConfigurer}
|
||||||
|
* @return a {@link OpenIDLoginConfigurer} for further customizations
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public OpenIDLoginConfigurer<H> attributeExchange(Customizer<AttributeExchangeConfigurer> attributeExchangeCustomizer)
|
||||||
|
throws Exception {
|
||||||
|
AttributeExchangeConfigurer attributeExchangeConfigurer = new AttributeExchangeConfigurer(".*");
|
||||||
|
attributeExchangeCustomizer.customize(attributeExchangeConfigurer);
|
||||||
|
this.attributeExchangeConfigurers.add(attributeExchangeConfigurer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows specifying the {@link OpenIDConsumer} to be used. The default is using an
|
* Allows specifying the {@link OpenIDConsumer} to be used. The default is using an
|
||||||
* {@link OpenID4JavaConsumer}.
|
* {@link OpenID4JavaConsumer}.
|
||||||
|
@ -373,7 +392,7 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>> exten
|
||||||
* @author Rob Winch
|
* @author Rob Winch
|
||||||
*/
|
*/
|
||||||
public final class AttributeExchangeConfigurer {
|
public final class AttributeExchangeConfigurer {
|
||||||
private final String identifier;
|
private String identifier;
|
||||||
private List<OpenIDAttribute> attributes = new ArrayList<>();
|
private List<OpenIDAttribute> attributes = new ArrayList<>();
|
||||||
private List<AttributeConfigurer> attributeConfigurers = new ArrayList<>();
|
private List<AttributeConfigurer> attributeConfigurers = new ArrayList<>();
|
||||||
|
|
||||||
|
@ -395,6 +414,19 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>> exten
|
||||||
return OpenIDLoginConfigurer.this;
|
return OpenIDLoginConfigurer.this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the regular expression for matching on OpenID's (i.e.
|
||||||
|
* "https://www.google.com/.*", ".*yahoo.com.*", etc)
|
||||||
|
*
|
||||||
|
* @param identifierPattern the regular expression for matching on OpenID's
|
||||||
|
* @return the {@link AttributeExchangeConfigurer} for further customization of
|
||||||
|
* attribute exchange
|
||||||
|
*/
|
||||||
|
public AttributeExchangeConfigurer identifierPattern(String identifierPattern) {
|
||||||
|
this.identifier = identifierPattern;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an {@link OpenIDAttribute} to be obtained for the configured OpenID
|
* Adds an {@link OpenIDAttribute} to be obtained for the configured OpenID
|
||||||
* pattern.
|
* pattern.
|
||||||
|
@ -419,6 +451,22 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>> exten
|
||||||
return attributeConfigurer;
|
return attributeConfigurer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an {@link OpenIDAttribute} named "default-attribute".
|
||||||
|
* The name can by updated using {@link AttributeConfigurer#name(String)}.
|
||||||
|
*
|
||||||
|
* @param attributeCustomizer the {@link Customizer} to provide more options for
|
||||||
|
* the {@link AttributeConfigurer}
|
||||||
|
* @return a {@link AttributeExchangeConfigurer} for further customizations
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public AttributeExchangeConfigurer attribute(Customizer<AttributeConfigurer> attributeCustomizer) throws Exception {
|
||||||
|
AttributeConfigurer attributeConfigurer = new AttributeConfigurer();
|
||||||
|
attributeCustomizer.customize(attributeConfigurer);
|
||||||
|
this.attributeConfigurers.add(attributeConfigurer);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link OpenIDAttribute}'s for the configured OpenID pattern
|
* Gets the {@link OpenIDAttribute}'s for the configured OpenID pattern
|
||||||
* @return
|
* @return
|
||||||
|
@ -443,6 +491,16 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>> exten
|
||||||
private boolean required = false;
|
private boolean required = false;
|
||||||
private String type;
|
private String type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new instance named "default-attribute".
|
||||||
|
* The name can by updated using {@link #name(String)}.
|
||||||
|
*
|
||||||
|
* @see AttributeExchangeConfigurer#attribute(String)
|
||||||
|
*/
|
||||||
|
private AttributeConfigurer() {
|
||||||
|
this.name = "default-attribute";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new instance
|
* Creates a new instance
|
||||||
* @param name the name of the attribute
|
* @param name the name of the attribute
|
||||||
|
@ -486,6 +544,16 @@ public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>> exten
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The OpenID attribute name.
|
||||||
|
* @param name
|
||||||
|
* @return the {@link AttributeConfigurer} for further customizations
|
||||||
|
*/
|
||||||
|
public AttributeConfigurer name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link AttributeExchangeConfigurer} for further customization of
|
* Gets the {@link AttributeExchangeConfigurer} for further customization of
|
||||||
* the attributes
|
* the attributes
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue