parent
e7ce694b23
commit
f94090a59b
|
@ -23,7 +23,6 @@ dependencies {
|
|||
optional project(':spring-security-oauth2-client')
|
||||
optional project(':spring-security-oauth2-jose')
|
||||
optional project(':spring-security-oauth2-resource-server')
|
||||
optional project(':spring-security-openid')
|
||||
optional project(':spring-security-rsocket')
|
||||
optional project(':spring-security-web')
|
||||
optional 'io.projectreactor:reactor-core'
|
||||
|
@ -80,10 +79,6 @@ dependencies {
|
|||
testImplementation 'org.hsqldb:hsqldb'
|
||||
testImplementation 'org.mockito:mockito-core'
|
||||
testImplementation "org.mockito:mockito-inline"
|
||||
testImplementation ('org.openid4java:openid4java-nodeps') {
|
||||
exclude group: 'com.google.code.guice', module: 'guice'
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
testImplementation('org.seleniumhq.selenium:htmlunit-driver') {
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
|
|
|
@ -72,12 +72,6 @@ public abstract class Elements {
|
|||
|
||||
public static final String FORM_LOGIN = "form-login";
|
||||
|
||||
public static final String OPENID_LOGIN = "openid-login";
|
||||
|
||||
public static final String OPENID_ATTRIBUTE_EXCHANGE = "attribute-exchange";
|
||||
|
||||
public static final String OPENID_ATTRIBUTE = "openid-attribute";
|
||||
|
||||
public static final String BASIC_AUTH = "http-basic";
|
||||
|
||||
public static final String REMEMBER_ME = "remember-me";
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.springframework.security.config.annotation.SecurityBuilder;
|
|||
import org.springframework.security.config.annotation.SecurityConfigurer;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationFilter;
|
||||
import org.springframework.security.web.DefaultSecurityFilterChain;
|
||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||
import org.springframework.security.web.access.channel.ChannelProcessingFilter;
|
||||
|
@ -132,7 +131,6 @@ public interface HttpSecurityBuilder<H extends HttpSecurityBuilder<H>>
|
|||
* <li><a href="
|
||||
* {@docRoot}/org/springframework/security/cas/web/CasAuthenticationFilter.html">CasAuthenticationFilter</a></li>
|
||||
* <li>{@link UsernamePasswordAuthenticationFilter}</li>
|
||||
* <li>{@link OpenIDAuthenticationFilter}</li>
|
||||
* <li>{@link org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter}</li>
|
||||
* <li>{@link org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter}</li>
|
||||
* <li>{@link ConcurrentSessionFilter}</li>
|
||||
|
|
|
@ -91,7 +91,6 @@ final class FilterOrderRegistration {
|
|||
order.next());
|
||||
put(UsernamePasswordAuthenticationFilter.class, order.next());
|
||||
order.next(); // gh-8105
|
||||
this.filterToOrder.put("org.springframework.security.openid.OpenIDAuthenticationFilter", order.next());
|
||||
put(DefaultLoginPageGeneratingFilter.class, order.next());
|
||||
put(DefaultLogoutPageGeneratingFilter.class, order.next());
|
||||
put(ConcurrentSessionFilter.class, order.next());
|
||||
|
|
|
@ -70,7 +70,6 @@ import org.springframework.security.config.annotation.web.configurers.X509Config
|
|||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2ClientConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.client.OAuth2LoginConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.oauth2.server.resource.OAuth2ResourceServerConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.openid.OpenIDLoginConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.saml2.Saml2LoginConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.saml2.Saml2LogoutConfigurer;
|
||||
import org.springframework.security.core.Authentication;
|
||||
|
@ -171,219 +170,6 @@ public final class HttpSecurity extends AbstractConfiguredSecurityBuilder<Defaul
|
|||
return getSharedObject(ApplicationContext.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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().antMatchers("/**").hasRole("USER").and().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) {
|
||||
* http.authorizeRequests()
|
||||
* .antMatchers("/**")
|
||||
* .hasRole("USER")
|
||||
* .and()
|
||||
* .openidLogin()
|
||||
* .loginPage("/login")
|
||||
* .permitAll()
|
||||
* .authenticationUserDetailsService(
|
||||
* new AutoProvisioningUserDetailsService())
|
||||
* .attributeExchange("https://www.google.com/.*").attribute("email")
|
||||
* .type("https://axschema.org/contact/email").required(true).and()
|
||||
* .attribute("firstname").type("https://axschema.org/namePerson/first")
|
||||
* .required(true).and().attribute("lastname")
|
||||
* .type("https://axschema.org/namePerson/last").required(true).and().and()
|
||||
* .attributeExchange(".*yahoo.com.*").attribute("email")
|
||||
* .type("https://schema.openid.net/contact/email").required(true).and()
|
||||
* .attribute("fullname").type("https://axschema.org/namePerson")
|
||||
* .required(true).and().and().attributeExchange(".*myopenid.com.*")
|
||||
* .attribute("email").type("https://schema.openid.net/contact/email")
|
||||
* .required(true).and().attribute("fullname")
|
||||
* .type("https://schema.openid.net/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>
|
||||
* @return the {@link OpenIDLoginConfigurer} for further customizations.
|
||||
* @throws Exception
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
* @see OpenIDLoginConfigurer
|
||||
*/
|
||||
@Deprecated
|
||||
public OpenIDLoginConfigurer<HttpSecurity> openidLogin() throws Exception {
|
||||
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>
|
||||
* @param openidLoginCustomizer the {@link Customizer} to provide more options for the
|
||||
* {@link OpenIDLoginConfigurer}
|
||||
* @return the {@link HttpSecurity} for further customizations
|
||||
* @throws Exception
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
* @see OpenIDLoginConfigurer
|
||||
*/
|
||||
@Deprecated
|
||||
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
|
||||
* {@link WebSecurityConfigurerAdapter}'s default constructor. Accepting the default
|
||||
|
|
|
@ -26,7 +26,6 @@ import org.springframework.security.authentication.AuthenticationDetailsSource;
|
|||
import org.springframework.security.authentication.AuthenticationManager;
|
||||
import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.openid.OpenIDLoginConfigurer;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.PortMapper;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
|
@ -57,7 +56,6 @@ import org.springframework.web.accept.HeaderContentNegotiationStrategy;
|
|||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
* @see FormLoginConfigurer
|
||||
* @see OpenIDLoginConfigurer
|
||||
*/
|
||||
public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecurityBuilder<B>, T extends AbstractAuthenticationFilterConfigurer<B, T, F>, F extends AbstractAuthenticationProcessingFilter>
|
||||
extends AbstractHttpConfigurer<T, B> {
|
||||
|
|
|
@ -1,569 +0,0 @@
|
|||
/*
|
||||
* 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.config.annotation.web.configurers.openid;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.openid4java.consumer.ConsumerException;
|
||||
import org.openid4java.consumer.ConsumerManager;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
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.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.AbstractAuthenticationFilterConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.FormLoginConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.RememberMeConfigurer;
|
||||
import org.springframework.security.config.annotation.web.configurers.SessionManagementConfigurer;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.openid.AxFetchListFactory;
|
||||
import org.springframework.security.openid.OpenID4JavaConsumer;
|
||||
import org.springframework.security.openid.OpenIDAttribute;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationFilter;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationProvider;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationToken;
|
||||
import org.springframework.security.openid.OpenIDConsumer;
|
||||
import org.springframework.security.openid.RegexBasedAxFetchListFactory;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
|
||||
import org.springframework.security.web.authentication.RememberMeServices;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||
|
||||
/**
|
||||
* Adds support for OpenID based authentication.
|
||||
*
|
||||
* <h2>Example Configuration</h2>
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* @Configuration
|
||||
* @EnableWebSecurity
|
||||
* public class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(HttpSecurity http) {
|
||||
* http
|
||||
* .authorizeRequests()
|
||||
* .antMatchers("/**").hasRole("USER")
|
||||
* .and()
|
||||
* .openidLogin()
|
||||
* .permitAll();
|
||||
* }
|
||||
*
|
||||
* @Override
|
||||
* protected void configure(AuthenticationManagerBuilder auth)(
|
||||
* AuthenticationManagerBuilder auth) throws Exception {
|
||||
* auth
|
||||
* .inMemoryAuthentication()
|
||||
* .withUser("https://www.google.com/accounts/o8/id?id=lmkCn9xzPdsxVwG7pjYMuDgNNdASFmobNkcRPaWU")
|
||||
* .password("password")
|
||||
* .roles("USER");
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <h2>Security Filters</h2>
|
||||
*
|
||||
* The following Filters are populated
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link OpenIDAuthenticationFilter}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Shared Objects Created</h2>
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link AuthenticationEntryPoint} is populated with a
|
||||
* {@link LoginUrlAuthenticationEntryPoint}</li>
|
||||
* <li>An {@link OpenIDAuthenticationProvider} is populated into
|
||||
* {@link HttpSecurity#authenticationProvider(org.springframework.security.authentication.AuthenticationProvider)}
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* <h2>Shared Objects Used</h2>
|
||||
*
|
||||
* The following shared objects are used:
|
||||
*
|
||||
* <ul>
|
||||
* <li>{@link AuthenticationManager}</li>
|
||||
* <li>{@link RememberMeServices} - is optionally used. See {@link RememberMeConfigurer}
|
||||
* </li>
|
||||
* <li>{@link SessionAuthenticationStrategy} - is optionally used. See
|
||||
* {@link SessionManagementConfigurer}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public final class OpenIDLoginConfigurer<H extends HttpSecurityBuilder<H>>
|
||||
extends AbstractAuthenticationFilterConfigurer<H, OpenIDLoginConfigurer<H>, OpenIDAuthenticationFilter> {
|
||||
|
||||
private OpenIDConsumer openIDConsumer;
|
||||
|
||||
private ConsumerManager consumerManager;
|
||||
|
||||
private AuthenticationUserDetailsService<OpenIDAuthenticationToken> authenticationUserDetailsService;
|
||||
|
||||
private List<AttributeExchangeConfigurer> attributeExchangeConfigurers = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
*/
|
||||
public OpenIDLoginConfigurer() {
|
||||
super(new OpenIDAuthenticationFilter(), "/login/openid");
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up OpenID attribute exchange for OpenID's matching the specified pattern.
|
||||
* @param identifierPattern the regular expression for matching on OpenID's (i.e.
|
||||
* "https://www.google.com/.*", ".*yahoo.com.*", etc)
|
||||
* @return a {@link AttributeExchangeConfigurer} for further customizations of the
|
||||
* attribute exchange
|
||||
*/
|
||||
public AttributeExchangeConfigurer attributeExchange(String identifierPattern) {
|
||||
AttributeExchangeConfigurer attributeExchangeConfigurer = new AttributeExchangeConfigurer(identifierPattern);
|
||||
this.attributeExchangeConfigurers.add(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
|
||||
*/
|
||||
public OpenIDLoginConfigurer<H> attributeExchange(
|
||||
Customizer<AttributeExchangeConfigurer> attributeExchangeCustomizer) {
|
||||
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
|
||||
* {@link OpenID4JavaConsumer}.
|
||||
* @param consumer the {@link OpenIDConsumer} to be used
|
||||
* @return the {@link OpenIDLoginConfigurer} for further customizations
|
||||
*/
|
||||
public OpenIDLoginConfigurer<H> consumer(OpenIDConsumer consumer) {
|
||||
this.openIDConsumer = consumer;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows specifying the {@link ConsumerManager} to be used. If specified, will be
|
||||
* populated into an {@link OpenID4JavaConsumer}.
|
||||
*
|
||||
* <p>
|
||||
* This is a shortcut for specifying the {@link OpenID4JavaConsumer} with a specific
|
||||
* {@link ConsumerManager} on {@link #consumer(OpenIDConsumer)}.
|
||||
* </p>
|
||||
* @param consumerManager the {@link ConsumerManager} to use. Cannot be null.
|
||||
* @return the {@link OpenIDLoginConfigurer} for further customizations
|
||||
*/
|
||||
public OpenIDLoginConfigurer<H> consumerManager(ConsumerManager consumerManager) {
|
||||
this.consumerManager = consumerManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link AuthenticationUserDetailsService} to use. By default a
|
||||
* {@link UserDetailsByNameServiceWrapper} is used with the {@link UserDetailsService}
|
||||
* shared object found with {@link HttpSecurity#getSharedObject(Class)}.
|
||||
* @param authenticationUserDetailsService the {@link AuthenticationDetailsSource} to
|
||||
* use
|
||||
* @return the {@link OpenIDLoginConfigurer} for further customizations
|
||||
*/
|
||||
public OpenIDLoginConfigurer<H> authenticationUserDetailsService(
|
||||
AuthenticationUserDetailsService<OpenIDAuthenticationToken> authenticationUserDetailsService) {
|
||||
this.authenticationUserDetailsService = authenticationUserDetailsService;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the URL used to authenticate OpenID requests. If the
|
||||
* {@link HttpServletRequest} matches this URL the {@link OpenIDAuthenticationFilter}
|
||||
* will attempt to authenticate the request. The default is "/login/openid".
|
||||
* @param loginProcessingUrl the URL used to perform authentication
|
||||
* @return the {@link OpenIDLoginConfigurer} for additional customization
|
||||
*/
|
||||
@Override
|
||||
public OpenIDLoginConfigurer<H> loginProcessingUrl(String loginProcessingUrl) {
|
||||
return super.loginProcessingUrl(loginProcessingUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Specifies the URL to send users to if login is required. If used with
|
||||
* {@link WebSecurityConfigurerAdapter} a default login page will be generated when
|
||||
* this attribute is not specified.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* If a URL is specified or this is not being used in conjunction with
|
||||
* {@link WebSecurityConfigurerAdapter}, users are required to process the specified
|
||||
* URL to generate a login page.
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>It must be an HTTP POST</li>
|
||||
* <li>It must be submitted to {@link #loginProcessingUrl(String)}</li>
|
||||
* <li>It should include the OpenID as an HTTP parameter by the name of
|
||||
* {@link OpenIDAuthenticationFilter#DEFAULT_CLAIMED_IDENTITY_FIELD}</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* <h2>Impact on other defaults</h2>
|
||||
*
|
||||
* Updating this value, also impacts a number of other default values. For example,
|
||||
* the following are the default values when only formLogin() was specified.
|
||||
*
|
||||
* <ul>
|
||||
* <li>/login GET - the login form</li>
|
||||
* <li>/login POST - process the credentials and if valid authenticate the user</li>
|
||||
* <li>/login?error GET - redirect here for failed authentication attempts</li>
|
||||
* <li>/login?logout GET - redirect here after successfully logging out</li>
|
||||
* </ul>
|
||||
*
|
||||
* If "/authenticate" was passed to this method it update the defaults as shown below:
|
||||
*
|
||||
* <ul>
|
||||
* <li>/authenticate GET - the login form</li>
|
||||
* <li>/authenticate POST - process the credentials and if valid authenticate the user
|
||||
* </li>
|
||||
* <li>/authenticate?error GET - redirect here for failed authentication attempts</li>
|
||||
* <li>/authenticate?logout GET - redirect here after successfully logging out</li>
|
||||
* </ul>
|
||||
* @param loginPage the login page to redirect to if authentication is required (i.e.
|
||||
* "/login")
|
||||
* @return the {@link FormLoginConfigurer} for additional customization
|
||||
*/
|
||||
@Override
|
||||
public OpenIDLoginConfigurer<H> loginPage(String loginPage) {
|
||||
return super.loginPage(loginPage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(H http) throws Exception {
|
||||
super.init(http);
|
||||
OpenIDAuthenticationProvider authenticationProvider = new OpenIDAuthenticationProvider();
|
||||
authenticationProvider.setAuthenticationUserDetailsService(getAuthenticationUserDetailsService(http));
|
||||
authenticationProvider = postProcess(authenticationProvider);
|
||||
http.authenticationProvider(authenticationProvider);
|
||||
initDefaultLoginFilter(http);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(H http) throws Exception {
|
||||
getAuthenticationFilter().setConsumer(getConsumer());
|
||||
super.configure(http);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RequestMatcher createLoginProcessingUrlMatcher(String loginProcessingUrl) {
|
||||
return new AntPathRequestMatcher(loginProcessingUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link OpenIDConsumer} that was configured or defaults to an
|
||||
* {@link OpenID4JavaConsumer}.
|
||||
* @return the {@link OpenIDConsumer} to use
|
||||
* @throws ConsumerException
|
||||
*/
|
||||
private OpenIDConsumer getConsumer() throws ConsumerException {
|
||||
if (this.openIDConsumer == null) {
|
||||
this.openIDConsumer = new OpenID4JavaConsumer(getConsumerManager(), attributesToFetchFactory());
|
||||
}
|
||||
return this.openIDConsumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link ConsumerManager} that was configured or defaults to using a
|
||||
* {@link ConsumerManager} with the default constructor.
|
||||
* @return the {@link ConsumerManager} to use
|
||||
*/
|
||||
private ConsumerManager getConsumerManager() {
|
||||
if (this.consumerManager != null) {
|
||||
return this.consumerManager;
|
||||
}
|
||||
return new ConsumerManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link RegexBasedAxFetchListFactory} using the attributes populated by
|
||||
* {@link AttributeExchangeConfigurer}
|
||||
* @return the {@link AxFetchListFactory} to use
|
||||
*/
|
||||
private AxFetchListFactory attributesToFetchFactory() {
|
||||
Map<String, List<OpenIDAttribute>> identityToAttrs = new HashMap<>();
|
||||
for (AttributeExchangeConfigurer conf : this.attributeExchangeConfigurers) {
|
||||
identityToAttrs.put(conf.identifier, conf.getAttributes());
|
||||
}
|
||||
return new RegexBasedAxFetchListFactory(identityToAttrs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link AuthenticationUserDetailsService} that was configured or defaults
|
||||
* to {@link UserDetailsByNameServiceWrapper} that uses a {@link UserDetailsService}
|
||||
* looked up using {@link HttpSecurity#getSharedObject(Class)}
|
||||
* @param http the current {@link HttpSecurity}
|
||||
* @return the {@link AuthenticationUserDetailsService}.
|
||||
*/
|
||||
private AuthenticationUserDetailsService<OpenIDAuthenticationToken> getAuthenticationUserDetailsService(H http) {
|
||||
if (this.authenticationUserDetailsService != null) {
|
||||
return this.authenticationUserDetailsService;
|
||||
}
|
||||
return new UserDetailsByNameServiceWrapper<>(http.getSharedObject(UserDetailsService.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* If available, initializes the {@link DefaultLoginPageGeneratingFilter} shared
|
||||
* object.
|
||||
* @param http the {@link HttpSecurityBuilder} to use
|
||||
*/
|
||||
private void initDefaultLoginFilter(H http) {
|
||||
DefaultLoginPageGeneratingFilter loginPageGeneratingFilter = http
|
||||
.getSharedObject(DefaultLoginPageGeneratingFilter.class);
|
||||
if (loginPageGeneratingFilter != null && !isCustomLoginPage()) {
|
||||
loginPageGeneratingFilter.setOpenIdEnabled(true);
|
||||
loginPageGeneratingFilter.setOpenIDauthenticationUrl(getLoginProcessingUrl());
|
||||
String loginPageUrl = loginPageGeneratingFilter.getLoginPageUrl();
|
||||
if (loginPageUrl == null) {
|
||||
loginPageGeneratingFilter.setLoginPageUrl(getLoginPage());
|
||||
loginPageGeneratingFilter.setFailureUrl(getFailureUrl());
|
||||
}
|
||||
loginPageGeneratingFilter
|
||||
.setOpenIDusernameParameter(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A class used to add OpenID attributes to look up
|
||||
*
|
||||
* @author Rob Winch
|
||||
*/
|
||||
public final class AttributeExchangeConfigurer {
|
||||
|
||||
private String identifier;
|
||||
|
||||
private List<OpenIDAttribute> attributes = new ArrayList<>();
|
||||
|
||||
private List<AttributeConfigurer> attributeConfigurers = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates a new instance
|
||||
* @param identifierPattern the pattern that attempts to match on the OpenID
|
||||
* @see OpenIDLoginConfigurer#attributeExchange(String)
|
||||
*/
|
||||
private AttributeExchangeConfigurer(String identifierPattern) {
|
||||
this.identifier = identifierPattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link OpenIDLoginConfigurer} to customize the OpenID configuration
|
||||
* further
|
||||
* @return the {@link OpenIDLoginConfigurer}
|
||||
*/
|
||||
public OpenIDLoginConfigurer<H> and() {
|
||||
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
|
||||
* pattern.
|
||||
* @param attribute the {@link OpenIDAttribute} to obtain
|
||||
* @return the {@link AttributeExchangeConfigurer} for further customization of
|
||||
* attribute exchange
|
||||
*/
|
||||
public AttributeExchangeConfigurer attribute(OpenIDAttribute attribute) {
|
||||
this.attributes.add(attribute);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an {@link OpenIDAttribute} with the given name
|
||||
* @param name the name of the {@link OpenIDAttribute} to create
|
||||
* @return an {@link AttributeConfigurer} to further configure the
|
||||
* {@link OpenIDAttribute} that should be obtained.
|
||||
*/
|
||||
public AttributeConfigurer attribute(String name) {
|
||||
AttributeConfigurer attributeConfigurer = new AttributeConfigurer(name);
|
||||
this.attributeConfigurers.add(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
|
||||
*/
|
||||
public AttributeExchangeConfigurer attribute(Customizer<AttributeConfigurer> attributeCustomizer) {
|
||||
AttributeConfigurer attributeConfigurer = new AttributeConfigurer();
|
||||
attributeCustomizer.customize(attributeConfigurer);
|
||||
this.attributeConfigurers.add(attributeConfigurer);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link OpenIDAttribute}'s for the configured OpenID pattern
|
||||
* @return
|
||||
*/
|
||||
private List<OpenIDAttribute> getAttributes() {
|
||||
for (AttributeConfigurer config : this.attributeConfigurers) {
|
||||
this.attributes.add(config.build());
|
||||
}
|
||||
this.attributeConfigurers.clear();
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures an {@link OpenIDAttribute}
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @since 3.2
|
||||
*/
|
||||
public final class AttributeConfigurer {
|
||||
|
||||
private String name;
|
||||
|
||||
private int count = 1;
|
||||
|
||||
private boolean required = false;
|
||||
|
||||
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
|
||||
* @param name the name of the attribute
|
||||
* @see AttributeExchangeConfigurer#attribute(String)
|
||||
*/
|
||||
private AttributeConfigurer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the number of attribute values to request. Default is 1.
|
||||
* @param count the number of attributes to request.
|
||||
* @return the {@link AttributeConfigurer} for further customization
|
||||
*/
|
||||
public AttributeConfigurer count(int count) {
|
||||
this.count = count;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies that this attribute is required. The default is
|
||||
* <code>false</code>. Note that as outlined in the OpenID specification,
|
||||
* required attributes are not validated by the OpenID Provider. Developers
|
||||
* should perform any validation in custom code.
|
||||
* @param required specifies the attribute is required
|
||||
* @return the {@link AttributeConfigurer} for further customization
|
||||
*/
|
||||
public AttributeConfigurer required(boolean required) {
|
||||
this.required = required;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The OpenID attribute type.
|
||||
* @param type
|
||||
* @return the {@link AttributeConfigurer} for further customizations
|
||||
*/
|
||||
public AttributeConfigurer type(String type) {
|
||||
this.type = type;
|
||||
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
|
||||
* the attributes
|
||||
* @return the {@link AttributeConfigurer}
|
||||
*/
|
||||
public AttributeExchangeConfigurer and() {
|
||||
return AttributeExchangeConfigurer.this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the {@link OpenIDAttribute}.
|
||||
* @return
|
||||
*/
|
||||
private OpenIDAttribute build() {
|
||||
OpenIDAttribute attribute = new OpenIDAttribute(this.name, this.type);
|
||||
attribute.setCount(this.count);
|
||||
attribute.setRequired(this.required);
|
||||
return attribute;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -85,16 +85,6 @@ final class AuthenticationConfigBuilder {
|
|||
|
||||
private static final String DEF_REALM = "Realm";
|
||||
|
||||
static final String OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationFilter";
|
||||
|
||||
static final String OPEN_ID_AUTHENTICATION_PROVIDER_CLASS = "org.springframework.security.openid.OpenIDAuthenticationProvider";
|
||||
|
||||
private static final String OPEN_ID_CONSUMER_CLASS = "org.springframework.security.openid.OpenID4JavaConsumer";
|
||||
|
||||
static final String OPEN_ID_ATTRIBUTE_CLASS = "org.springframework.security.openid.OpenIDAttribute";
|
||||
|
||||
private static final String OPEN_ID_ATTRIBUTE_FACTORY_CLASS = "org.springframework.security.openid.RegexBasedAxFetchListFactory";
|
||||
|
||||
static final String AUTHENTICATION_PROCESSING_FILTER_CLASS = "org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter";
|
||||
|
||||
static final String ATT_AUTH_DETAILS_SOURCE_REF = "authentication-details-source-ref";
|
||||
|
@ -135,14 +125,8 @@ final class AuthenticationConfigBuilder {
|
|||
|
||||
private BeanDefinition formEntryPoint;
|
||||
|
||||
private BeanDefinition openIDEntryPoint;
|
||||
|
||||
private BeanReference openIDProviderRef;
|
||||
|
||||
private String formFilterId = null;
|
||||
|
||||
private String openIDFilterId = null;
|
||||
|
||||
private BeanDefinition x509Filter;
|
||||
|
||||
private BeanReference x509ProviderRef;
|
||||
|
@ -180,12 +164,8 @@ final class AuthenticationConfigBuilder {
|
|||
|
||||
private String loginProcessingUrl;
|
||||
|
||||
private String openidLoginProcessingUrl;
|
||||
|
||||
private String formLoginPage;
|
||||
|
||||
private String openIDLoginPage;
|
||||
|
||||
private boolean oauth2LoginEnabled;
|
||||
|
||||
private boolean defaultAuthorizedClientRepositoryRegistered;
|
||||
|
@ -237,7 +217,6 @@ final class AuthenticationConfigBuilder {
|
|||
createBearerTokenAuthenticationFilter(authenticationManager);
|
||||
createFormLoginFilter(sessionStrategy, authenticationManager);
|
||||
createOAuth2ClientFilters(sessionStrategy, requestCache, authenticationManager);
|
||||
createOpenIDLoginFilter(sessionStrategy, authenticationManager);
|
||||
createX509Filter(authenticationManager);
|
||||
createJeeFilter(authenticationManager);
|
||||
createLogoutFilter();
|
||||
|
@ -395,106 +374,6 @@ final class AuthenticationConfigBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
void createOpenIDLoginFilter(BeanReference sessionStrategy, BeanReference authManager) {
|
||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN);
|
||||
RootBeanDefinition openIDFilter = null;
|
||||
if (openIDLoginElt != null) {
|
||||
openIDFilter = parseOpenIDFilter(sessionStrategy, openIDLoginElt);
|
||||
}
|
||||
if (openIDFilter != null) {
|
||||
openIDFilter.getPropertyValues().addPropertyValue("allowSessionCreation", this.allowSessionCreation);
|
||||
openIDFilter.getPropertyValues().addPropertyValue("authenticationManager", authManager);
|
||||
// Required by login page filter
|
||||
this.openIDFilterId = this.pc.getReaderContext().generateBeanName(openIDFilter);
|
||||
this.pc.registerBeanComponent(new BeanComponentDefinition(openIDFilter, this.openIDFilterId));
|
||||
injectRememberMeServicesRef(openIDFilter, this.rememberMeServicesId);
|
||||
createOpenIDProvider();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses OpenID 1.0 and 2.0 - related parts of configuration xmls
|
||||
* @param sessionStrategy sessionStrategy
|
||||
* @param openIDLoginElt the element from the xml file
|
||||
* @return the parsed filter as rootBeanDefinition
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
private RootBeanDefinition parseOpenIDFilter(BeanReference sessionStrategy, Element openIDLoginElt) {
|
||||
RootBeanDefinition openIDFilter;
|
||||
FormLoginBeanDefinitionParser parser = new FormLoginBeanDefinitionParser("/login/openid", null,
|
||||
OPEN_ID_AUTHENTICATION_PROCESSING_FILTER_CLASS, this.requestCache, sessionStrategy,
|
||||
this.allowSessionCreation, this.portMapper, this.portResolver);
|
||||
|
||||
parser.parse(openIDLoginElt, this.pc);
|
||||
openIDFilter = parser.getFilterBean();
|
||||
this.openIDEntryPoint = parser.getEntryPointBean();
|
||||
this.openidLoginProcessingUrl = parser.getLoginProcessingUrl();
|
||||
this.openIDLoginPage = parser.getLoginPage();
|
||||
List<Element> attrExElts = DomUtils.getChildElementsByTagName(openIDLoginElt,
|
||||
Elements.OPENID_ATTRIBUTE_EXCHANGE);
|
||||
if (!attrExElts.isEmpty()) {
|
||||
// Set up the consumer with the required attribute list
|
||||
BeanDefinitionBuilder consumerBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_CONSUMER_CLASS);
|
||||
BeanDefinitionBuilder axFactory = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_FACTORY_CLASS);
|
||||
ManagedMap<String, ManagedList<BeanDefinition>> axMap = new ManagedMap<>();
|
||||
for (Element attrExElt : attrExElts) {
|
||||
String identifierMatch = attrExElt.getAttribute("identifier-match");
|
||||
if (!StringUtils.hasText(identifierMatch)) {
|
||||
if (attrExElts.size() > 1) {
|
||||
this.pc.getReaderContext().error("You must supply an identifier-match attribute if using more"
|
||||
+ " than one " + Elements.OPENID_ATTRIBUTE_EXCHANGE + " element", attrExElt);
|
||||
}
|
||||
// Match anything
|
||||
identifierMatch = ".*";
|
||||
}
|
||||
axMap.put(identifierMatch, parseOpenIDAttributes(attrExElt));
|
||||
}
|
||||
axFactory.addConstructorArgValue(axMap);
|
||||
consumerBldr.addConstructorArgValue(axFactory.getBeanDefinition());
|
||||
openIDFilter.getPropertyValues().addPropertyValue("consumer", consumerBldr.getBeanDefinition());
|
||||
}
|
||||
return openIDFilter;
|
||||
}
|
||||
|
||||
private ManagedList<BeanDefinition> parseOpenIDAttributes(Element attrExElt) {
|
||||
ManagedList<BeanDefinition> attributes = new ManagedList<>();
|
||||
for (Element attElt : DomUtils.getChildElementsByTagName(attrExElt, Elements.OPENID_ATTRIBUTE)) {
|
||||
String name = attElt.getAttribute("name");
|
||||
String type = attElt.getAttribute("type");
|
||||
String required = attElt.getAttribute("required");
|
||||
String count = attElt.getAttribute("count");
|
||||
BeanDefinitionBuilder attrBldr = BeanDefinitionBuilder.rootBeanDefinition(OPEN_ID_ATTRIBUTE_CLASS);
|
||||
attrBldr.addConstructorArgValue(name);
|
||||
attrBldr.addConstructorArgValue(type);
|
||||
if (StringUtils.hasLength(required)) {
|
||||
attrBldr.addPropertyValue("required", Boolean.valueOf(required));
|
||||
}
|
||||
if (StringUtils.hasLength(count)) {
|
||||
attrBldr.addPropertyValue("count", Integer.parseInt(count));
|
||||
}
|
||||
attributes.add(attrBldr.getBeanDefinition());
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private void createOpenIDProvider() {
|
||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN);
|
||||
BeanDefinitionBuilder openIDProviderBuilder = BeanDefinitionBuilder
|
||||
.rootBeanDefinition(OPEN_ID_AUTHENTICATION_PROVIDER_CLASS);
|
||||
RootBeanDefinition uds = new RootBeanDefinition();
|
||||
uds.setFactoryBeanName(BeanIds.USER_DETAILS_SERVICE_FACTORY);
|
||||
uds.setFactoryMethodName("authenticationUserDetailsService");
|
||||
uds.getConstructorArgumentValues().addGenericArgumentValue(openIDLoginElt.getAttribute(ATT_USER_SERVICE_REF));
|
||||
openIDProviderBuilder.addPropertyValue("authenticationUserDetailsService", uds);
|
||||
BeanDefinition openIDProvider = openIDProviderBuilder.getBeanDefinition();
|
||||
this.openIDProviderRef = new RuntimeBeanReference(
|
||||
this.pc.getReaderContext().registerWithGeneratedName(openIDProvider));
|
||||
}
|
||||
|
||||
private void injectRememberMeServicesRef(RootBeanDefinition bean, String rememberMeServicesId) {
|
||||
if (rememberMeServicesId != null) {
|
||||
bean.getPropertyValues().addPropertyValue("rememberMeServices",
|
||||
|
@ -640,10 +519,9 @@ final class AuthenticationConfigBuilder {
|
|||
}
|
||||
|
||||
void createLoginPageFilterIfNeeded() {
|
||||
boolean needLoginPage = this.formFilterId != null || this.openIDFilterId != null
|
||||
|| this.oauth2LoginFilterId != null;
|
||||
boolean needLoginPage = this.formFilterId != null || this.oauth2LoginFilterId != null;
|
||||
// If no login page has been defined, add in the default page generator.
|
||||
if (needLoginPage && this.formLoginPage == null && this.openIDLoginPage == null) {
|
||||
if (needLoginPage && this.formLoginPage == null) {
|
||||
this.logger.info("No login page configured. The default internal one will be used. Use the '"
|
||||
+ FormLoginBeanDefinitionParser.ATT_LOGIN_PAGE + "' attribute to set the URL of the login page.");
|
||||
BeanDefinitionBuilder loginPageFilter = BeanDefinitionBuilder
|
||||
|
@ -657,12 +535,7 @@ final class AuthenticationConfigBuilder {
|
|||
loginPageFilter.addConstructorArgReference(this.formFilterId);
|
||||
loginPageFilter.addPropertyValue("authenticationUrl", this.loginProcessingUrl);
|
||||
}
|
||||
if (this.openIDFilterId != null) {
|
||||
loginPageFilter.addConstructorArgReference(this.openIDFilterId);
|
||||
loginPageFilter.addPropertyValue("openIDauthenticationUrl", this.openidLoginProcessingUrl);
|
||||
}
|
||||
if (this.oauth2LoginFilterId != null) {
|
||||
loginPageFilter.addConstructorArgReference(this.oauth2LoginFilterId);
|
||||
loginPageFilter.addPropertyValue("Oauth2LoginEnabled", true);
|
||||
loginPageFilter.addPropertyValue("Oauth2AuthenticationUrlToClientName", this.oauth2LoginLinks);
|
||||
}
|
||||
|
@ -820,21 +693,11 @@ final class AuthenticationConfigBuilder {
|
|||
}
|
||||
Element basicAuthElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.BASIC_AUTH);
|
||||
Element formLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.FORM_LOGIN);
|
||||
Element openIDLoginElt = DomUtils.getChildElementByTagName(this.httpElt, Elements.OPENID_LOGIN);
|
||||
// Basic takes precedence if explicit element is used and no others are configured
|
||||
if (basicAuthElt != null && formLoginElt == null && openIDLoginElt == null
|
||||
&& this.oauth2LoginEntryPoint == null) {
|
||||
if (basicAuthElt != null && formLoginElt == null && this.oauth2LoginEntryPoint == null) {
|
||||
return this.basicEntryPoint;
|
||||
}
|
||||
// If formLogin has been enabled either through an element or auto-config, then it
|
||||
// is used if no openID login page
|
||||
// has been set.
|
||||
if (this.formLoginPage != null && this.openIDLoginPage != null) {
|
||||
this.pc.getReaderContext().error(
|
||||
"Only one login-page can be defined, either for OpenID or form-login, " + "but not both.",
|
||||
this.pc.extractSource(openIDLoginElt));
|
||||
}
|
||||
if (this.formFilterId != null && this.openIDLoginPage == null) {
|
||||
if (this.formFilterId != null) {
|
||||
// If form login was enabled through element and Oauth2 login was enabled from
|
||||
// element then use form login (gh-6802)
|
||||
if (formLoginElt != null && this.oauth2LoginEntryPoint != null) {
|
||||
|
@ -846,10 +709,6 @@ final class AuthenticationConfigBuilder {
|
|||
return this.formEntryPoint;
|
||||
}
|
||||
}
|
||||
// Otherwise use OpenID if enabled
|
||||
if (this.openIDFilterId != null) {
|
||||
return this.openIDEntryPoint;
|
||||
}
|
||||
// If X.509 or JEE have been enabled, use the preauth entry point.
|
||||
if (this.preAuthEntryPoint != null) {
|
||||
return this.preAuthEntryPoint;
|
||||
|
@ -902,10 +761,6 @@ final class AuthenticationConfigBuilder {
|
|||
filters.add(new OrderDecorator(this.oauth2AuthorizationRequestRedirectFilter,
|
||||
SecurityFilters.OAUTH2_AUTHORIZATION_REQUEST_FILTER));
|
||||
}
|
||||
if (this.openIDFilterId != null) {
|
||||
filters.add(
|
||||
new OrderDecorator(new RuntimeBeanReference(this.openIDFilterId), SecurityFilters.OPENID_FILTER));
|
||||
}
|
||||
if (this.loginPageGenerationFilter != null) {
|
||||
filters.add(new OrderDecorator(this.loginPageGenerationFilter, SecurityFilters.LOGIN_PAGE_FILTER));
|
||||
filters.add(new OrderDecorator(this.logoutPageGenerationFilter, SecurityFilters.LOGOUT_PAGE_FILTER));
|
||||
|
@ -935,9 +790,6 @@ final class AuthenticationConfigBuilder {
|
|||
if (this.rememberMeProviderRef != null) {
|
||||
providers.add(this.rememberMeProviderRef);
|
||||
}
|
||||
if (this.openIDProviderRef != null) {
|
||||
providers.add(this.openIDProviderRef);
|
||||
}
|
||||
if (this.x509ProviderRef != null) {
|
||||
providers.add(this.x509ProviderRef);
|
||||
}
|
||||
|
|
|
@ -57,8 +57,6 @@ enum SecurityFilters {
|
|||
|
||||
FORM_LOGIN_FILTER,
|
||||
|
||||
OPENID_FILTER,
|
||||
|
||||
LOGIN_PAGE_FILTER,
|
||||
|
||||
LOGOUT_PAGE_FILTER,
|
||||
|
|
|
@ -109,7 +109,7 @@ public class UserDetailsServiceFactoryBean implements ApplicationContextAware {
|
|||
}
|
||||
if (beans.size() > 1) {
|
||||
throw new ApplicationContextException("More than one UserDetailsService registered. Please "
|
||||
+ "use a specific Id reference in <remember-me/> <openid-login/> or <x509 /> elements.");
|
||||
+ "use a specific Id reference in <remember-me/> or <x509 /> elements.");
|
||||
}
|
||||
return (UserDetailsService) beans.values().toArray()[0];
|
||||
}
|
||||
|
|
|
@ -312,7 +312,7 @@ http-firewall =
|
|||
|
||||
http =
|
||||
## Container element for HTTP security configuration. Multiple elements can now be defined, each with a specific pattern to which the enclosed security configuration applies. A pattern can also be configured to bypass Spring Security's filters completely by setting the "security" attribute to "none".
|
||||
element http {http.attlist, (intercept-url* & access-denied-handler? & form-login? & oauth2-login? & oauth2-client? & oauth2-resource-server? & openid-login? & x509? & jee? & http-basic? & logout? & password-management? & session-management & remember-me? & anonymous? & port-mappings & custom-filter* & request-cache? & expression-handler? & headers? & csrf? & cors?) }
|
||||
element http {http.attlist, (intercept-url* & access-denied-handler? & form-login? & oauth2-login? & oauth2-client? & oauth2-resource-server? & x509? & jee? & http-basic? & logout? & password-management? & session-management & remember-me? & anonymous? & port-mappings & custom-filter* & request-cache? & expression-handler? & headers? & csrf? & cors?) }
|
||||
http.attlist &=
|
||||
## The request URL pattern which will be mapped to the filter chain created by this <http> element. If omitted, the filter chain will match all requests.
|
||||
attribute pattern {xsd:token}?
|
||||
|
@ -630,36 +630,6 @@ opaque-token.attlist &=
|
|||
## Reference to an OpaqueTokenIntrospector
|
||||
attribute introspector-ref {xsd:token}?
|
||||
|
||||
openid-login =
|
||||
## Sets up form login for authentication with an Open ID identity. NOTE: The OpenID 1.0 and 2.0 protocols have been deprecated and users are <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is supported by <code>spring-security-oauth2</code>.
|
||||
element openid-login {form-login.attlist, user-service-ref?, attribute-exchange*}
|
||||
|
||||
attribute-exchange =
|
||||
## Sets up an attribute exchange configuration to request specified attributes from the OpenID identity provider. When multiple elements are used, each must have an identifier-attribute attribute. Each configuration will be matched in turn against the supplied login identifier until a match is found.
|
||||
element attribute-exchange {attribute-exchange.attlist, openid-attribute+}
|
||||
|
||||
attribute-exchange.attlist &=
|
||||
## A regular expression which will be compared against the claimed identity, when deciding which attribute-exchange configuration to use during authentication.
|
||||
attribute identifier-match {xsd:token}?
|
||||
|
||||
openid-attribute =
|
||||
## Attributes used when making an OpenID AX Fetch Request. NOTE: The OpenID 1.0 and 2.0 protocols have been deprecated and users are <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is supported by <code>spring-security-oauth2</code>.
|
||||
element openid-attribute {openid-attribute.attlist}
|
||||
|
||||
openid-attribute.attlist &=
|
||||
## Specifies the name of the attribute that you wish to get back. For example, email.
|
||||
attribute name {xsd:token}
|
||||
openid-attribute.attlist &=
|
||||
## Specifies the attribute type. For example, https://axschema.org/contact/email. See your OP's documentation for valid attribute types.
|
||||
attribute type {xsd:token}
|
||||
openid-attribute.attlist &=
|
||||
## Specifies if this attribute is required to the OP, but does not error out if the OP does not return the attribute. Default is false.
|
||||
attribute required {xsd:boolean}?
|
||||
openid-attribute.attlist &=
|
||||
## Specifies the number of attributes that you wish to get back. For example, return 3 emails. The default value is 1.
|
||||
attribute count {xsd:int}?
|
||||
|
||||
|
||||
filter-chain-map =
|
||||
## Used to explicitly configure a FilterChainProxy instance with a FilterChainMap
|
||||
element filter-chain-map {filter-chain-map.attlist, filter-chain+}
|
||||
|
@ -1148,4 +1118,4 @@ position =
|
|||
## The explicit position at which the custom-filter should be placed in the chain. Use if you are replacing a standard filter.
|
||||
attribute position {named-security-filter}
|
||||
|
||||
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "SECURITY_CONTEXT_FILTER" | "CONCURRENT_SESSION_FILTER" | "WEB_ASYNC_MANAGER_FILTER" | "HEADERS_FILTER" | "CORS_FILTER" | "CSRF_FILTER" | "LOGOUT_FILTER" | "OAUTH2_AUTHORIZATION_REQUEST_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "OAUTH2_LOGIN_FILTER" | "FORM_LOGIN_FILTER" | "OPENID_FILTER" | "LOGIN_PAGE_FILTER" |"LOGOUT_PAGE_FILTER" | "DIGEST_AUTH_FILTER" | "BEARER_TOKEN_AUTH_FILTER" | "BASIC_AUTH_FILTER" | "REQUEST_CACHE_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "JAAS_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER" | "WELL_KNOWN_CHANGE_PASSWORD_REDIRECT_FILTER" | "SESSION_MANAGEMENT_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
||||
named-security-filter = "FIRST" | "CHANNEL_FILTER" | "SECURITY_CONTEXT_FILTER" | "CONCURRENT_SESSION_FILTER" | "WEB_ASYNC_MANAGER_FILTER" | "HEADERS_FILTER" | "CORS_FILTER" | "CSRF_FILTER" | "LOGOUT_FILTER" | "OAUTH2_AUTHORIZATION_REQUEST_FILTER" | "X509_FILTER" | "PRE_AUTH_FILTER" | "CAS_FILTER" | "OAUTH2_LOGIN_FILTER" | "FORM_LOGIN_FILTER" | "LOGIN_PAGE_FILTER" |"LOGOUT_PAGE_FILTER" | "DIGEST_AUTH_FILTER" | "BEARER_TOKEN_AUTH_FILTER" | "BASIC_AUTH_FILTER" | "REQUEST_CACHE_FILTER" | "SERVLET_API_SUPPORT_FILTER" | "JAAS_API_SUPPORT_FILTER" | "REMEMBER_ME_FILTER" | "ANONYMOUS_FILTER" | "OAUTH2_AUTHORIZATION_CODE_GRANT_FILTER" | "WELL_KNOWN_CHANGE_PASSWORD_REDIRECT_FILTER" | "SESSION_MANAGEMENT_FILTER" | "EXCEPTION_TRANSLATION_FILTER" | "FILTER_SECURITY_INTERCEPTOR" | "SWITCH_USER_FILTER" | "LAST"
|
||||
|
|
|
@ -1015,28 +1015,6 @@
|
|||
<xs:element ref="security:oauth2-login"/>
|
||||
<xs:element ref="security:oauth2-client"/>
|
||||
<xs:element ref="security:oauth2-resource-server"/>
|
||||
<xs:element name="openid-login">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Sets up form login for authentication with an Open ID identity. NOTE: The OpenID 1.0 and
|
||||
2.0 protocols have been deprecated and users are <a
|
||||
href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
supported by <code>spring-security-oauth2</code>.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs="0" maxOccurs="unbounded" ref="security:attribute-exchange"/>
|
||||
</xs:sequence>
|
||||
<xs:attributeGroup ref="security:form-login.attlist"/>
|
||||
<xs:attribute name="user-service-ref" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A reference to a user-service (or UserDetailsService bean) Id
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="x509">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Adds support for X.509 client authentication.
|
||||
|
@ -1942,73 +1920,6 @@
|
|||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
|
||||
<xs:element name="attribute-exchange">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Sets up an attribute exchange configuration to request specified attributes from the
|
||||
OpenID identity provider. When multiple elements are used, each must have an
|
||||
identifier-attribute attribute. Each configuration will be matched in turn against the
|
||||
supplied login identifier until a match is found.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element maxOccurs="unbounded" ref="security:openid-attribute"/>
|
||||
</xs:sequence>
|
||||
<xs:attributeGroup ref="security:attribute-exchange.attlist"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:attributeGroup name="attribute-exchange.attlist">
|
||||
<xs:attribute name="identifier-match" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>A regular expression which will be compared against the claimed identity, when deciding
|
||||
which attribute-exchange configuration to use during authentication.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="openid-attribute">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Attributes used when making an OpenID AX Fetch Request. NOTE: The OpenID 1.0 and 2.0
|
||||
protocols have been deprecated and users are <a
|
||||
href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
supported by <code>spring-security-oauth2</code>.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
<xs:complexType>
|
||||
<xs:attributeGroup ref="security:openid-attribute.attlist"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:attributeGroup name="openid-attribute.attlist">
|
||||
<xs:attribute name="name" use="required" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies the name of the attribute that you wish to get back. For example, email.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="type" use="required" type="xs:token">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies the attribute type. For example, https://axschema.org/contact/email. See your
|
||||
OP's documentation for valid attribute types.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="required" type="xs:boolean">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies if this attribute is required to the OP, but does not error out if the OP does
|
||||
not return the attribute. Default is false.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="count" type="xs:int">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Specifies the number of attributes that you wish to get back. For example, return 3
|
||||
emails. The default value is 1.
|
||||
</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
</xs:attributeGroup>
|
||||
<xs:element name="filter-chain-map">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Used to explicitly configure a FilterChainProxy instance with a FilterChainMap
|
||||
|
@ -3335,7 +3246,6 @@
|
|||
<xs:enumeration value="CAS_FILTER"/>
|
||||
<xs:enumeration value="OAUTH2_LOGIN_FILTER"/>
|
||||
<xs:enumeration value="FORM_LOGIN_FILTER"/>
|
||||
<xs:enumeration value="OPENID_FILTER"/>
|
||||
<xs:enumeration value="LOGIN_PAGE_FILTER"/>
|
||||
<xs:enumeration value="LOGOUT_PAGE_FILTER"/>
|
||||
<xs:enumeration value="DIGEST_AUTH_FILTER"/>
|
||||
|
|
|
@ -260,87 +260,6 @@ public class DefaultLoginPageConfigurerTests {
|
|||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginPageWhenOpenIdLoginConfiguredThenOpedIdLoginPage() throws Exception {
|
||||
this.spring.register(DefaultLoginPageWithOpenIDConfig.class).autowire();
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"/login/openid\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loginPageWhenOpenIdLoginAndFormLoginAndRememberMeConfiguredThenOpedIdLoginPage() throws Exception {
|
||||
this.spring.register(DefaultLoginPageWithFormLoginOpenIDRememberMeConfig.class).autowire();
|
||||
CsrfToken csrfToken = new DefaultCsrfToken("X-CSRF-TOKEN", "_csrf", "BaseSpringSpec_CSRFTOKEN");
|
||||
String csrfAttributeName = HttpSessionCsrfTokenRepository.class.getName().concat(".CSRF_TOKEN");
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login").sessionAttr(csrfAttributeName, csrfToken))
|
||||
.andExpect(content().string("<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n" + " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ "<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ " <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"/login/openid\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n"
|
||||
+ " <p>\n" + " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ "<p><input type='checkbox' name='remember-me'/> Remember me on this computer.</p>\n"
|
||||
+ "<input name=\"" + csrfToken.getParameterName() + "\" type=\"hidden\" value=\"" + csrfToken.getToken() + "\" />\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenRegisteringObjectPostProcessorThenInvokedOnDefaultLoginPageGeneratingFilter() {
|
||||
ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
|
||||
|
@ -472,42 +391,6 @@ public class DefaultLoginPageConfigurerTests {
|
|||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class DefaultLoginPageWithOpenIDConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().hasRole("USER")
|
||||
.and()
|
||||
.openidLogin();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class DefaultLoginPageWithFormLoginOpenIDRememberMeConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().hasRole("USER")
|
||||
.and()
|
||||
.rememberMe()
|
||||
.and()
|
||||
.formLogin()
|
||||
.and()
|
||||
.openidLogin();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class DefaultLoginWithCustomAuthenticationEntryPointConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
|
|
|
@ -1,299 +0,0 @@
|
|||
/*
|
||||
* 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.config.annotation.web.configurers;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.openid4java.consumer.ConsumerManager;
|
||||
import org.openid4java.discovery.DiscoveryInformation;
|
||||
import org.openid4java.discovery.yadis.YadisResolver;
|
||||
import org.openid4java.message.AuthRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.config.annotation.ObjectPostProcessor;
|
||||
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.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.openid.OpenIDAttribute;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationFilter;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationStatus;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationToken;
|
||||
import org.springframework.security.openid.OpenIDConsumer;
|
||||
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
|
||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.csrf;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Tests to verify that all the functionality of <openid-login> attributes is
|
||||
* present
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Josh Cummings
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class NamespaceHttpOpenIDLoginTests {
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Autowired
|
||||
MockMvc mvc;
|
||||
|
||||
@Test
|
||||
public void openidLoginWhenUsingDefaultsThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(OpenIDLoginConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/login"));
|
||||
this.mvc.perform(post("/login/openid").with(csrf())).andExpect(redirectedUrl("/login?error"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openidLoginWhenAttributeExchangeConfiguredThenFetchAttributesMatchAttributeList() throws Exception {
|
||||
OpenIDLoginAttributeExchangeConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
|
||||
AuthRequest mockAuthRequest = mock(AuthRequest.class);
|
||||
DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class);
|
||||
given(mockAuthRequest.getDestinationUrl(anyBoolean())).willReturn("mockUrl");
|
||||
given(OpenIDLoginAttributeExchangeConfig.CONSUMER_MANAGER.associate(any()))
|
||||
.willReturn(mockDiscoveryInformation);
|
||||
given(OpenIDLoginAttributeExchangeConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(),
|
||||
any())).willReturn(mockAuthRequest);
|
||||
this.spring.register(OpenIDLoginAttributeExchangeConfig.class).autowire();
|
||||
try (MockWebServer server = new MockWebServer()) {
|
||||
String endpoint = server.url("/").toString();
|
||||
server.enqueue(new MockResponse().addHeader(YadisResolver.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, "https://www.google.com/1"))
|
||||
.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) -> "firstname".equals(attribute.getName())
|
||||
&& "https://axschema.org/namePerson/first".equals(attribute.getType()) && attribute.isRequired()))
|
||||
.isTrue();
|
||||
assertThat(attributeList.stream().anyMatch((attribute) -> "lastname".equals(attribute.getName())
|
||||
&& "https://axschema.org/namePerson/last".equals(attribute.getType()) && attribute.isRequired()))
|
||||
.isTrue();
|
||||
assertThat(attributeList.stream().anyMatch((attribute) -> "email".equals(attribute.getName())
|
||||
&& "https://axschema.org/contact/email".equals(attribute.getType()) && attribute.isRequired()))
|
||||
.isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openidLoginWhenUsingCustomEndpointsThenMatchesNamespace() throws Exception {
|
||||
this.spring.register(OpenIDLoginCustomConfig.class).autowire();
|
||||
this.mvc.perform(get("/")).andExpect(redirectedUrl("http://localhost/authentication/login"));
|
||||
this.mvc.perform(post("/authentication/login/process").with(csrf()))
|
||||
.andExpect(redirectedUrl("/authentication/login?failed"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openidLoginWithCustomHandlersThenBehaviorMatchesNamespace() throws Exception {
|
||||
OpenIDAuthenticationToken token = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS,
|
||||
"identityUrl", "message", Arrays.asList(new OpenIDAttribute("name", "type")));
|
||||
OpenIDLoginCustomRefsConfig.AUDS = mock(AuthenticationUserDetailsService.class);
|
||||
User user = new User("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"));
|
||||
given(OpenIDLoginCustomRefsConfig.AUDS.loadUserDetails(any(Authentication.class))).willReturn(user);
|
||||
OpenIDLoginCustomRefsConfig.ADS = spy(new WebAuthenticationDetailsSource());
|
||||
OpenIDLoginCustomRefsConfig.CONSUMER = mock(OpenIDConsumer.class);
|
||||
this.spring.register(OpenIDLoginCustomRefsConfig.class, UserDetailsServiceConfig.class).autowire();
|
||||
given(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class)))
|
||||
.willThrow(new AuthenticationServiceException("boom"));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder login = post("/login/openid")
|
||||
.with(csrf())
|
||||
.param("openid.identity", "identity");
|
||||
// @formatter:on
|
||||
this.mvc.perform(login).andExpect(redirectedUrl("/custom/failure"));
|
||||
reset(OpenIDLoginCustomRefsConfig.CONSUMER);
|
||||
given(OpenIDLoginCustomRefsConfig.CONSUMER.endConsumption(any(HttpServletRequest.class))).willReturn(token);
|
||||
this.mvc.perform(login).andExpect(redirectedUrl("/custom/targetUrl"));
|
||||
verify(OpenIDLoginCustomRefsConfig.AUDS).loadUserDetails(any(Authentication.class));
|
||||
verify(OpenIDLoginCustomRefsConfig.ADS).buildDetails(any(Object.class));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class OpenIDLoginConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().hasRole("USER")
|
||||
.and()
|
||||
.openidLogin()
|
||||
.permitAll();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class OpenIDLoginAttributeExchangeConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
static ConsumerManager CONSUMER_MANAGER;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().hasRole("USER")
|
||||
.and()
|
||||
.openidLogin()
|
||||
.consumerManager(CONSUMER_MANAGER)
|
||||
.attributeExchange("https://www.google.com/.*") // attribute-exchange@identifier-match
|
||||
.attribute("email") // openid-attribute@name
|
||||
.type("https://axschema.org/contact/email") // openid-attribute@type
|
||||
.required(true) // openid-attribute@required
|
||||
.count(1) // openid-attribute@count
|
||||
.and()
|
||||
.attribute("firstname")
|
||||
.type("https://axschema.org/namePerson/first")
|
||||
.required(true)
|
||||
.and()
|
||||
.attribute("lastname")
|
||||
.type("https://axschema.org/namePerson/last")
|
||||
.required(true)
|
||||
.and()
|
||||
.and()
|
||||
.attributeExchange(".*yahoo.com.*")
|
||||
.attribute("email")
|
||||
.type("https://schema.openid.net/contact/email")
|
||||
.required(true)
|
||||
.and()
|
||||
.attribute("fullname")
|
||||
.type("https://axschema.org/namePerson")
|
||||
.required(true)
|
||||
.and()
|
||||
.and()
|
||||
.permitAll();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class OpenIDLoginCustomConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
boolean alwaysUseDefaultSuccess = true;
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().hasRole("USER")
|
||||
.and()
|
||||
.openidLogin()
|
||||
.permitAll()
|
||||
.loginPage("/authentication/login") // openid-login@login-page
|
||||
.failureUrl("/authentication/login?failed") // openid-login@authentication-failure-url
|
||||
.loginProcessingUrl("/authentication/login/process") // openid-login@login-processing-url
|
||||
.defaultSuccessUrl("/default", alwaysUseDefaultSuccess); // openid-login@default-target-url / openid-login@always-use-default-target
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
static class OpenIDLoginCustomRefsConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
static AuthenticationUserDetailsService AUDS;
|
||||
static AuthenticationDetailsSource ADS;
|
||||
static OpenIDConsumer CONSUMER;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
SavedRequestAwareAuthenticationSuccessHandler handler = new SavedRequestAwareAuthenticationSuccessHandler();
|
||||
handler.setDefaultTargetUrl("/custom/targetUrl");
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().hasRole("USER")
|
||||
.and()
|
||||
.openidLogin()
|
||||
// if using UserDetailsService wrap with new UserDetailsByNameServiceWrapper<OpenIDAuthenticationToken>()
|
||||
.authenticationUserDetailsService(AUDS) // openid-login@user-service-ref
|
||||
.failureHandler(new SimpleUrlAuthenticationFailureHandler("/custom/failure")) // openid-login@authentication-failure-handler-ref
|
||||
.successHandler(handler) // openid-login@authentication-success-handler-ref
|
||||
.authenticationDetailsSource(ADS) // openid-login@authentication-details-source-ref
|
||||
.withObjectPostProcessor(new ObjectPostProcessor<OpenIDAuthenticationFilter>() {
|
||||
@Override
|
||||
public <O extends OpenIDAuthenticationFilter> O postProcess(O filter) {
|
||||
filter.setConsumer(CONSUMER);
|
||||
return filter;
|
||||
}
|
||||
});
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class UserDetailsServiceConfig {
|
||||
|
||||
@Bean
|
||||
UserDetailsService userDetailsService() {
|
||||
return new InMemoryUserDetailsManager(
|
||||
User.withDefaultPasswordEncoder().username("user").password("password").roles("USER").build());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,312 +0,0 @@
|
|||
/*
|
||||
* 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.config.annotation.web.configurers.openid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.openid4java.consumer.ConsumerManager;
|
||||
import org.openid4java.discovery.DiscoveryInformation;
|
||||
import org.openid4java.discovery.yadis.YadisResolver;
|
||||
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;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
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.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
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 org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Tests for {@link OpenIDLoginConfigurer}
|
||||
*
|
||||
* @author Rob Winch
|
||||
* @author Eleftheria Stein
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class OpenIDLoginConfigurerTests {
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Autowired
|
||||
MockMvc mvc;
|
||||
|
||||
@Test
|
||||
public void configureWhenRegisteringObjectPostProcessorThenInvokedOnOpenIDAuthenticationFilter() {
|
||||
ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
|
||||
this.spring.register(ObjectPostProcessorConfig.class).autowire();
|
||||
verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(OpenIDAuthenticationFilter.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenRegisteringObjectPostProcessorThenInvokedOnOpenIDAuthenticationProvider() {
|
||||
ObjectPostProcessorConfig.objectPostProcessor = spy(ReflectingObjectPostProcessor.class);
|
||||
this.spring.register(ObjectPostProcessorConfig.class).autowire();
|
||||
verify(ObjectPostProcessorConfig.objectPostProcessor).postProcess(any(OpenIDAuthenticationProvider.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void openidLoginWhenInvokedTwiceThenUsesOriginalLoginPage() throws Exception {
|
||||
this.spring.register(InvokeTwiceDoesNotOverrideConfig.class).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login/custom"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenOpenIdLoginPageInLambdaThenRedirectsToLoginPAge() throws Exception {
|
||||
this.spring.register(OpenIdLoginPageInLambdaConfig.class).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/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);
|
||||
given(mockAuthRequest.getDestinationUrl(anyBoolean())).willReturn("mockUrl");
|
||||
given(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.associate(any())).willReturn(mockDiscoveryInformation);
|
||||
given(OpenIdAttributesInLambdaConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(),
|
||||
any())).willReturn(mockAuthRequest);
|
||||
this.spring.register(OpenIdAttributesInLambdaConfig.class).autowire();
|
||||
try (MockWebServer server = new MockWebServer()) {
|
||||
String endpoint = server.url("/").toString();
|
||||
server.enqueue(new MockResponse().addHeader(YadisResolver.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();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenAttributeNameNotSpecifiedThenAttributeNameDefaulted() throws Exception {
|
||||
OpenIdAttributesNullNameConfig.CONSUMER_MANAGER = mock(ConsumerManager.class);
|
||||
AuthRequest mockAuthRequest = mock(AuthRequest.class);
|
||||
DiscoveryInformation mockDiscoveryInformation = mock(DiscoveryInformation.class);
|
||||
given(mockAuthRequest.getDestinationUrl(anyBoolean())).willReturn("mockUrl");
|
||||
given(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.associate(any())).willReturn(mockDiscoveryInformation);
|
||||
given(OpenIdAttributesNullNameConfig.CONSUMER_MANAGER.authenticate(any(DiscoveryInformation.class), any(),
|
||||
any())).willReturn(mockAuthRequest);
|
||||
this.spring.register(OpenIdAttributesNullNameConfig.class).autowire();
|
||||
try (MockWebServer server = new MockWebServer()) {
|
||||
String endpoint = server.url("/").toString();
|
||||
server.enqueue(new MockResponse().addHeader(YadisResolver.YADIS_XRDS_LOCATION, endpoint));
|
||||
server.enqueue(new MockResponse()
|
||||
.setBody(String.format("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", endpoint)));
|
||||
// @formatter:off
|
||||
MockHttpServletRequestBuilder request = get("/login/openid")
|
||||
.param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint);
|
||||
MvcResult mvcResult = this.mvc.perform(request)
|
||||
.andExpect(status().isFound())
|
||||
.andReturn();
|
||||
Object attributeObject = mvcResult.getRequest().getSession()
|
||||
.getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST");
|
||||
// @formatter:on
|
||||
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 ObjectPostProcessorConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
static ObjectPostProcessor<Object> objectPostProcessor;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.openidLogin();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Bean
|
||||
static ObjectPostProcessor<Object> objectPostProcessor() {
|
||||
return objectPostProcessor;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class ReflectingObjectPostProcessor implements ObjectPostProcessor<Object> {
|
||||
|
||||
@Override
|
||||
public <O> O postProcess(O object) {
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@EnableWebSecurity
|
||||
static class InvokeTwiceDoesNotOverrideConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Override
|
||||
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
// @formatter:off
|
||||
auth
|
||||
.inMemoryAuthentication();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.authorizeRequests()
|
||||
.anyRequest().authenticated()
|
||||
.and()
|
||||
.openidLogin()
|
||||
.loginPage("/login/custom")
|
||||
.and()
|
||||
.openidLogin();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@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
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -92,21 +92,6 @@ public class UserServiceBeanDefinitionParserTests {
|
|||
Long.parseLong(joe.getPassword());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void worksWithOpenIDUrlsAsNames() {
|
||||
// @formatter:off
|
||||
setContext("<user-service id='service'>"
|
||||
+ " <user name='https://joe.myopenid.com/' authorities='ROLE_A'/>"
|
||||
+ " <user name='https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9' authorities='ROLE_A'/>"
|
||||
+ "</user-service>");
|
||||
// @formatter:on
|
||||
UserDetailsService userService = (UserDetailsService) this.appContext.getBean("service");
|
||||
assertThat(userService.loadUserByUsername("https://joe.myopenid.com/").getUsername())
|
||||
.isEqualTo("https://joe.myopenid.com/");
|
||||
assertThat(userService.loadUserByUsername("https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9")
|
||||
.getUsername()).isEqualTo("https://www.google.com/accounts/o8/id?id=MPtOaenBIk5yzW9n7n9");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void disabledAndEmbeddedFlagsAreSupported() {
|
||||
// @formatter:off
|
||||
|
|
|
@ -129,91 +129,6 @@ public class FormLoginBeanDefinitionParserTests {
|
|||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLoginWhenConfiguredForOpenIdThenLoginPageReflects() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithOpenId")).autowire();
|
||||
// @formatter:off
|
||||
String expectedContent = "<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ " <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"/login/openid\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>";
|
||||
// @formatter:on
|
||||
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getLoginWhenConfiguredForOpenIdWithCustomAttributesThenLoginPageReflects() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithOpenIdCustomAttributes")).autowire();
|
||||
// @formatter:off
|
||||
String expectedContent = "<!DOCTYPE html>\n"
|
||||
+ "<html lang=\"en\">\n"
|
||||
+ " <head>\n"
|
||||
+ " <meta charset=\"utf-8\">\n"
|
||||
+ " <meta name=\"viewport\" content=\"width=device-width, initial-scale=1, shrink-to-fit=no\">\n"
|
||||
+ " <meta name=\"description\" content=\"\">\n"
|
||||
+ " <meta name=\"author\" content=\"\">\n"
|
||||
+ " <title>Please sign in</title>\n"
|
||||
+ " <link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css\" rel=\"stylesheet\" integrity=\"sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M\" crossorigin=\"anonymous\">\n"
|
||||
+ " <link href=\"https://getbootstrap.com/docs/4.0/examples/signin/signin.css\" rel=\"stylesheet\" crossorigin=\"anonymous\"/>\n"
|
||||
+ " </head>\n"
|
||||
+ " <body>\n"
|
||||
+ " <div class=\"container\">\n"
|
||||
+ " <form class=\"form-signin\" method=\"post\" action=\"/login\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Please sign in</h2>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Username</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"username\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <p>\n"
|
||||
+ " <label for=\"password\" class=\"sr-only\">Password</label>\n"
|
||||
+ " <input type=\"password\" id=\"password\" name=\"password\" class=\"form-control\" placeholder=\"Password\" required>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ " <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"/signin\">\n"
|
||||
+ " <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n" + " <p>\n"
|
||||
+ " <label for=\"username\" class=\"sr-only\">Identity</label>\n"
|
||||
+ " <input type=\"text\" id=\"username\" name=\"openid_identifier\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n"
|
||||
+ " </p>\n"
|
||||
+ " <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n"
|
||||
+ " </form>\n"
|
||||
+ "</div>\n"
|
||||
+ "</body></html>";
|
||||
// @formatter:on
|
||||
this.mvc.perform(get("/login")).andExpect(content().string(expectedContent));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failedLoginWhenConfiguredWithCustomAuthenticationFailureThenForwardsAccordingly() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithAuthenticationFailureForwardUrl")).autowire();
|
||||
|
|
|
@ -78,7 +78,6 @@ import org.springframework.security.core.authority.AuthorityUtils;
|
|||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationFilter;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.access.ExceptionTranslationFilter;
|
||||
|
@ -105,7 +104,6 @@ import org.springframework.security.web.savedrequest.RequestCache;
|
|||
import org.springframework.security.web.savedrequest.RequestCacheAwareFilter;
|
||||
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||
import org.springframework.security.web.session.SessionManagementFilter;
|
||||
import org.springframework.test.util.ReflectionTestUtils;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.MvcResult;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
|
@ -624,8 +622,6 @@ public class MiscHttpConfigTests {
|
|||
this.mvc.perform(get("/details").session(session))
|
||||
.andExpect(content().string(details.getClass().getName()));
|
||||
// @formatter:on
|
||||
assertThat(ReflectionTestUtils.getField(getFilter(OpenIDAuthenticationFilter.class),
|
||||
"authenticationDetailsSource")).isEqualTo(source);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -1,203 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2018 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.config.http;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.servlet.Filter;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import okhttp3.mockwebserver.MockResponse;
|
||||
import okhttp3.mockwebserver.MockWebServer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.openid4java.consumer.ConsumerManager;
|
||||
import org.openid4java.discovery.yadis.YadisResolver;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.parsing.BeanDefinitionParsingException;
|
||||
import org.springframework.security.config.test.SpringTestContext;
|
||||
import org.springframework.security.config.test.SpringTestContextExtension;
|
||||
import org.springframework.security.openid.OpenID4JavaConsumer;
|
||||
import org.springframework.security.openid.OpenIDAuthenticationFilter;
|
||||
import org.springframework.security.openid.OpenIDConsumer;
|
||||
import org.springframework.security.util.FieldUtils;
|
||||
import org.springframework.security.web.FilterChainProxy;
|
||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.redirectedUrl;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* Tests usage of the <openid-login> element
|
||||
*
|
||||
* @author Luke Taylor
|
||||
*/
|
||||
@ExtendWith(SpringTestContextExtension.class)
|
||||
public class OpenIDConfigTests {
|
||||
|
||||
private static final String CONFIG_LOCATION_PREFIX = "classpath:org/springframework/security/config/http/OpenIDConfigTests";
|
||||
|
||||
@Autowired
|
||||
MockMvc mvc;
|
||||
|
||||
public final SpringTestContext spring = new SpringTestContext(this);
|
||||
|
||||
@Test
|
||||
public void requestWhenOpenIDAndFormLoginBothConfiguredThenRedirectsToGeneratedLoginPage() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithFormLogin")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
// @formatter:on
|
||||
assertThat(getFilter(DefaultLoginPageGeneratingFilter.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenOpenIDAndFormLoginWithFormLoginPageConfiguredThenFormLoginPageWins() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithFormLoginPage")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/form-page"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenOpenIDAndFormLoginWithOpenIDLoginPageConfiguredThenOpenIDLoginPageWins() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithOpenIDLoginPageAndFormLogin")).autowire();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/openid-page"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void configureWhenOpenIDAndFormLoginBothConfigureLoginPagesThenWiringException() {
|
||||
assertThatExceptionOfType(BeanDefinitionParsingException.class)
|
||||
.isThrownBy(() -> this.spring.configLocations(this.xml("WithFormLoginAndOpenIDLoginPages")).autowire());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenOpenIDAndRememberMeConfiguredThenRememberMePassedToIdp() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithRememberMe")).autowire();
|
||||
OpenIDAuthenticationFilter openIDFilter = getFilter(OpenIDAuthenticationFilter.class);
|
||||
String openIdEndpointUrl = "https://testopenid.com?openid.return_to=";
|
||||
Set<String> returnToUrlParameters = new HashSet<>();
|
||||
returnToUrlParameters.add(AbstractRememberMeServices.DEFAULT_PARAMETER);
|
||||
openIDFilter.setReturnToUrlParameters(returnToUrlParameters);
|
||||
OpenIDConsumer consumer = mock(OpenIDConsumer.class);
|
||||
given(consumer.beginConsumption(any(HttpServletRequest.class), anyString(), anyString(), anyString()))
|
||||
.will((invocation) -> openIdEndpointUrl + invocation.getArgument(2));
|
||||
openIDFilter.setConsumer(consumer);
|
||||
String expectedReturnTo = new StringBuilder("http://localhost/login/openid").append("?")
|
||||
.append(AbstractRememberMeServices.DEFAULT_PARAMETER).append("=").append("on").toString();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/"))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl("http://localhost/login"));
|
||||
this.mvc.perform(get("/login"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string(containsString(AbstractRememberMeServices.DEFAULT_PARAMETER)));
|
||||
MockHttpServletRequestBuilder openidLogin = get("/login/openid")
|
||||
.param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, "https://ww1.openid.com")
|
||||
.param(AbstractRememberMeServices.DEFAULT_PARAMETER, "on");
|
||||
this.mvc.perform(openidLogin)
|
||||
.andExpect(status().isFound())
|
||||
.andExpect(redirectedUrl(openIdEndpointUrl + expectedReturnTo));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Test
|
||||
public void requestWhenAttributeExchangeConfiguredThenFetchAttributesPassedToIdp() throws Exception {
|
||||
this.spring.configLocations(this.xml("WithOpenIDAttributes")).autowire();
|
||||
OpenIDAuthenticationFilter openIDFilter = getFilter(OpenIDAuthenticationFilter.class);
|
||||
OpenID4JavaConsumer consumer = getFieldValue(openIDFilter, "consumer");
|
||||
ConsumerManager manager = getFieldValue(consumer, "consumerManager");
|
||||
manager.setMaxAssocAttempts(0);
|
||||
try (MockWebServer server = new MockWebServer()) {
|
||||
String endpoint = server.url("/").toString();
|
||||
server.enqueue(new MockResponse().addHeader(YadisResolver.YADIS_XRDS_LOCATION, endpoint));
|
||||
server.enqueue(new MockResponse()
|
||||
.setBody(String.format("<XRDS><XRD><Service><URI>%s</URI></Service></XRD></XRDS>", endpoint)));
|
||||
this.mvc.perform(
|
||||
get("/login/openid").param(OpenIDAuthenticationFilter.DEFAULT_CLAIMED_IDENTITY_FIELD, endpoint))
|
||||
.andExpect(status().isFound())
|
||||
.andExpect((result) -> result.getResponse().getRedirectedUrl().endsWith(
|
||||
"openid.ext1.type.nickname=http%3A%2F%2Fschema.openid.net%2FnamePerson%2Ffriendly&"
|
||||
+ "openid.ext1.if_available=nickname&"
|
||||
+ "openid.ext1.type.email=http%3A%2F%2Fschema.openid.net%2Fcontact%2Femail&"
|
||||
+ "openid.ext1.required=email&" + "openid.ext1.count.email=2"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SEC-2919
|
||||
*/
|
||||
@Test
|
||||
public void requestWhenLoginPageConfiguredWithPhraseLoginThenRedirectsOnlyToUserGeneratedLoginPage()
|
||||
throws Exception {
|
||||
this.spring.configLocations(this.xml("Sec2919")).autowire();
|
||||
assertThat(getFilter(DefaultLoginPageGeneratingFilter.class)).isNull();
|
||||
// @formatter:off
|
||||
this.mvc.perform(get("/login"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("a custom login page"));
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
private <T extends Filter> T getFilter(Class<T> clazz) {
|
||||
FilterChainProxy filterChain = this.spring.getContext().getBean(FilterChainProxy.class);
|
||||
return (T) filterChain.getFilters("/").stream().filter(clazz::isInstance).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
private String xml(String configName) {
|
||||
return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
|
||||
}
|
||||
|
||||
private static <T> T getFieldValue(Object bean, String fieldName) throws IllegalAccessException {
|
||||
return (T) FieldUtils.getFieldValue(bean, fieldName);
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class CustomLoginController {
|
||||
|
||||
@GetMapping("/login")
|
||||
String custom() {
|
||||
return "a custom login page";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 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.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security
|
||||
https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http auto-config="true">
|
||||
<openid-login/>
|
||||
<csrf disabled="true"/>
|
||||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
</b:beans>
|
|
@ -1,35 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 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.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security
|
||||
https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans
|
||||
https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http auto-config="true">
|
||||
<openid-login
|
||||
login-processing-url="/signin"/>
|
||||
|
||||
<csrf disabled="true"/>
|
||||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
</b:beans>
|
|
@ -28,7 +28,6 @@
|
|||
<http-basic authentication-details-source-ref="authenticationDetailsSource"/>
|
||||
<form-login authentication-details-source-ref="authenticationDetailsSource"/>
|
||||
<x509 subject-principal-regex="OU=(.*?)(?:,|$)" authentication-details-source-ref="authenticationDetailsSource"/>
|
||||
<openid-login authentication-details-source-ref="authenticationDetailsSource"/>
|
||||
</http>
|
||||
|
||||
<b:bean name="authenticationDetailsSource" class="org.mockito.Mockito" factory-method="mock">
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 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.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http use-expressions="true">
|
||||
<intercept-url pattern="/login" access="permitAll"/>
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<openid-login login-page="/login"/>
|
||||
</http>
|
||||
|
||||
<b:bean
|
||||
name="customLogin"
|
||||
class="org.springframework.security.config.http.OpenIDConfigTests.CustomLoginController"/>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
</b:beans>
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 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.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http use-expressions="true">
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<openid-login/>
|
||||
<form-login/>
|
||||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
</b:beans>
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 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.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http use-expressions="true">
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<openid-login login-page="/openid-page"/>
|
||||
<form-login login-page="/form-page"/>
|
||||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
</b:beans>
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 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.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http use-expressions="true">
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<openid-login/>
|
||||
<form-login login-page="/form-page"/>
|
||||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
</b:beans>
|
|
@ -1,36 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 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.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http use-expressions="true">
|
||||
<intercept-url pattern="/**" access="denyAll"/>
|
||||
<openid-login>
|
||||
<attribute-exchange>
|
||||
<openid-attribute name="nickname" type="https://schema.openid.net/namePerson/friendly"/>
|
||||
<openid-attribute name="email" type="https://schema.openid.net/contact/email" required="true" count="2"/>
|
||||
</attribute-exchange>
|
||||
</openid-login>
|
||||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
</b:beans>
|
|
@ -1,32 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 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.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http use-expressions="true">
|
||||
<intercept-url pattern="/**" access="authenticated"/>
|
||||
<openid-login login-page="/openid-page"/>
|
||||
<form-login/>
|
||||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
</b:beans>
|
|
@ -1,33 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2002-2018 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.
|
||||
-->
|
||||
|
||||
<b:beans xmlns:b="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/security"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
|
||||
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<http use-expressions="true">
|
||||
<intercept-url pattern="/**" access="denyAll"/>
|
||||
<openid-login/>
|
||||
<remember-me/>
|
||||
<csrf disabled="true"/>
|
||||
</http>
|
||||
|
||||
<b:import resource="userservice.xml"/>
|
||||
</b:beans>
|
|
@ -29,7 +29,7 @@ package org.springframework.security.authentication;
|
|||
* <p>
|
||||
* This might be thrown if a backend authentication repository is unavailable, for
|
||||
* example. However, it would not be thrown in the event that an error occurred when
|
||||
* validating an OpenID response with an OpenID Provider.
|
||||
* validating an OIDC response from an OIDC provider.
|
||||
* </p>
|
||||
*
|
||||
* @author Rob Winch
|
||||
|
|
|
@ -58,7 +58,6 @@ dependencies {
|
|||
api "org.mockito:mockito-core:3.12.4"
|
||||
api "org.mockito:mockito-inline:3.12.4"
|
||||
api "org.mockito:mockito-junit-jupiter:3.12.4"
|
||||
api "org.openid4java:openid4java-nodeps:0.9.6"
|
||||
api "org.opensaml:opensaml-core:$openSamlVersion"
|
||||
api "org.opensaml:opensaml-saml-api:$openSamlVersion"
|
||||
api "org.opensaml:opensaml-saml-impl:$openSamlVersion"
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
***** xref:servlet/authentication/passwords/ldap.adoc[LDAP]
|
||||
*** xref:servlet/authentication/session-management.adoc[Session Management]
|
||||
*** xref:servlet/authentication/rememberme.adoc[Remember Me]
|
||||
*** xref:servlet/authentication/openid.adoc[OpenID]
|
||||
*** xref:servlet/authentication/anonymous.adoc[Anonymous]
|
||||
*** xref:servlet/authentication/preauth.adoc[Pre-Authentication]
|
||||
*** xref:servlet/authentication/jaas.adoc[JAAS]
|
||||
|
|
|
@ -71,7 +71,7 @@ You can do so by adding a Maven property:
|
|||
----
|
||||
====
|
||||
|
||||
If you use additional features (such as LDAP, OpenID, and others), you need to also include the appropriate xref:modules.adoc#modules[Project Modules and Dependencies].
|
||||
If you use additional features (such as LDAP, OAuth 2, and others), you need to also include the appropriate xref:modules.adoc#modules[Project Modules and Dependencies].
|
||||
|
||||
[[getting-maven-no-boot]]
|
||||
=== Maven Without Spring Boot
|
||||
|
@ -117,7 +117,7 @@ A minimal Spring Security Maven set of dependencies typically looks like the fol
|
|||
----
|
||||
====
|
||||
|
||||
If you use additional features (such as LDAP, OpenID, and others), you need to also include the appropriate xref:modules.adoc#modules[Project Modules and Dependencies].
|
||||
If you use additional features (such as LDAP, OAuth 2, and others), you need to also include the appropriate xref:modules.adoc#modules[Project Modules and Dependencies].
|
||||
|
||||
Spring Security builds against Spring Framework {spring-core-version} but should generally work with any newer version of Spring Framework 5.x.
|
||||
Many users are likely to run afoul of the fact that Spring Security's transitive dependencies resolve Spring Framework {spring-core-version}, which can cause strange classpath problems.
|
||||
|
@ -238,7 +238,7 @@ ext['spring.version']='{spring-core-version}'
|
|||
----
|
||||
====
|
||||
|
||||
If you use additional features (such as LDAP, OpenID, and others), you need to also include the appropriate xref:modules.adoc#modules[Project Modules and Dependencies].
|
||||
If you use additional features (such as LDAP, OAuth 2, and others), you need to also include the appropriate xref:modules.adoc#modules[Project Modules and Dependencies].
|
||||
|
||||
=== Gradle Without Spring Boot
|
||||
|
||||
|
@ -276,7 +276,7 @@ dependencies {
|
|||
----
|
||||
====
|
||||
|
||||
If you use additional features (such as LDAP, OpenID, and others), you need to also include the appropriate xref:modules.adoc#modules[Project Modules and Dependencies].
|
||||
If you use additional features (such as LDAP, OAuth 2, and others), you need to also include the appropriate xref:modules.adoc#modules[Project Modules and Dependencies].
|
||||
|
||||
Spring Security builds against Spring Framework {spring-core-version} but should generally work with any newer version of Spring Framework 5.x.
|
||||
Many users are likely to run afoul of the fact that Spring Security's transitive dependencies resolve Spring Framework {spring-core-version}, which can cause strange classpath problems.
|
||||
|
|
|
@ -139,10 +139,6 @@ None of the classes are intended for direct use in an application.
|
|||
|
|
||||
| Required if you are using the LDAP namespace options (optional).
|
||||
|
||||
| spring-security-openid
|
||||
|
|
||||
| Required if you are using OpenID authentication (optional).
|
||||
|
||||
| aspectjweaver
|
||||
| 1.6.10
|
||||
| Required if using the protect-pointcut namespace syntax (optional).
|
||||
|
@ -275,44 +271,6 @@ This is the basis of the Spring Security integration.
|
|||
| Required if you are using the Ehcache-based ticket cache (optional).
|
||||
|===
|
||||
|
||||
[[spring-security-openid]]
|
||||
== OpenID -- `spring-security-openid.jar`
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The OpenID 1.0 and 2.0 protocols have been deprecated and users are encouraged to migrate to OpenID Connect, which is supported by spring-security-oauth2.
|
||||
====
|
||||
|
||||
This module contains OpenID web authentication support.
|
||||
It is used to authenticate users against an external OpenID server.
|
||||
The top-level package is `org.springframework.security.openid`.
|
||||
It requires OpenID4Java.
|
||||
|
||||
.OpenID Dependencies
|
||||
|===
|
||||
| Dependency | Version | Description
|
||||
|
||||
| spring-security-core
|
||||
|
|
||||
|
|
||||
|
||||
| spring-security-web
|
||||
|
|
||||
|
|
||||
|
||||
| openid4java-nodeps
|
||||
| 0.9.6
|
||||
| Spring Security's OpenID integration uses OpenID4Java.
|
||||
|
||||
| httpclient
|
||||
| 4.1.1
|
||||
| openid4java-nodeps depends on HttpClient 4.
|
||||
|
||||
| guice
|
||||
| 2.0
|
||||
| openid4java-nodeps depends on Guice 2.
|
||||
|===
|
||||
|
||||
|
||||
[[spring-security-test]]
|
||||
== Test -- `spring-security-test.jar`
|
||||
|
|
|
@ -159,7 +159,6 @@ The default value is true.
|
|||
* <<nsa-oauth2-client,oauth2-client>>
|
||||
* <<nsa-oauth2-login,oauth2-login>>
|
||||
* <<nsa-oauth2-resource-server,oauth2-resource-server>>
|
||||
* <<nsa-openid-login,openid-login>>
|
||||
* <<nsa-password-management,password-management>>
|
||||
* <<nsa-port-mappings,port-mappings>>
|
||||
* <<nsa-remember-me,remember-me>>
|
||||
|
@ -838,7 +837,7 @@ Used to add an `UsernamePasswordAuthenticationFilter` to the filter stack and an
|
|||
This will always take precedence over other namespace-created entry points.
|
||||
If no attributes are supplied, a login page will be generated automatically at the URL "/login" footnote:[
|
||||
This feature is really just provided for convenience and is not intended for production (where a view technology will have been chosen and can be used to render a customized login page).
|
||||
The class `DefaultLoginPageGeneratingFilter` is responsible for rendering the login page and will provide login forms for both normal form login and/or OpenID if required.
|
||||
The class `DefaultLoginPageGeneratingFilter` is responsible for rendering the login page and will provide login forms for both normal form login and/or OIDC if required.
|
||||
] The behaviour can be customized using the <<nsa-form-login-attributes, `<form-login>` Attributes>>.
|
||||
|
||||
|
||||
|
@ -1476,182 +1475,6 @@ Defaults to "/logout".
|
|||
May be used to supply an instance of `LogoutSuccessHandler` which will be invoked to control the navigation after logging out.
|
||||
|
||||
|
||||
[[nsa-openid-login]]
|
||||
== <openid-login>
|
||||
Similar to `<form-login>` and has the same attributes.
|
||||
The default value for `login-processing-url` is "/login/openid".
|
||||
An `OpenIDAuthenticationFilter` and `OpenIDAuthenticationProvider` will be registered.
|
||||
The latter requires a reference to a `UserDetailsService`.
|
||||
Again, this can be specified by `id`, using the `user-service-ref` attribute, or will be located automatically in the application context.
|
||||
|
||||
|
||||
[[nsa-openid-login-parents]]
|
||||
=== Parent Elements of <openid-login>
|
||||
|
||||
|
||||
* <<nsa-http,http>>
|
||||
|
||||
|
||||
|
||||
[[nsa-openid-login-attributes]]
|
||||
=== <openid-login> Attributes
|
||||
|
||||
|
||||
[[nsa-openid-login-always-use-default-target]]
|
||||
* **always-use-default-target**
|
||||
Whether the user should always be redirected to the default-target-url after login.
|
||||
|
||||
|
||||
[[nsa-openid-login-authentication-details-source-ref]]
|
||||
* **authentication-details-source-ref**
|
||||
Reference to an AuthenticationDetailsSource which will be used by the authentication filter
|
||||
|
||||
|
||||
[[nsa-openid-login-authentication-failure-handler-ref]]
|
||||
* **authentication-failure-handler-ref**
|
||||
Reference to an AuthenticationFailureHandler bean which should be used to handle a failed authentication request.
|
||||
Should not be used in combination with authentication-failure-url as the implementation should always deal with navigation to the subsequent destination
|
||||
|
||||
|
||||
[[nsa-openid-login-authentication-failure-url]]
|
||||
* **authentication-failure-url**
|
||||
The URL for the login failure page.
|
||||
If no login failure URL is specified, Spring Security will automatically create a failure login URL at /login?login_error and a corresponding filter to render that login failure URL when requested.
|
||||
|
||||
|
||||
[[nsa-openid-login-authentication-success-forward-url]]
|
||||
* **authentication-success-forward-url**
|
||||
Maps a `ForwardAuthenticationSuccessHandler` to `authenticationSuccessHandler` property of `UsernamePasswordAuthenticationFilter`.
|
||||
|
||||
|
||||
[[nsa-openid-login-authentication-failure-forward-url]]
|
||||
* **authentication-failure-forward-url**
|
||||
Maps a `ForwardAuthenticationFailureHandler` to `authenticationFailureHandler` property of `UsernamePasswordAuthenticationFilter`.
|
||||
|
||||
|
||||
[[nsa-openid-login-authentication-success-handler-ref]]
|
||||
* **authentication-success-handler-ref**
|
||||
Reference to an AuthenticationSuccessHandler bean which should be used to handle a successful authentication request.
|
||||
Should not be used in combination with <<nsa-openid-login-default-target-url,default-target-url>> (or <<nsa-openid-login-always-use-default-target, always-use-default-target>>) as the implementation should always deal with navigation to the subsequent destination
|
||||
|
||||
|
||||
[[nsa-openid-login-default-target-url]]
|
||||
* **default-target-url**
|
||||
The URL that will be redirected to after successful authentication, if the user's previous action could not be resumed.
|
||||
This generally happens if the user visits a login page without having first requested a secured operation that triggers authentication.
|
||||
If unspecified, defaults to the root of the application.
|
||||
|
||||
|
||||
[[nsa-openid-login-login-page]]
|
||||
* **login-page**
|
||||
The URL for the login page.
|
||||
If no login URL is specified, Spring Security will automatically create a login URL at /login and a corresponding filter to render that login URL when requested.
|
||||
|
||||
|
||||
[[nsa-openid-login-login-processing-url]]
|
||||
* **login-processing-url**
|
||||
The URL that the login form is posted to.
|
||||
If unspecified, it defaults to /login.
|
||||
|
||||
|
||||
[[nsa-openid-login-password-parameter]]
|
||||
* **password-parameter**
|
||||
The name of the request parameter which contains the password.
|
||||
Defaults to "password".
|
||||
|
||||
|
||||
[[nsa-openid-login-user-service-ref]]
|
||||
* **user-service-ref**
|
||||
A reference to a user-service (or UserDetailsService bean) Id
|
||||
|
||||
|
||||
[[nsa-openid-login-username-parameter]]
|
||||
* **username-parameter**
|
||||
The name of the request parameter which contains the username.
|
||||
Defaults to "username".
|
||||
|
||||
|
||||
[[nsa-openid-login-children]]
|
||||
=== Child Elements of <openid-login>
|
||||
* <<nsa-attribute-exchange,attribute-exchange>>
|
||||
|
||||
|
||||
|
||||
[[nsa-attribute-exchange]]
|
||||
== <attribute-exchange>
|
||||
The `attribute-exchange` element defines the list of attributes which should be requested from the identity provider.
|
||||
An example can be found in the xref:servlet/authentication/openid.adoc#servlet-openid[OpenID Support] section of the namespace configuration chapter.
|
||||
More than one can be used, in which case each must have an `identifier-match` attribute, containing a regular expression which is matched against the supplied OpenID identifier.
|
||||
This allows different attribute lists to be fetched from different providers (Google, Yahoo etc).
|
||||
|
||||
|
||||
[[nsa-attribute-exchange-parents]]
|
||||
=== Parent Elements of <attribute-exchange>
|
||||
|
||||
|
||||
* <<nsa-openid-login,openid-login>>
|
||||
|
||||
|
||||
|
||||
[[nsa-attribute-exchange-attributes]]
|
||||
=== <attribute-exchange> Attributes
|
||||
|
||||
|
||||
[[nsa-attribute-exchange-identifier-match]]
|
||||
* **identifier-match**
|
||||
A regular expression which will be compared against the claimed identity, when deciding which attribute-exchange configuration to use during authentication.
|
||||
|
||||
|
||||
[[nsa-attribute-exchange-children]]
|
||||
=== Child Elements of <attribute-exchange>
|
||||
|
||||
|
||||
* <<nsa-openid-attribute,openid-attribute>>
|
||||
|
||||
|
||||
|
||||
[[nsa-openid-attribute]]
|
||||
== <openid-attribute>
|
||||
Attributes used when making an OpenID AX https://openid.net/specs/openid-attribute-exchange-1_0.html#fetch_request[ Fetch Request]
|
||||
|
||||
|
||||
[[nsa-openid-attribute-parents]]
|
||||
=== Parent Elements of <openid-attribute>
|
||||
|
||||
|
||||
* <<nsa-attribute-exchange,attribute-exchange>>
|
||||
|
||||
|
||||
|
||||
[[nsa-openid-attribute-attributes]]
|
||||
=== <openid-attribute> Attributes
|
||||
|
||||
|
||||
[[nsa-openid-attribute-count]]
|
||||
* **count**
|
||||
Specifies the number of attributes that you wish to get back.
|
||||
For example, return 3 emails.
|
||||
The default value is 1.
|
||||
|
||||
|
||||
[[nsa-openid-attribute-name]]
|
||||
* **name**
|
||||
Specifies the name of the attribute that you wish to get back.
|
||||
For example, email.
|
||||
|
||||
|
||||
[[nsa-openid-attribute-required]]
|
||||
* **required**
|
||||
Specifies if this attribute is required to the OP, but does not error out if the OP does not return the attribute.
|
||||
Default is false.
|
||||
|
||||
|
||||
[[nsa-openid-attribute-type]]
|
||||
* **type**
|
||||
Specifies the attribute type.
|
||||
For example, https://axschema.org/contact/email.
|
||||
See your OP's documentation for valid attribute types.
|
||||
|
||||
[[nsa-password-management]]
|
||||
== <password-management>
|
||||
This element configures password management.
|
||||
|
|
|
@ -182,7 +182,6 @@ The following is a comprehensive list of Spring Security Filter ordering:
|
|||
* `OAuth2LoginAuthenticationFilter`
|
||||
* `Saml2WebSsoAuthenticationFilter`
|
||||
* xref:servlet/authentication/passwords/form.adoc#servlet-authentication-usernamepasswordauthenticationfilter[`UsernamePasswordAuthenticationFilter`]
|
||||
* `OpenIDAuthenticationFilter`
|
||||
* `DefaultLoginPageGeneratingFilter`
|
||||
* `DefaultLogoutPageGeneratingFilter`
|
||||
* `ConcurrentSessionFilter`
|
||||
|
|
|
@ -18,6 +18,5 @@ These sections focus on specific ways you may want to authenticate and point bac
|
|||
* xref:servlet/saml2/index.adoc#servlet-saml2[SAML 2.0 Login] - SAML 2.0 Log In
|
||||
* xref:servlet/authentication/rememberme.adoc#servlet-rememberme[Remember Me] - how to remember a user past session expiration
|
||||
* xref:servlet/authentication/jaas.adoc#servlet-jaas[JAAS Authentication] - authenticate with JAAS
|
||||
* xref:servlet/authentication/openid.adoc#servlet-openid[OpenID] - OpenID Authentication (not to be confused with OpenID Connect)
|
||||
* xref:servlet/authentication/preauth.adoc#servlet-preauth[Pre-Authentication Scenarios] - authenticate with an external mechanism such as https://www.siteminder.com/[SiteMinder] or Java EE security but still use Spring Security for authorization and protection against common exploits.
|
||||
* xref:servlet/authentication/x509.adoc#servlet-x509[X509 Authentication] - X509 Authentication
|
||||
|
|
|
@ -1,70 +0,0 @@
|
|||
[[servlet-openid]]
|
||||
= OpenID Support
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
The OpenID 1.0 and 2.0 protocols have been deprecated. You should migrate to OpenID Connect, which is supported by `spring-security-oauth2`.
|
||||
====
|
||||
|
||||
The namespace supports https://openid.net/[OpenID] login either instead of or in addition to normal form-based login, with a simple change:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<http>
|
||||
<intercept-url pattern="/**" access="ROLE_USER" />
|
||||
<openid-login />
|
||||
</http>
|
||||
----
|
||||
====
|
||||
|
||||
You should then register yourself with an OpenID provider (such as myopenid.com), and add the user information to your in-memory `<user-service>`:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<user name="https://jimi.hendrix.myopenid.com/" authorities="ROLE_USER" />
|
||||
----
|
||||
====
|
||||
|
||||
You should be able to login by using the `myopenid.com` site to authenticate.
|
||||
You can also select a specific `UserDetailsService` bean for use with OpenID by setting the `user-service-ref` attribute on the `openid-login` element.
|
||||
Note that we have omitted the password attribute from the above user configuration, since this set of user data is being used only to load the authorities for the user.
|
||||
A random password is generated internally, preventing you from accidentally using this user data as an authentication source elsewhere in your configuration.
|
||||
|
||||
|
||||
== Attribute Exchange
|
||||
Spring Security includes support for OpenID https://openid.net/specs/openid-attribute-exchange-1_0.html[attribute exchange].
|
||||
As an example, the following configuration tries to retrieve the email and full name from the OpenID provider for use by the application:
|
||||
|
||||
====
|
||||
[source,xml]
|
||||
----
|
||||
<openid-login>
|
||||
<attribute-exchange>
|
||||
<openid-attribute name="email" type="https://axschema.org/contact/email" required="true"/>
|
||||
<openid-attribute name="name" type="https://axschema.org/namePerson"/>
|
||||
</attribute-exchange>
|
||||
</openid-login>
|
||||
----
|
||||
====
|
||||
|
||||
The "`type`" of each OpenID attribute is a URI, determined by a particular schema -- in this case, https://axschema.org/[https://axschema.org/].
|
||||
If an attribute must be retrieved for successful authentication, you can set the `required` attribute.
|
||||
The exact schema and attributes supported depend on your OpenID provider.
|
||||
The attribute values are returned as part of the authentication process and can be accessed afterwards by using the following code:
|
||||
|
||||
====
|
||||
[source,java]
|
||||
----
|
||||
OpenIDAuthenticationToken token =
|
||||
(OpenIDAuthenticationToken)SecurityContextHolder.getContext().getAuthentication();
|
||||
List<OpenIDAttribute> attributes = token.getAttributes();
|
||||
----
|
||||
====
|
||||
|
||||
We can obtain the `OpenIDAuthenticationToken` from the xref:servlet/authentication/architecture.adoc#servlet-authentication-securitycontextholder[SecurityContextHolder].
|
||||
The `OpenIDAttribute` contains the attribute type and the retrieved value (or values in the case of multi-valued attributes).
|
||||
You can supply multiple `attribute-exchange` elements by using an `identifier-matcher` attribute on each element.
|
||||
This contains a regular expression that is matched against the OpenID identifier supplied by the user.
|
||||
See the OpenID sample application in the codebase for an example configuration, providing different attribute lists for the Google, Yahoo and MyOpenID providers.
|
|
@ -29,7 +29,6 @@
|
|||
<classpathentry kind="lib" path="oauth2/oauth2-core/build/classes/java/main" module="spring-security-oauth2-core" />
|
||||
<classpathentry kind="lib" path="oauth2/oauth2-jose/build/classes/java/main" module="spring-security-oauth2-jose" />
|
||||
<classpathentry kind="lib" path="oauth2/oauth2-resource-server/build/classes/java/main" module="spring-security-oauth2-resource-server" />
|
||||
<classpathentry kind="lib" path="openid/build/classes/java/main" module="spring-security-openid" />
|
||||
<classpathentry kind="lib" path="remoting/build/classes/java/main" module="spring-security-remoting" />
|
||||
<classpathentry kind="lib" path="rsocket/build/classes/java/main" module="spring-security-rsocket" />
|
||||
<classpathentry kind="lib" path="saml2/saml2-service-provider/build/classes/java/main" module="spring-security-saml2-service-provider" />
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
// NOTE: The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
// <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to migrate</a>
|
||||
// to <a href="https://openid.net/connect/">OpenID Connect</a>, which is supported by <code>spring-security-oauth2</code>.
|
||||
|
||||
apply plugin: 'io.spring.convention.spring-module'
|
||||
|
||||
dependencies {
|
||||
management platform(project(":spring-security-dependencies"))
|
||||
api project(':spring-security-core')
|
||||
api project(':spring-security-web')
|
||||
api('com.google.inject:guice') {
|
||||
exclude group: 'aopalliance', module: 'aopalliance'
|
||||
exclude group: 'javax.inject', module: 'javax.inject'
|
||||
}
|
||||
// openid4java has a compile time dep on guice with a group
|
||||
// name which is different from the maven central one.
|
||||
// We use the maven central version here instead.
|
||||
api('org.openid4java:openid4java-nodeps') {
|
||||
exclude group: 'com.google.code.guice', module: 'guice'
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
api 'org.springframework:spring-aop'
|
||||
api 'org.springframework:spring-beans'
|
||||
api 'org.springframework:spring-context'
|
||||
api 'org.springframework:spring-core'
|
||||
api 'org.springframework:spring-web'
|
||||
|
||||
provided 'jakarta.servlet:jakarta.servlet-api'
|
||||
|
||||
runtimeOnly 'net.sourceforge.nekohtml:nekohtml'
|
||||
runtimeOnly('org.apache.httpcomponents:httpclient') {
|
||||
exclude group: 'commons-logging', module: 'commons-logging'
|
||||
}
|
||||
|
||||
testImplementation "jakarta.inject:jakarta.inject-api"
|
||||
testImplementation "org.assertj:assertj-core"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-api"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-params"
|
||||
testImplementation "org.junit.jupiter:junit-jupiter-engine"
|
||||
testImplementation "org.mockito:mockito-core"
|
||||
testImplementation "org.mockito:mockito-junit-jupiter"
|
||||
testImplementation "org.springframework:spring-test"
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
|
||||
/**
|
||||
* Indicates that OpenID authentication was cancelled
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class AuthenticationCancelledException extends AuthenticationException {
|
||||
|
||||
public AuthenticationCancelledException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public AuthenticationCancelledException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2016 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.openid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A strategy which can be used by an OpenID consumer implementation, to dynamically
|
||||
* determine the attribute exchange information based on the OpenID identifier.
|
||||
* <p>
|
||||
* This allows the list of attributes for a fetch request to be tailored for different
|
||||
* OpenID providers, since they do not all support the same attributes.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface AxFetchListFactory {
|
||||
|
||||
/**
|
||||
* Builds the list of attributes which should be added to the fetch request for the
|
||||
* supplied OpenID identifier.
|
||||
* @param identifier the claimed_identity
|
||||
* @return the attributes to fetch for this identifier
|
||||
*/
|
||||
List<OpenIDAttribute> createAttributeList(String identifier);
|
||||
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2016 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.openid;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class NullAxFetchListFactory implements AxFetchListFactory {
|
||||
|
||||
@Override
|
||||
public List<OpenIDAttribute> createAttributeList(String identifier) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,197 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.openid4java.association.AssociationException;
|
||||
import org.openid4java.consumer.ConsumerException;
|
||||
import org.openid4java.consumer.ConsumerManager;
|
||||
import org.openid4java.consumer.VerificationResult;
|
||||
import org.openid4java.discovery.DiscoveryException;
|
||||
import org.openid4java.discovery.DiscoveryInformation;
|
||||
import org.openid4java.discovery.Identifier;
|
||||
import org.openid4java.message.AuthRequest;
|
||||
import org.openid4java.message.Message;
|
||||
import org.openid4java.message.MessageException;
|
||||
import org.openid4java.message.MessageExtension;
|
||||
import org.openid4java.message.ParameterList;
|
||||
import org.openid4java.message.ax.AxMessage;
|
||||
import org.openid4java.message.ax.FetchRequest;
|
||||
import org.openid4java.message.ax.FetchResponse;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* @author Ray Krueger
|
||||
* @author Luke Taylor
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("unchecked")
|
||||
public class OpenID4JavaConsumer implements OpenIDConsumer {
|
||||
|
||||
private static final String DISCOVERY_INFO_KEY = DiscoveryInformation.class.getName();
|
||||
|
||||
private static final String ATTRIBUTE_LIST_KEY = "SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST";
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
private final ConsumerManager consumerManager;
|
||||
|
||||
private final AxFetchListFactory attributesToFetchFactory;
|
||||
|
||||
public OpenID4JavaConsumer() throws ConsumerException {
|
||||
this(new ConsumerManager(), new NullAxFetchListFactory());
|
||||
}
|
||||
|
||||
public OpenID4JavaConsumer(AxFetchListFactory attributesToFetchFactory) throws ConsumerException {
|
||||
this(new ConsumerManager(), attributesToFetchFactory);
|
||||
}
|
||||
|
||||
public OpenID4JavaConsumer(ConsumerManager consumerManager, AxFetchListFactory attributesToFetchFactory) {
|
||||
this.consumerManager = consumerManager;
|
||||
this.attributesToFetchFactory = attributesToFetchFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String beginConsumption(HttpServletRequest req, String identityUrl, String returnToUrl, String realm)
|
||||
throws OpenIDConsumerException {
|
||||
List<DiscoveryInformation> discoveries = getDiscoveries(identityUrl);
|
||||
DiscoveryInformation information = this.consumerManager.associate(discoveries);
|
||||
req.getSession().setAttribute(DISCOVERY_INFO_KEY, information);
|
||||
AuthRequest authReq = getAuthRequest(req, identityUrl, returnToUrl, realm, information);
|
||||
return authReq.getDestinationUrl(true);
|
||||
}
|
||||
|
||||
private List<DiscoveryInformation> getDiscoveries(String identityUrl) throws OpenIDConsumerException {
|
||||
try {
|
||||
return this.consumerManager.discover(identityUrl);
|
||||
}
|
||||
catch (DiscoveryException ex) {
|
||||
throw new OpenIDConsumerException("Error during discovery", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private AuthRequest getAuthRequest(HttpServletRequest req, String identityUrl, String returnToUrl, String realm,
|
||||
DiscoveryInformation information) throws OpenIDConsumerException {
|
||||
try {
|
||||
AuthRequest authReq = this.consumerManager.authenticate(information, returnToUrl, realm);
|
||||
this.logger.debug("Looking up attribute fetch list for identifier: " + identityUrl);
|
||||
List<OpenIDAttribute> attributesToFetch = this.attributesToFetchFactory.createAttributeList(identityUrl);
|
||||
if (!attributesToFetch.isEmpty()) {
|
||||
req.getSession().setAttribute(ATTRIBUTE_LIST_KEY, attributesToFetch);
|
||||
FetchRequest fetchRequest = FetchRequest.createFetchRequest();
|
||||
for (OpenIDAttribute attr : attributesToFetch) {
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Adding attribute " + attr.getType() + " to fetch request");
|
||||
}
|
||||
fetchRequest.addAttribute(attr.getName(), attr.getType(), attr.isRequired(), attr.getCount());
|
||||
}
|
||||
authReq.addExtension(fetchRequest);
|
||||
}
|
||||
return authReq;
|
||||
}
|
||||
catch (MessageException | ConsumerException ex) {
|
||||
throw new OpenIDConsumerException("Error processing ConsumerManager authentication", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenIDAuthenticationToken endConsumption(HttpServletRequest request) throws OpenIDConsumerException {
|
||||
// extract the parameters from the authentication response
|
||||
// (which comes in as a HTTP request from the OpenID provider)
|
||||
ParameterList openidResp = new ParameterList(request.getParameterMap());
|
||||
// retrieve the previously stored discovery information
|
||||
DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute(DISCOVERY_INFO_KEY);
|
||||
if (discovered == null) {
|
||||
throw new OpenIDConsumerException(
|
||||
"DiscoveryInformation is not available. Possible causes are lost session or replay attack");
|
||||
}
|
||||
List<OpenIDAttribute> attributesToFetch = (List<OpenIDAttribute>) request.getSession()
|
||||
.getAttribute(ATTRIBUTE_LIST_KEY);
|
||||
request.getSession().removeAttribute(DISCOVERY_INFO_KEY);
|
||||
request.getSession().removeAttribute(ATTRIBUTE_LIST_KEY);
|
||||
// extract the receiving URL from the HTTP request
|
||||
StringBuffer receivingURL = request.getRequestURL();
|
||||
String queryString = request.getQueryString();
|
||||
if (StringUtils.hasLength(queryString)) {
|
||||
receivingURL.append("?").append(request.getQueryString());
|
||||
}
|
||||
// verify the response
|
||||
VerificationResult verification;
|
||||
try {
|
||||
verification = this.consumerManager.verify(receivingURL.toString(), openidResp, discovered);
|
||||
}
|
||||
catch (MessageException | AssociationException | DiscoveryException ex) {
|
||||
throw new OpenIDConsumerException("Error verifying openid response", ex);
|
||||
}
|
||||
// examine the verification result and extract the verified identifier
|
||||
Identifier verified = verification.getVerifiedId();
|
||||
if (verified == null) {
|
||||
Identifier id = discovered.getClaimedIdentifier();
|
||||
return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE,
|
||||
(id != null) ? id.getIdentifier() : "Unknown",
|
||||
"Verification status message: [" + verification.getStatusMsg() + "]",
|
||||
Collections.<OpenIDAttribute>emptyList());
|
||||
}
|
||||
List<OpenIDAttribute> attributes = fetchAxAttributes(verification.getAuthResponse(), attributesToFetch);
|
||||
return new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, verified.getIdentifier(),
|
||||
"some message", attributes);
|
||||
}
|
||||
|
||||
List<OpenIDAttribute> fetchAxAttributes(Message authSuccess, List<OpenIDAttribute> attributesToFetch)
|
||||
throws OpenIDConsumerException {
|
||||
if (attributesToFetch == null || !authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
this.logger.debug("Extracting attributes retrieved by attribute exchange");
|
||||
List<OpenIDAttribute> attributes = Collections.emptyList();
|
||||
try {
|
||||
MessageExtension ext = authSuccess.getExtension(AxMessage.OPENID_NS_AX);
|
||||
if (ext instanceof FetchResponse) {
|
||||
FetchResponse fetchResp = (FetchResponse) ext;
|
||||
attributes = new ArrayList<>(attributesToFetch.size());
|
||||
for (OpenIDAttribute attr : attributesToFetch) {
|
||||
List<String> values = fetchResp.getAttributeValues(attr.getName());
|
||||
if (!values.isEmpty()) {
|
||||
OpenIDAttribute fetched = new OpenIDAttribute(attr.getName(), attr.getType(), values);
|
||||
fetched.setRequired(attr.isRequired());
|
||||
attributes.add(fetched);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MessageException ex) {
|
||||
throw new OpenIDConsumerException("Attribute retrieval failed", ex);
|
||||
}
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Retrieved attributes" + attributes);
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2016 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.openid;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Represents an OpenID subject identity attribute.
|
||||
* <p>
|
||||
* Can be used for configuring the <tt>OpenID4JavaConsumer</tt> with the attributes which
|
||||
* should be requested during a fetch request, or to hold values for an attribute which
|
||||
* are returned during the authentication process.
|
||||
*
|
||||
* @author Luke Taylor
|
||||
* @since 3.0
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenIDAttribute implements Serializable {
|
||||
|
||||
private final String name;
|
||||
|
||||
private final String typeIdentifier;
|
||||
|
||||
private boolean required = false;
|
||||
|
||||
private int count = 1;
|
||||
|
||||
private final List<String> values;
|
||||
|
||||
public OpenIDAttribute(String name, String type) {
|
||||
this.name = name;
|
||||
this.typeIdentifier = type;
|
||||
this.values = null;
|
||||
}
|
||||
|
||||
public OpenIDAttribute(String name, String type, List<String> values) {
|
||||
Assert.notEmpty(values, "values cannot be empty");
|
||||
this.name = name;
|
||||
this.typeIdentifier = type;
|
||||
this.values = values;
|
||||
}
|
||||
|
||||
/**
|
||||
* The attribute name
|
||||
*/
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The attribute type Identifier (a URI).
|
||||
*/
|
||||
public String getType() {
|
||||
return this.typeIdentifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* The "required" flag for the attribute when used with an authentication request.
|
||||
* Defaults to "false".
|
||||
*/
|
||||
public boolean isRequired() {
|
||||
return this.required;
|
||||
}
|
||||
|
||||
public void setRequired(boolean required) {
|
||||
this.required = required;
|
||||
}
|
||||
|
||||
/**
|
||||
* The requested count for the attribute when it is used as part of an authentication
|
||||
* request. Defaults to 1.
|
||||
*/
|
||||
public int getCount() {
|
||||
return this.count;
|
||||
}
|
||||
|
||||
public void setCount(int count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
/**
|
||||
* The values obtained from an attribute exchange.
|
||||
*/
|
||||
public List<String> getValues() {
|
||||
Assert.notNull(this.values, "Cannot read values from an authentication request attribute");
|
||||
return this.values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder("[");
|
||||
result.append(this.name);
|
||||
if (this.values != null) {
|
||||
result.append(":");
|
||||
result.append(this.values.toString());
|
||||
}
|
||||
result.append("]");
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,283 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.openid4java.consumer.ConsumerException;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Filter which processes OpenID authentication requests.
|
||||
* <p>
|
||||
* The OpenID authentication involves two stages.
|
||||
*
|
||||
* <h2>Submission of OpenID identity</h2>
|
||||
*
|
||||
* The user's OpenID identity is submitted via a login form, just as it would be for a
|
||||
* normal form login. At this stage the filter will extract the identity from the
|
||||
* submitted request (by default, the parameter is called <tt>openid_identifier</tt>, as
|
||||
* recommended by the OpenID 2.0 Specification). It then passes the identity to the
|
||||
* configured <tt>OpenIDConsumer</tt>, which returns the URL to which the request should
|
||||
* be redirected for authentication. A "return_to" URL is also supplied, which matches the
|
||||
* URL processed by this filter, to allow the filter to handle the request once the user
|
||||
* has been successfully authenticated. The OpenID server will then authenticate the user
|
||||
* and redirect back to the application.
|
||||
*
|
||||
* <h2>Processing the Redirect from the OpenID Server</h2>
|
||||
*
|
||||
* Once the user has been authenticated externally, the redirected request will be passed
|
||||
* to the <tt>OpenIDConsumer</tt> again for validation. The returned
|
||||
* <tt>OpenIDAuthentication</tt> will be passed to the <tt>AuthenticationManager</tt>
|
||||
* where it should (normally) be processed by an <tt>OpenIDAuthenticationProvider</tt> in
|
||||
* order to load the authorities for the user.
|
||||
*
|
||||
* @author Robin Bramley
|
||||
* @author Ray Krueger
|
||||
* @author Luke Taylor
|
||||
* @since 2.0
|
||||
* @see OpenIDAuthenticationProvider
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenIDAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
public static final String DEFAULT_CLAIMED_IDENTITY_FIELD = "openid_identifier";
|
||||
|
||||
private OpenIDConsumer consumer;
|
||||
|
||||
private String claimedIdentityFieldName = DEFAULT_CLAIMED_IDENTITY_FIELD;
|
||||
|
||||
private Map<String, String> realmMapping = Collections.emptyMap();
|
||||
|
||||
private Set<String> returnToUrlParameters = Collections.emptySet();
|
||||
|
||||
public OpenIDAuthenticationFilter() {
|
||||
super("/login/openid");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
if (this.consumer == null) {
|
||||
try {
|
||||
this.consumer = new OpenID4JavaConsumer();
|
||||
}
|
||||
catch (ConsumerException ex) {
|
||||
throw new IllegalArgumentException("Failed to initialize OpenID", ex);
|
||||
}
|
||||
}
|
||||
if (this.returnToUrlParameters.isEmpty() && getRememberMeServices() instanceof AbstractRememberMeServices) {
|
||||
this.returnToUrlParameters = new HashSet<>();
|
||||
this.returnToUrlParameters.add(((AbstractRememberMeServices) getRememberMeServices()).getParameter());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Authentication has two phases.
|
||||
* <ol>
|
||||
* <li>The initial submission of the claimed OpenID. A redirect to the URL returned
|
||||
* from the consumer will be performed and null will be returned.</li>
|
||||
* <li>The redirection from the OpenID server to the return_to URL, once it has
|
||||
* authenticated the user</li>
|
||||
* </ol>
|
||||
*/
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
throws AuthenticationException, IOException {
|
||||
OpenIDAuthenticationToken token;
|
||||
String identity = request.getParameter("openid.identity");
|
||||
if (!StringUtils.hasText(identity)) {
|
||||
String claimedIdentity = obtainUsername(request);
|
||||
try {
|
||||
String returnToUrl = buildReturnToUrl(request);
|
||||
String realm = lookupRealm(returnToUrl);
|
||||
String openIdUrl = this.consumer.beginConsumption(request, claimedIdentity, returnToUrl, realm);
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("return_to is '" + returnToUrl + "', realm is '" + realm + "'");
|
||||
this.logger.debug("Redirecting to " + openIdUrl);
|
||||
}
|
||||
response.sendRedirect(openIdUrl);
|
||||
// Indicate to parent class that authentication is continuing.
|
||||
return null;
|
||||
}
|
||||
catch (OpenIDConsumerException ex) {
|
||||
this.logger.debug("Failed to consume claimedIdentity: " + claimedIdentity, ex);
|
||||
throw new AuthenticationServiceException(
|
||||
"Unable to process claimed identity '" + claimedIdentity + "'");
|
||||
}
|
||||
}
|
||||
if (this.logger.isDebugEnabled()) {
|
||||
this.logger.debug("Supplied OpenID identity is " + identity);
|
||||
}
|
||||
try {
|
||||
token = this.consumer.endConsumption(request);
|
||||
}
|
||||
catch (OpenIDConsumerException ex) {
|
||||
throw new AuthenticationServiceException("Consumer error", ex);
|
||||
}
|
||||
token.setDetails(this.authenticationDetailsSource.buildDetails(request));
|
||||
// delegate to the authentication provider
|
||||
Authentication authentication = this.getAuthenticationManager().authenticate(token);
|
||||
return authentication;
|
||||
}
|
||||
|
||||
protected String lookupRealm(String returnToUrl) {
|
||||
String mapping = this.realmMapping.get(returnToUrl);
|
||||
if (mapping == null) {
|
||||
try {
|
||||
URL url = new URL(returnToUrl);
|
||||
int port = url.getPort();
|
||||
StringBuilder realmBuffer = new StringBuilder(returnToUrl.length()).append(url.getProtocol())
|
||||
.append("://").append(url.getHost());
|
||||
if (port > 0) {
|
||||
realmBuffer.append(":").append(port);
|
||||
}
|
||||
realmBuffer.append("/");
|
||||
mapping = realmBuffer.toString();
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
this.logger.warn("returnToUrl was not a valid URL: [" + returnToUrl + "]", ex);
|
||||
}
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the <tt>return_to</tt> URL that will be sent to the OpenID service provider.
|
||||
* By default returns the URL of the current request.
|
||||
* @param request the current request which is being processed by this filter
|
||||
* @return The <tt>return_to</tt> URL.
|
||||
*/
|
||||
protected String buildReturnToUrl(HttpServletRequest request) {
|
||||
StringBuffer sb = request.getRequestURL();
|
||||
Iterator<String> iterator = this.returnToUrlParameters.iterator();
|
||||
boolean isFirst = true;
|
||||
while (iterator.hasNext()) {
|
||||
String name = iterator.next();
|
||||
// Assume for simplicity that there is only one value
|
||||
String value = request.getParameter(name);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
if (isFirst) {
|
||||
sb.append("?");
|
||||
isFirst = false;
|
||||
}
|
||||
sb.append(utf8UrlEncode(name)).append("=").append(utf8UrlEncode(value));
|
||||
if (iterator.hasNext()) {
|
||||
sb.append("&");
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the <tt>claimedIdentityFieldName</tt> from the submitted request.
|
||||
*/
|
||||
protected String obtainUsername(HttpServletRequest req) {
|
||||
String claimedIdentity = req.getParameter(this.claimedIdentityFieldName);
|
||||
if (!StringUtils.hasText(claimedIdentity)) {
|
||||
this.logger.error("No claimed identity supplied in authentication request");
|
||||
return "";
|
||||
}
|
||||
return claimedIdentity.trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the <tt>return_to url</tt> to a realm, for example:
|
||||
*
|
||||
* <pre>
|
||||
* https://www.example.com/login/openid -> https://www.example.com/realm
|
||||
* </pre>
|
||||
*
|
||||
* If no mapping is provided then the returnToUrl will be parsed to extract the
|
||||
* protocol, hostname and port followed by a trailing slash. This means that
|
||||
* <tt>https://foo.example.com/login/openid</tt> will automatically become
|
||||
* <tt>http://foo.example.com:80/</tt>
|
||||
* @param realmMapping containing returnToUrl -> realm mappings
|
||||
*/
|
||||
public void setRealmMapping(Map<String, String> realmMapping) {
|
||||
this.realmMapping = realmMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the request parameter containing the OpenID identity, as submitted from
|
||||
* the initial login form.
|
||||
* @param claimedIdentityFieldName defaults to "openid_identifier"
|
||||
*/
|
||||
public void setClaimedIdentityFieldName(String claimedIdentityFieldName) {
|
||||
this.claimedIdentityFieldName = claimedIdentityFieldName;
|
||||
}
|
||||
|
||||
public void setConsumer(OpenIDConsumer consumer) {
|
||||
this.consumer = consumer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies any extra parameters submitted along with the identity field which should
|
||||
* be appended to the {@code return_to} URL which is assembled by
|
||||
* {@link #buildReturnToUrl}.
|
||||
* @param returnToUrlParameters the set of parameter names. If not set, it will
|
||||
* default to the parameter name used by the {@code RememberMeServices} obtained from
|
||||
* the parent class (if one is set).
|
||||
*/
|
||||
public void setReturnToUrlParameters(Set<String> returnToUrlParameters) {
|
||||
Assert.notNull(returnToUrlParameters, "returnToUrlParameters cannot be null");
|
||||
this.returnToUrlParameters = returnToUrlParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs URL encoding with UTF-8
|
||||
* @param value the value to URL encode
|
||||
* @return the encoded value
|
||||
*/
|
||||
private String utf8UrlEncode(String value) {
|
||||
try {
|
||||
return URLEncoder.encode(value, "UTF-8");
|
||||
}
|
||||
catch (UnsupportedEncodingException ex) {
|
||||
Error err = new AssertionError(
|
||||
"The Java platform guarantees UTF-8 support, but it seemingly is not present.");
|
||||
err.initCause(ex);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.security.authentication.AuthenticationProvider;
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
||||
import org.springframework.security.core.userdetails.AuthenticationUserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Finalises the OpenID authentication by obtaining local authorities for the
|
||||
* authenticated user.
|
||||
* <p>
|
||||
* The authorities are obtained by calling the configured {@code UserDetailsService}. The
|
||||
* {@code UserDetails} it returns must, at minimum, contain the username and
|
||||
* {@code GrantedAuthority} objects applicable to the authenticated user. Note that by
|
||||
* default, Spring Security ignores the password and enabled/disabled status of the
|
||||
* {@code UserDetails} because this is authentication-related and should have been
|
||||
* enforced by another provider server.
|
||||
* <p>
|
||||
* The {@code UserDetails} returned by implementations is stored in the generated
|
||||
* {@code Authentication} token, so additional properties such as email addresses,
|
||||
* telephone numbers etc can easily be stored.
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd.
|
||||
* @author Luke Taylor
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenIDAuthenticationProvider implements AuthenticationProvider, InitializingBean {
|
||||
|
||||
private AuthenticationUserDetailsService<OpenIDAuthenticationToken> userDetailsService;
|
||||
|
||||
private GrantedAuthoritiesMapper authoritiesMapper = new NullAuthoritiesMapper();
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(this.userDetailsService, "The userDetailsService must be set");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
|
||||
if (!supports(authentication.getClass())) {
|
||||
return null;
|
||||
}
|
||||
if (!(authentication instanceof OpenIDAuthenticationToken)) {
|
||||
return null;
|
||||
}
|
||||
OpenIDAuthenticationToken response = (OpenIDAuthenticationToken) authentication;
|
||||
OpenIDAuthenticationStatus status = response.getStatus();
|
||||
// handle the various possibilities
|
||||
if (status == OpenIDAuthenticationStatus.SUCCESS) {
|
||||
// Lookup user details
|
||||
UserDetails userDetails = this.userDetailsService.loadUserDetails(response);
|
||||
return createSuccessfulAuthentication(userDetails, response);
|
||||
}
|
||||
if (status == OpenIDAuthenticationStatus.CANCELLED) {
|
||||
throw new AuthenticationCancelledException("Log in cancelled");
|
||||
}
|
||||
if (status == OpenIDAuthenticationStatus.ERROR) {
|
||||
throw new AuthenticationServiceException("Error message from server: " + response.getMessage());
|
||||
}
|
||||
if (status == OpenIDAuthenticationStatus.FAILURE) {
|
||||
throw new BadCredentialsException("Log in failed - identity could not be verified");
|
||||
}
|
||||
if (status == OpenIDAuthenticationStatus.SETUP_NEEDED) {
|
||||
throw new AuthenticationServiceException("The server responded setup was needed, which shouldn't happen");
|
||||
}
|
||||
throw new AuthenticationServiceException("Unrecognized return value " + status.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the creation of the final <tt>Authentication</tt> object which will be
|
||||
* returned by the provider.
|
||||
* <p>
|
||||
* The default implementation just creates a new OpenIDAuthenticationToken from the
|
||||
* original, but with the UserDetails as the principal and including the authorities
|
||||
* loaded by the UserDetailsService.
|
||||
* @param userDetails the loaded UserDetails object
|
||||
* @param auth the token passed to the authenticate method, containing
|
||||
* @return the token which will represent the authenticated user.
|
||||
*/
|
||||
protected Authentication createSuccessfulAuthentication(UserDetails userDetails, OpenIDAuthenticationToken auth) {
|
||||
return new OpenIDAuthenticationToken(userDetails,
|
||||
this.authoritiesMapper.mapAuthorities(userDetails.getAuthorities()), auth.getIdentityUrl(),
|
||||
auth.getAttributes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to load the {@code UserDetails} for the authenticated OpenID user.
|
||||
*/
|
||||
public void setUserDetailsService(UserDetailsService userDetailsService) {
|
||||
this.userDetailsService = new UserDetailsByNameServiceWrapper<>(userDetailsService);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to load the {@code UserDetails} for the authenticated OpenID user.
|
||||
*/
|
||||
public void setAuthenticationUserDetailsService(
|
||||
AuthenticationUserDetailsService<OpenIDAuthenticationToken> userDetailsService) {
|
||||
this.userDetailsService = userDetailsService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(Class<?> authentication) {
|
||||
return OpenIDAuthenticationToken.class.isAssignableFrom(authentication);
|
||||
}
|
||||
|
||||
public void setAuthoritiesMapper(GrantedAuthoritiesMapper authoritiesMapper) {
|
||||
this.authoritiesMapper = authoritiesMapper;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
/**
|
||||
* Authentication status codes, based on JanRain status codes
|
||||
* @author JanRain Inc.
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @author Luke Taylor
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
public enum OpenIDAuthenticationStatus {
|
||||
|
||||
/** This code indicates a successful authentication request */
|
||||
SUCCESS("success"),
|
||||
|
||||
/** This code indicates a failed authentication request */
|
||||
FAILURE("failure"),
|
||||
|
||||
/** This code indicates the server reported an error */
|
||||
ERROR("error"),
|
||||
|
||||
/**
|
||||
* This code indicates that the user needs to do additional work to prove their
|
||||
* identity
|
||||
*/
|
||||
SETUP_NEEDED("setup needed"),
|
||||
|
||||
/** This code indicates that the user cancelled their login request */
|
||||
CANCELLED("cancelled");
|
||||
|
||||
private final String name;
|
||||
|
||||
OpenIDAuthenticationStatus(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.SpringSecurityCoreVersion;
|
||||
|
||||
/**
|
||||
* OpenID Authentication Token
|
||||
*
|
||||
* @author Robin Bramley
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenIDAuthenticationToken extends AbstractAuthenticationToken {
|
||||
|
||||
private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
|
||||
|
||||
private final OpenIDAuthenticationStatus status;
|
||||
|
||||
private final Object principal;
|
||||
|
||||
private final String identityUrl;
|
||||
|
||||
private final String message;
|
||||
|
||||
private final List<OpenIDAttribute> attributes;
|
||||
|
||||
public OpenIDAuthenticationToken(OpenIDAuthenticationStatus status, String identityUrl, String message,
|
||||
List<OpenIDAttribute> attributes) {
|
||||
super(new ArrayList<>(0));
|
||||
this.principal = identityUrl;
|
||||
this.status = status;
|
||||
this.identityUrl = identityUrl;
|
||||
this.message = message;
|
||||
this.attributes = attributes;
|
||||
setAuthenticated(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Created by the <tt>OpenIDAuthenticationProvider</tt> on successful authentication.
|
||||
* @param principal usually the <tt>UserDetails</tt> returned by the configured
|
||||
* <tt>UserDetailsService</tt> used by the <tt>OpenIDAuthenticationProvider</tt>.
|
||||
*/
|
||||
public OpenIDAuthenticationToken(Object principal, Collection<? extends GrantedAuthority> authorities,
|
||||
String identityUrl, List<OpenIDAttribute> attributes) {
|
||||
super(authorities);
|
||||
this.principal = principal;
|
||||
this.status = OpenIDAuthenticationStatus.SUCCESS;
|
||||
this.identityUrl = identityUrl;
|
||||
this.message = null;
|
||||
this.attributes = attributes;
|
||||
|
||||
setAuthenticated(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 'null' always, as no credentials are processed by the OpenID provider.
|
||||
* @see org.springframework.security.core.Authentication#getCredentials()
|
||||
*/
|
||||
@Override
|
||||
public Object getCredentials() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getIdentityUrl() {
|
||||
return this.identityUrl;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <tt>principal</tt> value.
|
||||
*
|
||||
* @see org.springframework.security.core.Authentication#getPrincipal()
|
||||
*/
|
||||
@Override
|
||||
public Object getPrincipal() {
|
||||
return this.principal;
|
||||
}
|
||||
|
||||
public OpenIDAuthenticationStatus getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public List<OpenIDAttribute> getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[" + super.toString() + ", attributes : " + this.attributes + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* An interface for OpenID library implementations
|
||||
*
|
||||
* @author Ray Krueger
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public interface OpenIDConsumer {
|
||||
|
||||
/**
|
||||
* Given the request, the claimedIdentity, the return to url, and a realm, lookup the
|
||||
* openId authentication page the user should be redirected to.
|
||||
* @param req HttpServletRequest
|
||||
* @param claimedIdentity String URI the user presented during authentication
|
||||
* @param returnToUrl String URI of the URL we want the user sent back to by the OP
|
||||
* @param realm URI pattern matching the realm we want the user to see
|
||||
* @return String URI to redirect user to for authentication
|
||||
* @throws OpenIDConsumerException if anything bad happens
|
||||
*/
|
||||
String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl, String realm)
|
||||
throws OpenIDConsumerException;
|
||||
|
||||
OpenIDAuthenticationToken endConsumption(HttpServletRequest req) throws OpenIDConsumerException;
|
||||
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
/**
|
||||
* Thrown by an OpenIDConsumer if it cannot process a request
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenIDConsumerException extends Exception {
|
||||
|
||||
public OpenIDConsumerException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public OpenIDConsumerException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2016 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.openid;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @since 3.1
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class RegexBasedAxFetchListFactory implements AxFetchListFactory {
|
||||
|
||||
private final Map<Pattern, List<OpenIDAttribute>> idToAttributes;
|
||||
|
||||
/**
|
||||
* @param regexMap map of regular-expressions (matching the identifier) to attributes
|
||||
* which should be fetched for that pattern.
|
||||
*/
|
||||
public RegexBasedAxFetchListFactory(Map<String, List<OpenIDAttribute>> regexMap) {
|
||||
this.idToAttributes = new LinkedHashMap<>();
|
||||
for (Map.Entry<String, List<OpenIDAttribute>> entry : regexMap.entrySet()) {
|
||||
this.idToAttributes.put(Pattern.compile(entry.getKey()), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterates through the patterns stored in the map and returns the list of attributes
|
||||
* defined for the first match. If no match is found, returns an empty list.
|
||||
*/
|
||||
@Override
|
||||
public List<OpenIDAttribute> createAttributeList(String identifier) {
|
||||
for (Map.Entry<Pattern, List<OpenIDAttribute>> entry : this.idToAttributes.entrySet()) {
|
||||
if (entry.getKey().matcher(identifier).matches()) {
|
||||
return entry.getValue();
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2016 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.openid;
|
|
@ -1,9 +0,0 @@
|
|||
<html>
|
||||
<body>
|
||||
<p>Authenticates standard web browser users via <a href="https://openid.net">OpenID</a>.</p>
|
||||
|
||||
<p>NOTE: The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
<a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to migrate</a>
|
||||
to <a href="https://openid.net/connect/">OpenID Connect</a>, which is supported by <code>spring-security-oauth2</code>.</p>
|
||||
</body>
|
||||
</html>
|
|
@ -1,81 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class MockOpenIDConsumer implements OpenIDConsumer {
|
||||
|
||||
private OpenIDAuthenticationToken token;
|
||||
|
||||
private String redirectUrl;
|
||||
|
||||
public MockOpenIDConsumer() {
|
||||
}
|
||||
|
||||
public MockOpenIDConsumer(String redirectUrl, OpenIDAuthenticationToken token) {
|
||||
this.redirectUrl = redirectUrl;
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
public MockOpenIDConsumer(String redirectUrl) {
|
||||
this.redirectUrl = redirectUrl;
|
||||
}
|
||||
|
||||
public MockOpenIDConsumer(OpenIDAuthenticationToken token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl, String realm) {
|
||||
return this.redirectUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OpenIDAuthenticationToken endConsumption(HttpServletRequest req) {
|
||||
return this.token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the redirectUrl to be returned by beginConsumption
|
||||
* @param redirectUrl
|
||||
*/
|
||||
public void setRedirectUrl(String redirectUrl) {
|
||||
this.redirectUrl = redirectUrl;
|
||||
}
|
||||
|
||||
public void setReturnToUrl(String returnToUrl) {
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the token to be returned by endConsumption
|
||||
* @param token
|
||||
*/
|
||||
public void setToken(OpenIDAuthenticationToken token) {
|
||||
this.token = token;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,192 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2016 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.openid;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.openid4java.association.AssociationException;
|
||||
import org.openid4java.consumer.ConsumerException;
|
||||
import org.openid4java.consumer.ConsumerManager;
|
||||
import org.openid4java.consumer.VerificationResult;
|
||||
import org.openid4java.discovery.DiscoveryException;
|
||||
import org.openid4java.discovery.DiscoveryInformation;
|
||||
import org.openid4java.discovery.Identifier;
|
||||
import org.openid4java.message.AuthRequest;
|
||||
import org.openid4java.message.Message;
|
||||
import org.openid4java.message.MessageException;
|
||||
import org.openid4java.message.ParameterList;
|
||||
import org.openid4java.message.ax.AxMessage;
|
||||
import org.openid4java.message.ax.FetchResponse;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* @author Luke Taylor
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenID4JavaConsumerTests {
|
||||
|
||||
List<OpenIDAttribute> attributes = Arrays.asList(new OpenIDAttribute("a", "b"),
|
||||
new OpenIDAttribute("b", "b", Arrays.asList("c")));
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void beginConsumptionCreatesExpectedSessionData() throws Exception {
|
||||
ConsumerManager mgr = mock(ConsumerManager.class);
|
||||
AuthRequest authReq = mock(AuthRequest.class);
|
||||
DiscoveryInformation di = mock(DiscoveryInformation.class);
|
||||
given(mgr.authenticate(any(DiscoveryInformation.class), any(), any())).willReturn(authReq);
|
||||
given(mgr.associate(any())).willReturn(di);
|
||||
OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new MockAttributesFactory());
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
consumer.beginConsumption(request, "", "", "");
|
||||
assertThat(request.getSession().getAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST"))
|
||||
.isEqualTo(this.attributes);
|
||||
assertThat(request.getSession().getAttribute(DiscoveryInformation.class.getName())).isEqualTo(di);
|
||||
// Check with empty attribute fetch list
|
||||
consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory());
|
||||
request = new MockHttpServletRequest();
|
||||
consumer.beginConsumption(request, "", "", "");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void discoveryExceptionRaisesOpenIDException() throws Exception {
|
||||
ConsumerManager mgr = mock(ConsumerManager.class);
|
||||
OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory());
|
||||
given(mgr.discover(any())).willThrow(new DiscoveryException("msg"));
|
||||
assertThatExceptionOfType(OpenIDConsumerException.class)
|
||||
.isThrownBy(() -> consumer.beginConsumption(new MockHttpServletRequest(), "", "", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messageOrConsumerAuthenticationExceptionRaisesOpenIDException() throws Exception {
|
||||
ConsumerManager mgr = mock(ConsumerManager.class);
|
||||
OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory());
|
||||
given(mgr.authenticate(ArgumentMatchers.<DiscoveryInformation>any(), any(), any()))
|
||||
.willThrow(new MessageException("msg"), new ConsumerException("msg"));
|
||||
assertThatExceptionOfType(OpenIDConsumerException.class)
|
||||
.isThrownBy(() -> consumer.beginConsumption(new MockHttpServletRequest(), "", "", ""));
|
||||
assertThatExceptionOfType(OpenIDConsumerException.class)
|
||||
.isThrownBy(() -> consumer.beginConsumption(new MockHttpServletRequest(), "", "", ""));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void failedVerificationReturnsFailedAuthenticationStatus() throws Exception {
|
||||
ConsumerManager mgr = mock(ConsumerManager.class);
|
||||
OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory());
|
||||
VerificationResult vr = mock(VerificationResult.class);
|
||||
DiscoveryInformation di = mock(DiscoveryInformation.class);
|
||||
given(mgr.verify(any(), any(ParameterList.class), any(DiscoveryInformation.class))).willReturn(vr);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.getSession().setAttribute(DiscoveryInformation.class.getName(), di);
|
||||
OpenIDAuthenticationToken auth = consumer.endConsumption(request);
|
||||
assertThat(auth.getStatus()).isEqualTo(OpenIDAuthenticationStatus.FAILURE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verificationExceptionsRaiseOpenIDException() throws Exception {
|
||||
ConsumerManager mgr = mock(ConsumerManager.class);
|
||||
OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory());
|
||||
given(mgr.verify(any(), any(ParameterList.class), any(DiscoveryInformation.class)))
|
||||
.willThrow(new MessageException(""), new AssociationException(""), new DiscoveryException(""));
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setQueryString("x=5");
|
||||
assertThatExceptionOfType(OpenIDConsumerException.class).isThrownBy(() -> consumer.endConsumption(request));
|
||||
assertThatExceptionOfType(OpenIDConsumerException.class).isThrownBy(() -> consumer.endConsumption(request));
|
||||
assertThatExceptionOfType(OpenIDConsumerException.class).isThrownBy(() -> consumer.endConsumption(request));
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Test
|
||||
public void successfulVerificationReturnsExpectedAuthentication() throws Exception {
|
||||
ConsumerManager mgr = mock(ConsumerManager.class);
|
||||
OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(mgr, new NullAxFetchListFactory());
|
||||
VerificationResult vr = mock(VerificationResult.class);
|
||||
DiscoveryInformation di = mock(DiscoveryInformation.class);
|
||||
Identifier id = (Identifier) () -> "id";
|
||||
Message msg = mock(Message.class);
|
||||
given(mgr.verify(any(), any(ParameterList.class), any(DiscoveryInformation.class))).willReturn(vr);
|
||||
given(vr.getVerifiedId()).willReturn(id);
|
||||
given(vr.getAuthResponse()).willReturn(msg);
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.getSession().setAttribute(DiscoveryInformation.class.getName(), di);
|
||||
request.getSession().setAttribute("SPRING_SECURITY_OPEN_ID_ATTRIBUTES_FETCH_LIST", this.attributes);
|
||||
OpenIDAuthenticationToken auth = consumer.endConsumption(request);
|
||||
assertThat(auth.getStatus()).isEqualTo(OpenIDAuthenticationStatus.SUCCESS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void fetchAttributesReturnsExpectedValues() throws Exception {
|
||||
OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(new NullAxFetchListFactory());
|
||||
Message msg = mock(Message.class);
|
||||
FetchResponse fr = mock(FetchResponse.class);
|
||||
given(msg.hasExtension(AxMessage.OPENID_NS_AX)).willReturn(true);
|
||||
given(msg.getExtension(AxMessage.OPENID_NS_AX)).willReturn(fr);
|
||||
given(fr.getAttributeValues("a")).willReturn(Arrays.asList("x", "y"));
|
||||
List<OpenIDAttribute> fetched = consumer.fetchAxAttributes(msg, this.attributes);
|
||||
assertThat(fetched).hasSize(1);
|
||||
assertThat(fetched.get(0).getValues()).hasSize(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void messageExceptionFetchingAttributesRaisesOpenIDException() throws Exception {
|
||||
OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(new NullAxFetchListFactory());
|
||||
Message msg = mock(Message.class);
|
||||
FetchResponse fr = mock(FetchResponse.class);
|
||||
given(msg.hasExtension(AxMessage.OPENID_NS_AX)).willReturn(true);
|
||||
given(msg.getExtension(AxMessage.OPENID_NS_AX)).willThrow(new MessageException(""));
|
||||
given(fr.getAttributeValues("a")).willReturn(Arrays.asList("x", "y"));
|
||||
assertThatExceptionOfType(OpenIDConsumerException.class)
|
||||
.isThrownBy(() -> consumer.fetchAxAttributes(msg, this.attributes));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void missingDiscoveryInformationThrowsException() throws Exception {
|
||||
OpenID4JavaConsumer consumer = new OpenID4JavaConsumer(new NullAxFetchListFactory());
|
||||
assertThatExceptionOfType(OpenIDConsumerException.class)
|
||||
.isThrownBy(() -> consumer.endConsumption(new MockHttpServletRequest()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void additionalConstructorsWork() throws Exception {
|
||||
new OpenID4JavaConsumer();
|
||||
new OpenID4JavaConsumer(new MockAttributesFactory());
|
||||
}
|
||||
|
||||
private class MockAttributesFactory implements AxFetchListFactory {
|
||||
|
||||
@Override
|
||||
public List<OpenIDAttribute> createAttributeList(String identifier) {
|
||||
return OpenID4JavaConsumerTests.this.attributes;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2017 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.openid;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
/**
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenIDAuthenticationFilterTests {
|
||||
|
||||
OpenIDAuthenticationFilter filter;
|
||||
|
||||
private static final String REDIRECT_URL = "https://www.example.com/redirect";
|
||||
|
||||
private static final String CLAIMED_IDENTITY_URL = "https://www.example.com/identity";
|
||||
|
||||
private static final String REQUEST_PATH = "/login/openid";
|
||||
|
||||
private static final String FILTER_PROCESS_URL = "http://localhost:8080" + REQUEST_PATH;
|
||||
|
||||
private static final String DEFAULT_TARGET_URL = FILTER_PROCESS_URL;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp() {
|
||||
this.filter = new OpenIDAuthenticationFilter();
|
||||
this.filter.setConsumer(new MockOpenIDConsumer(REDIRECT_URL));
|
||||
SavedRequestAwareAuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();
|
||||
this.filter.setAuthenticationSuccessHandler(new SavedRequestAwareAuthenticationSuccessHandler());
|
||||
successHandler.setDefaultTargetUrl(DEFAULT_TARGET_URL);
|
||||
this.filter.setAuthenticationManager((a) -> a);
|
||||
this.filter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterOperation() throws Exception {
|
||||
MockHttpServletRequest req = new MockHttpServletRequest();
|
||||
req.setServletPath(REQUEST_PATH);
|
||||
req.setRequestURI(REQUEST_PATH);
|
||||
req.setServerPort(8080);
|
||||
MockHttpServletResponse response = new MockHttpServletResponse();
|
||||
req.setParameter("openid_identifier", " " + CLAIMED_IDENTITY_URL);
|
||||
req.setRemoteHost("www.example.com");
|
||||
this.filter.setConsumer(new MockOpenIDConsumer() {
|
||||
@Override
|
||||
public String beginConsumption(HttpServletRequest req, String claimedIdentity, String returnToUrl,
|
||||
String realm) {
|
||||
assertThat(claimedIdentity).isEqualTo(CLAIMED_IDENTITY_URL);
|
||||
assertThat(returnToUrl).isEqualTo(DEFAULT_TARGET_URL);
|
||||
assertThat(realm).isEqualTo("http://localhost:8080/");
|
||||
return REDIRECT_URL;
|
||||
}
|
||||
});
|
||||
FilterChain fc = mock(FilterChain.class);
|
||||
this.filter.doFilter(req, response, fc);
|
||||
assertThat(response.getRedirectedUrl()).isEqualTo(REDIRECT_URL);
|
||||
// Filter chain shouldn't proceed
|
||||
verify(fc, never()).doFilter(any(HttpServletRequest.class), any(HttpServletResponse.class));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests that the filter encodes any query parameters on the return_to URL.
|
||||
*/
|
||||
@Test
|
||||
public void encodesUrlParameters() throws Exception {
|
||||
// Arbitrary parameter name and value that will both need to be encoded:
|
||||
String paramName = "foo&bar";
|
||||
String paramValue = "https://example.com/path?a=b&c=d";
|
||||
MockHttpServletRequest req = new MockHttpServletRequest("GET", REQUEST_PATH);
|
||||
req.addParameter(paramName, paramValue);
|
||||
this.filter.setReturnToUrlParameters(Collections.singleton(paramName));
|
||||
URI returnTo = new URI(this.filter.buildReturnToUrl(req));
|
||||
String query = returnTo.getRawQuery();
|
||||
assertThat(count(query, '=')).isEqualTo(1);
|
||||
assertThat(count(query, '&')).isZero();
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the number of occurrences of {@code c} in {@code s}.
|
||||
*/
|
||||
private static int count(String s, char c) {
|
||||
int count = 0;
|
||||
for (char ch : s.toCharArray()) {
|
||||
if (c == ch) {
|
||||
count += 1;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,200 +0,0 @@
|
|||
/*
|
||||
* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
|
||||
*
|
||||
* 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.openid;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.security.authentication.AuthenticationServiceException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.mapping.NullAuthoritiesMapper;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests {@link OpenIDAuthenticationProvider}
|
||||
*
|
||||
* @author Robin Bramley, Opsera Ltd
|
||||
* @deprecated The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
* <a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to
|
||||
* migrate</a> to <a href="https://openid.net/connect/">OpenID Connect</a>, which is
|
||||
* supported by <code>spring-security-oauth2</code>.
|
||||
*/
|
||||
@Deprecated
|
||||
public class OpenIDAuthenticationProviderTests {
|
||||
|
||||
private static final String USERNAME = "user.acegiopenid.com";
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.security.authentication.openid.OpenIDAuthenticationProvider.
|
||||
* authenticate(Authentication)'
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateCancel() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
provider.setAuthoritiesMapper(new NullAuthoritiesMapper());
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.CANCELLED, USERNAME, "",
|
||||
null);
|
||||
assertThat(preAuth.isAuthenticated()).isFalse();
|
||||
assertThatExceptionOfType(AuthenticationCancelledException.class)
|
||||
.isThrownBy(() -> provider.authenticate(preAuth)).withMessage("Log in cancelled");
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.security.authentication.openid.OpenIDAuthenticationProvider.
|
||||
* authenticate(Authentication)'
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateError() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.ERROR, USERNAME, "", null);
|
||||
assertThat(preAuth.isAuthenticated()).isFalse();
|
||||
assertThatExceptionOfType(AuthenticationServiceException.class).isThrownBy(() -> provider.authenticate(preAuth))
|
||||
.withMessage("Error message from server: ");
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.security.authentication.openid.OpenIDAuthenticationProvider.
|
||||
* authenticate(Authentication)'
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateFailure() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setAuthenticationUserDetailsService(
|
||||
new UserDetailsByNameServiceWrapper<>(new MockUserDetailsService()));
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.FAILURE, USERNAME, "", null);
|
||||
assertThat(preAuth.isAuthenticated()).isFalse();
|
||||
assertThatExceptionOfType(BadCredentialsException.class).isThrownBy(() -> provider.authenticate(preAuth))
|
||||
.withMessage("Log in failed - identity could not be verified");
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.security.authentication.openid.OpenIDAuthenticationProvider.
|
||||
* authenticate(Authentication)'
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateSetupNeeded() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SETUP_NEEDED, USERNAME, "",
|
||||
null);
|
||||
assertThat(preAuth.isAuthenticated()).isFalse();
|
||||
assertThatExceptionOfType(AuthenticationServiceException.class).isThrownBy(() -> provider.authenticate(preAuth))
|
||||
.withMessage("The server responded setup was needed, which shouldn't happen");
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.security.authentication.openid.OpenIDAuthenticationProvider.
|
||||
* authenticate(Authentication)'
|
||||
*/
|
||||
@Test
|
||||
public void testAuthenticateSuccess() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
Authentication preAuth = new OpenIDAuthenticationToken(OpenIDAuthenticationStatus.SUCCESS, USERNAME, "", null);
|
||||
assertThat(preAuth.isAuthenticated()).isFalse();
|
||||
Authentication postAuth = provider.authenticate(preAuth);
|
||||
assertThat(postAuth).isNotNull();
|
||||
assertThat(postAuth instanceof OpenIDAuthenticationToken).isTrue();
|
||||
assertThat(postAuth.isAuthenticated()).isTrue();
|
||||
assertThat(postAuth.getPrincipal()).isNotNull();
|
||||
assertThat(postAuth.getPrincipal() instanceof UserDetails).isTrue();
|
||||
assertThat(postAuth.getAuthorities()).isNotNull();
|
||||
assertThat(postAuth.getAuthorities().size() > 0).isTrue();
|
||||
assertThat(((OpenIDAuthenticationToken) postAuth).getStatus() == OpenIDAuthenticationStatus.SUCCESS).isTrue();
|
||||
assertThat(((OpenIDAuthenticationToken) postAuth).getMessage() == null).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDetectsMissingAuthoritiesPopulator() throws Exception {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
assertThatIllegalArgumentException().isThrownBy(provider::afterPropertiesSet);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.security.authentication.openid.OpenIDAuthenticationProvider.
|
||||
* supports(Class)'
|
||||
*/
|
||||
@Test
|
||||
public void testDoesntSupport() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
assertThat(provider.supports(UsernamePasswordAuthenticationToken.class)).isFalse();
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.security.authentication.openid.OpenIDAuthenticationProvider.
|
||||
* authenticate(Authentication)'
|
||||
*/
|
||||
@Test
|
||||
public void testIgnoresUserPassAuthToken() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(USERNAME, "password");
|
||||
assertThat(provider.authenticate(token)).isNull();
|
||||
}
|
||||
|
||||
/*
|
||||
* Test method for
|
||||
* 'org.springframework.security.authentication.openid.OpenIDAuthenticationProvider.
|
||||
* supports(Class)'
|
||||
*/
|
||||
@Test
|
||||
public void testSupports() {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
assertThat(provider.supports(OpenIDAuthenticationToken.class)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValidation() throws Exception {
|
||||
OpenIDAuthenticationProvider provider = new OpenIDAuthenticationProvider();
|
||||
assertThatIllegalArgumentException().isThrownBy(provider::afterPropertiesSet);
|
||||
provider = new OpenIDAuthenticationProvider();
|
||||
provider.setUserDetailsService(new MockUserDetailsService());
|
||||
provider.afterPropertiesSet();
|
||||
}
|
||||
|
||||
static class MockUserDetailsService implements UserDetailsService {
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String ssoUserId) throws AuthenticationException {
|
||||
return new User(ssoUserId, "password", true, true, true, true,
|
||||
AuthorityUtils.createAuthorityList("ROLE_A", "ROLE_B"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
<!-- NOTE: The OpenID 1.0 and 2.0 protocols have been deprecated and users are
|
||||
<a href="https://openid.net/specs/openid-connect-migration-1_0.html">encouraged to migrate</a>
|
||||
to <a href="https://openid.net/connect/">OpenID Connect</a>, which is supported by <code>spring-security-oauth2</code>. -->
|
||||
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.security" level="${sec.log.level:-WARN}"/>
|
||||
|
||||
|
||||
<root level="${root.level:-WARN}">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
|
||||
</configuration>
|
|
@ -280,7 +280,7 @@ public abstract class AbstractAuthenticationProcessingFilter extends GenericFilt
|
|||
* </ol>
|
||||
* @param request from which to extract parameters and perform the authentication
|
||||
* @param response the response, which may be needed if the implementation has to do a
|
||||
* redirect as part of a multi-stage authentication process (such as OpenID).
|
||||
* redirect as part of a multi-stage authentication process (such as OIDC).
|
||||
* @return the authenticated user token, or null if authentication is incomplete.
|
||||
* @throws AuthenticationException if authentication fails.
|
||||
*/
|
||||
|
|
|
@ -32,7 +32,6 @@ import jakarta.servlet.http.HttpSession;
|
|||
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.web.WebAttributes;
|
||||
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
|
||||
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
|
||||
import org.springframework.security.web.authentication.rememberme.AbstractRememberMeServices;
|
||||
import org.springframework.util.Assert;
|
||||
|
@ -63,8 +62,6 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
|||
|
||||
private boolean formLoginEnabled;
|
||||
|
||||
private boolean openIdEnabled;
|
||||
|
||||
private boolean oauth2LoginEnabled;
|
||||
|
||||
private boolean saml2LoginEnabled;
|
||||
|
@ -77,12 +74,6 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
|||
|
||||
private String rememberMeParameter;
|
||||
|
||||
private String openIDauthenticationUrl;
|
||||
|
||||
private String openIDusernameParameter;
|
||||
|
||||
private String openIDrememberMeParameter;
|
||||
|
||||
private Map<String, String> oauth2AuthenticationUrlToClientName;
|
||||
|
||||
private Map<String, String> saml2AuthenticationUrlToProviderName;
|
||||
|
@ -92,31 +83,13 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
|||
public DefaultLoginPageGeneratingFilter() {
|
||||
}
|
||||
|
||||
public DefaultLoginPageGeneratingFilter(AbstractAuthenticationProcessingFilter filter) {
|
||||
if (filter instanceof UsernamePasswordAuthenticationFilter) {
|
||||
init((UsernamePasswordAuthenticationFilter) filter, null);
|
||||
}
|
||||
else {
|
||||
init(null, filter);
|
||||
}
|
||||
}
|
||||
|
||||
public DefaultLoginPageGeneratingFilter(UsernamePasswordAuthenticationFilter authFilter,
|
||||
AbstractAuthenticationProcessingFilter openIDFilter) {
|
||||
init(authFilter, openIDFilter);
|
||||
}
|
||||
|
||||
private void init(UsernamePasswordAuthenticationFilter authFilter,
|
||||
AbstractAuthenticationProcessingFilter openIDFilter) {
|
||||
public DefaultLoginPageGeneratingFilter(UsernamePasswordAuthenticationFilter authFilter) {
|
||||
this.loginPageUrl = DEFAULT_LOGIN_PAGE_URL;
|
||||
this.logoutSuccessUrl = DEFAULT_LOGIN_PAGE_URL + "?logout";
|
||||
this.failureUrl = DEFAULT_LOGIN_PAGE_URL + "?" + ERROR_PARAMETER_NAME;
|
||||
if (authFilter != null) {
|
||||
initAuthFilter(authFilter);
|
||||
}
|
||||
if (openIDFilter != null) {
|
||||
initOpenIdFilter(openIDFilter);
|
||||
}
|
||||
}
|
||||
|
||||
private void initAuthFilter(UsernamePasswordAuthenticationFilter authFilter) {
|
||||
|
@ -128,15 +101,6 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
|||
}
|
||||
}
|
||||
|
||||
private void initOpenIdFilter(AbstractAuthenticationProcessingFilter openIDFilter) {
|
||||
this.openIdEnabled = true;
|
||||
this.openIDusernameParameter = "openid_identifier";
|
||||
if (openIDFilter.getRememberMeServices() instanceof AbstractRememberMeServices) {
|
||||
this.openIDrememberMeParameter = ((AbstractRememberMeServices) openIDFilter.getRememberMeServices())
|
||||
.getParameter();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a Function used to resolve a Map of the hidden inputs where the key is the
|
||||
* name of the input and the value is the value of the input. Typically this is used
|
||||
|
@ -149,7 +113,7 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
|||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return this.formLoginEnabled || this.openIdEnabled || this.oauth2LoginEnabled || this.saml2LoginEnabled;
|
||||
return this.formLoginEnabled || this.oauth2LoginEnabled || this.saml2LoginEnabled;
|
||||
}
|
||||
|
||||
public void setLogoutSuccessUrl(String logoutSuccessUrl) {
|
||||
|
@ -172,10 +136,6 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
|||
this.formLoginEnabled = formLoginEnabled;
|
||||
}
|
||||
|
||||
public void setOpenIdEnabled(boolean openIdEnabled) {
|
||||
this.openIdEnabled = openIdEnabled;
|
||||
}
|
||||
|
||||
public void setOauth2LoginEnabled(boolean oauth2LoginEnabled) {
|
||||
this.oauth2LoginEnabled = oauth2LoginEnabled;
|
||||
}
|
||||
|
@ -198,15 +158,6 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
|||
|
||||
public void setRememberMeParameter(String rememberMeParameter) {
|
||||
this.rememberMeParameter = rememberMeParameter;
|
||||
this.openIDrememberMeParameter = rememberMeParameter;
|
||||
}
|
||||
|
||||
public void setOpenIDauthenticationUrl(String openIDauthenticationUrl) {
|
||||
this.openIDauthenticationUrl = openIDauthenticationUrl;
|
||||
}
|
||||
|
||||
public void setOpenIDusernameParameter(String openIDusernameParameter) {
|
||||
this.openIDusernameParameter = openIDusernameParameter;
|
||||
}
|
||||
|
||||
public void setOauth2AuthenticationUrlToClientName(Map<String, String> oauth2AuthenticationUrlToClientName) {
|
||||
|
@ -282,19 +233,6 @@ public class DefaultLoginPageGeneratingFilter extends GenericFilterBean {
|
|||
sb.append(" <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n");
|
||||
sb.append(" </form>\n");
|
||||
}
|
||||
if (this.openIdEnabled) {
|
||||
sb.append(" <form name=\"oidf\" class=\"form-signin\" method=\"post\" action=\"" + contextPath
|
||||
+ this.openIDauthenticationUrl + "\">\n");
|
||||
sb.append(" <h2 class=\"form-signin-heading\">Login with OpenID Identity</h2>\n");
|
||||
sb.append(createError(loginError, errorMsg) + createLogoutSuccess(logoutSuccess) + " <p>\n");
|
||||
sb.append(" <label for=\"username\" class=\"sr-only\">Identity</label>\n");
|
||||
sb.append(" <input type=\"text\" id=\"username\" name=\"" + this.openIDusernameParameter
|
||||
+ "\" class=\"form-control\" placeholder=\"Username\" required autofocus>\n");
|
||||
sb.append(" </p>\n");
|
||||
sb.append(createRememberMe(this.openIDrememberMeParameter) + renderHiddenInputs(request));
|
||||
sb.append(" <button class=\"btn btn-lg btn-primary btn-block\" type=\"submit\">Sign in</button>\n");
|
||||
sb.append(" </form>\n");
|
||||
}
|
||||
if (this.oauth2LoginEnabled) {
|
||||
sb.append("<h2 class=\"form-signin-heading\">Login with OAuth 2.0</h2>");
|
||||
sb.append(createError(loginError, errorMsg));
|
||||
|
|
|
@ -20,8 +20,6 @@ import java.util.Collections;
|
|||
import java.util.Locale;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -29,8 +27,6 @@ import org.springframework.context.support.MessageSourceAccessor;
|
|||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.SpringSecurityMessageSource;
|
||||
import org.springframework.security.web.WebAttributes;
|
||||
import org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter;
|
||||
|
@ -131,12 +127,6 @@ public class DefaultLoginPageGeneratingFilterTests {
|
|||
assertThat(response.getContentAsString()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void generatingPageWithOpenIdFilterOnlyIsSuccessFul() throws Exception {
|
||||
DefaultLoginPageGeneratingFilter filter = new DefaultLoginPageGeneratingFilter(new MockProcessingFilter());
|
||||
filter.doFilter(new MockHttpServletRequest("GET", "/login"), new MockHttpServletResponse(), this.chain);
|
||||
}
|
||||
|
||||
/* SEC-1111 */
|
||||
@Test
|
||||
public void handlesNonIso8859CharsInErrorMessage() throws Exception {
|
||||
|
@ -178,25 +168,6 @@ public class DefaultLoginPageGeneratingFilterTests {
|
|||
assertThat(response.getContentAsString()).contains("Login with SAML 2.0");
|
||||
assertThat(response.getContentAsString())
|
||||
.contains("<a href=\"/saml/sso/google\">Google < > " ' &</a>");
|
||||
} // Fake OpenID filter (since it's not in this module
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class MockProcessingFilter extends AbstractAuthenticationProcessingFilter {
|
||||
|
||||
MockProcessingFilter() {
|
||||
super("/someurl");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
|
||||
throws AuthenticationException {
|
||||
return null;
|
||||
}
|
||||
|
||||
String getClaimedIdentityFieldName() {
|
||||
return "unused";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue