AuthenticationConfigurationTests -> java

Issue: gh-4939
This commit is contained in:
Rob Winch 2018-01-26 15:14:34 -06:00
parent f7e49ace9f
commit e5d40c0599
2 changed files with 478 additions and 518 deletions

View File

@ -1,518 +0,0 @@
/*
* Copyright 2002-2013 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
*
* http://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.authentication.configuration;
import org.springframework.aop.framework.ProxyFactoryBean
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.core.Ordered
import org.springframework.core.annotation.Order
import org.springframework.security.access.annotation.Secured
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager
import org.springframework.security.authentication.AuthenticationProvider
import org.springframework.security.authentication.TestingAuthenticationToken
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.config.annotation.BaseSpringSpec
import org.springframework.security.config.annotation.ObjectPostProcessor
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter
import org.springframework.security.core.AuthenticationException
import org.springframework.security.core.authority.AuthorityUtils
import org.springframework.security.core.context.SecurityContextHolder
import org.springframework.security.core.userdetails.PasswordEncodedUser
import org.springframework.security.core.userdetails.User
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder
import org.springframework.security.crypto.password.PasswordEncoder
import org.springframework.security.provisioning.InMemoryUserDetailsManager
class AuthenticationConfigurationTests extends BaseSpringSpec {
def "Ordering Autowired on EnableGlobalMethodSecurity"() {
setup:
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
when:
loadConfig(GlobalMethodSecurityAutowiredConfigAndServicesConfig)
then:
context.getBean(Service).run()
}
@Configuration
@Import([GlobalMethodSecurityAutowiredConfig,ServicesConfig])
static class GlobalMethodSecurityAutowiredConfigAndServicesConfig {}
@EnableGlobalMethodSecurity(securedEnabled = true)
static class GlobalMethodSecurityAutowiredConfig {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user())
}
}
def "Ordering Autowired on EnableWebSecurity"() {
setup:
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
when:
loadConfig(GlobalMethodSecurityConfigAndServicesConfig)
then:
context.getBean(Service).run()
}
@Configuration
@Import([GlobalMethodSecurityConfig,WebSecurityConfig,ServicesConfig])
static class GlobalMethodSecurityConfigAndServicesConfig {}
@EnableGlobalMethodSecurity(securedEnabled = true)
static class GlobalMethodSecurityConfig {}
@EnableWebSecurity
static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user())
}
}
//
def "Ordering Autowired on EnableWebMvcSecurity"() {
setup:
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password","ROLE_USER"))
when:
loadConfig(GlobalMethodSecurityMvcSecurityAndServicesConfig)
then:
context.getBean(Service).run()
}
@Configuration
@Import([GlobalMethodSecurityConfig,WebMvcSecurityConfig,ServicesConfig])
static class GlobalMethodSecurityMvcSecurityAndServicesConfig {}
@EnableWebSecurity
static class WebMvcSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user())
}
}
//
def "no authentication getAuthenticationManager falls back to null"() {
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
then:
context.getBean(AuthenticationConfiguration).authenticationManager == null
}
def "QuiesentGlobalAuthenticationConfiguererAdapter falls back to null"() {
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,QuiesentGlobalAuthenticationConfiguererAdapter)
then:
context.getBean(AuthenticationConfiguration).authenticationManager == null
}
@Configuration
static class QuiesentGlobalAuthenticationConfiguererAdapter extends GlobalAuthenticationConfigurerAdapter {}
//
def "GlobalAuthenticationConfiguererAdapterImpl configures authentication successfully"() {
setup:
def token = new UsernamePasswordAuthenticationToken("user", "password")
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,GlobalAuthenticationConfiguererAdapterImpl)
then:
context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token)?.name == "user"
}
@Configuration
static class GlobalAuthenticationConfiguererAdapterImpl extends GlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser(PasswordEncodedUser.user())
}
}
//
def "AuthenticationManagerBean configures authentication successfully"() {
setup:
def token = new UsernamePasswordAuthenticationToken("user", "password")
def auth = new UsernamePasswordAuthenticationToken("user", "password", AuthorityUtils.createAuthorityList("ROLE_USER"))
AuthenticationManagerBeanConfig.AM = Mock(AuthenticationManager)
1 * AuthenticationManagerBeanConfig.AM.authenticate(token) >> auth
when:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration,AuthenticationManagerBeanConfig)
then:
context.getBean(AuthenticationConfiguration).authenticationManager.authenticate(token).name == auth.name
}
@Configuration
static class AuthenticationManagerBeanConfig {
static AuthenticationManager AM
@Bean
public AuthenticationManager authenticationManager() {
AM
}
}
//
@Configuration
static class ServicesConfig {
@Bean
public Service service() {
return new ServiceImpl()
}
}
static interface Service {
public void run();
}
static class ServiceImpl implements Service {
@Secured("ROLE_USER")
public void run() {}
}
//
def "GlobalAuthenticationConfigurerAdapter are ordered"() {
setup:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.setGlobalAuthenticationConfigurers([new LowestOrderGlobalAuthenticationConfigurerAdapter(), new HighestOrderGlobalAuthenticationConfigurerAdapter(), new DefaultOrderGlobalAuthenticationConfigurerAdapter()])
when:
config.getAuthenticationManager()
then:
DefaultOrderGlobalAuthenticationConfigurerAdapter.inits == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
DefaultOrderGlobalAuthenticationConfigurerAdapter.configs == [HighestOrderGlobalAuthenticationConfigurerAdapter,DefaultOrderGlobalAuthenticationConfigurerAdapter,LowestOrderGlobalAuthenticationConfigurerAdapter]
}
static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
static List inits = []
static List configs = []
public void init(AuthenticationManagerBuilder auth) throws Exception {
inits.add(getClass())
}
public void configure(AuthenticationManagerBuilder auth) throws Exception {
configs.add(getClass())
}
}
@Order(Ordered.LOWEST_PRECEDENCE)
static class LowestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
@Order(Ordered.HIGHEST_PRECEDENCE)
static class HighestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
//
def "Spring Boot not triggered when already configured"() {
setup:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.setGlobalAuthenticationConfigurers([new ConfiguresInMemoryConfigurerAdapter(), new BootGlobalAuthenticationConfigurerAdapter()])
AuthenticationManager authenticationManager = config.authenticationManager
when:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user","password"))
then:
noExceptionThrown()
when:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
then:
thrown(AuthenticationException)
}
def "Spring Boot is triggered when not already configured"() {
setup:
loadConfig(AuthenticationConfiguration,ObjectPostProcessorConfiguration)
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.setGlobalAuthenticationConfigurers([new BootGlobalAuthenticationConfigurerAdapter()])
AuthenticationManager authenticationManager = config.authenticationManager
when:
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot","password"))
then:
noExceptionThrown()
}
static class ConfiguresInMemoryConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser(PasswordEncodedUser.user())
}
}
@Order(Ordered.LOWEST_PRECEDENCE)
static class BootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.apply(new DefaultBootGlobalAuthenticationConfigurerAdapter())
}
}
static class DefaultBootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
if(auth.isConfigured()) {
return;
}
User user = User.withUserDetails(PasswordEncodedUser.user()).username("boot").build()
List<User> users = Arrays.asList(user);
InMemoryUserDetailsManager inMemory = new InMemoryUserDetailsManager(users);
DaoAuthenticationProvider provider = new DaoAuthenticationProvider()
provider.userDetailsService = inMemory
auth.authenticationProvider(provider)
}
}
def "SEC-2531: AuthenticationConfiguration#lazyBean should use BeanClassLoader on ProxyFactoryBean"() {
setup:
ObjectPostProcessor opp = Mock()
Sec2531Config. opp = opp
loadConfig(Sec2531Config)
when:
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.getAuthenticationManager()
then:
1 * opp.postProcess(_ as ProxyFactoryBean) >> { args ->
args[0]
}
}
@Configuration
@Import(AuthenticationConfiguration)
static class Sec2531Config {
static ObjectPostProcessor opp
@Bean
public ObjectPostProcessor objectPostProcessor() {
opp
}
@Bean
public AuthenticationManager manager() {
null
}
}
def "SEC-2822: Cannot Force Authentication already built"() {
setup:
loadConfig(Sec2822WebSecurity,Sec2822UseAuth,Sec2822Config)
when:
AuthenticationConfiguration config = context.getBean(AuthenticationConfiguration)
config.getAuthenticationManager()
then:
noExceptionThrown()
}
@Configuration
@Import(AuthenticationConfiguration)
static class Sec2822Config {}
@Configuration
@EnableWebSecurity
static class Sec2822WebSecurity extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.inMemoryAuthentication()
}
}
@Configuration
static class Sec2822UseAuth {
@Autowired
public void useAuthenticationManager(AuthenticationConfiguration auth) {
auth.authenticationManager
}
// Ensures that Sec2822UseAuth is initialized before Sec2822WebSecurity
// must have additional GlobalAuthenticationConfigurerAdapter to trigger SEC-2822
@Bean
public static GlobalAuthenticationConfigurerAdapter bootGlobalAuthenticationConfigurerAdapter() {
new BootGlobalAuthenticationConfigurerAdapter()
}
static class BootGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { }
}
def 'SEC-2868: Allow Configure UserDetailsService'() {
setup:
UserDetailsService uds = Mock()
UserDetailsServiceBeanConfig.UDS = uds
loadConfig(UserDetailsServiceBeanConfig)
AuthenticationManager am = context.getBean(AuthenticationConfiguration).getAuthenticationManager()
when:
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
then:
1 * uds.loadUserByUsername("user") >> PasswordEncodedUser.user()
when:
am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid"))
then:
1 * uds.loadUserByUsername("user") >> PasswordEncodedUser.user()
thrown(AuthenticationException.class)
}
@Configuration
@Import([AuthenticationConfiguration, ObjectPostProcessorConfiguration])
static class UserDetailsServiceBeanConfig {
static UserDetailsService UDS
@Bean
UserDetailsService userDetailsService() {
UDS
}
}
def 'SEC-2868: Allow Configure UserDetailsService with PasswordEncoder'() {
setup:
UserDetailsService uds = Mock()
UserDetailsServiceBeanWithPasswordEncoderConfig.UDS = uds
loadConfig(UserDetailsServiceBeanWithPasswordEncoderConfig)
AuthenticationManager am = context.getBean(AuthenticationConfiguration).getAuthenticationManager()
when:
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"))
then:
1 * uds.loadUserByUsername("user") >> new User("user",'$2a$10$FBAKClV1zBIOOC9XMXf3AO8RoGXYVYsfvUdoLxGkd/BnXEn4tqT3u',AuthorityUtils.createAuthorityList("ROLE_USER"))
when:
am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid"))
then:
1 * uds.loadUserByUsername("user") >> new User("user",'$2a$10$FBAKClV1zBIOOC9XMXf3AO8RoGXYVYsfvUdoLxGkd/BnXEn4tqT3u',AuthorityUtils.createAuthorityList("ROLE_USER"))
thrown(AuthenticationException.class)
}
@Configuration
@Import([AuthenticationConfiguration, ObjectPostProcessorConfiguration])
static class UserDetailsServiceBeanWithPasswordEncoderConfig {
static UserDetailsService UDS
@Bean
UserDetailsService userDetailsService() {
UDS
}
@Bean
PasswordEncoder passwordEncoder() {
new BCryptPasswordEncoder()
}
}
def 'gh-3091: Allow Configure AuthenticationProvider'() {
setup:
AuthenticationProvider ap = Mock()
AuthenticationProviderBeanConfig.AP = ap
loadConfig(AuthenticationProviderBeanConfig)
AuthenticationManager am = context.getBean(AuthenticationConfiguration).getAuthenticationManager()
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
User user = new User("user","password",AuthorityUtils.createAuthorityList("ROLE_USER"))
when:
am.authenticate(token)
then:
1 * ap.supports(_) >> true
1 * ap.authenticate(token) >> new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities())
}
@Configuration
@Import([AuthenticationConfiguration, ObjectPostProcessorConfiguration])
static class AuthenticationProviderBeanConfig {
static AuthenticationProvider AP
@Bean
AuthenticationProvider authenticationProvider() {
AP
}
}
def 'AuthenticationProvider Bean Prioritized over UserDetailsService'() {
setup:
UserDetailsService uds = Mock()
AuthenticationProvider ap = Mock()
AuthenticationProviderBeanAndUserDetailsServiceConfig.AP = ap
AuthenticationProviderBeanAndUserDetailsServiceConfig.UDS = uds
loadConfig(AuthenticationProviderBeanAndUserDetailsServiceConfig)
AuthenticationManager am = context.getBean(AuthenticationConfiguration).getAuthenticationManager()
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
User user = new User("user","password",AuthorityUtils.createAuthorityList("ROLE_USER"))
when:
am.authenticate(token)
then:
1 * ap.supports(_) >> true
1 * ap.authenticate(token) >> new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities())
0 * uds._
}
@Configuration
@Import([AuthenticationConfiguration, ObjectPostProcessorConfiguration])
static class AuthenticationProviderBeanAndUserDetailsServiceConfig {
static AuthenticationProvider AP
static UserDetailsService UDS
@Bean
AuthenticationProvider authenticationProvider() {
AP
}
@Bean
UserDetailsService uds() {
UDS
}
}
def 'EnableGlobalMethodSecurity configuration uses PreAuthorize does not cause BeanCurrentlyInCreationException'() {
when:
loadConfig(UsesPreAuthorizeMethodSecurityConfig,AuthenticationManagerBeanConfig)
then:
noExceptionThrown()
}
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class UsesPreAuthorizeMethodSecurityConfig {
@PreAuthorize("denyAll")
void run() {}
}
def 'EnableGlobalMethodSecurity uses method security service'() {
when:
loadConfig(ServicesConfig,UsesPreAuthorizeMethodSecurityConfig,AuthenticationManagerBeanConfig)
then:
noExceptionThrown()
}
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
static class UsesServiceMethodSecurityConfig {
@Autowired
Service service
}
}

View File

@ -0,0 +1,478 @@
/*
* 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
*
* http://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.authentication.configuration;
import org.apache.http.auth.AUTH;
import org.junit.After;
import org.junit.Rule;
import org.junit.Test;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.TestAuthentication;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.config.users.AuthenticationTestConfiguration;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.PasswordEncodedUser;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
public class AuthenticationConfigurationTests {
@Rule
public final SpringTestRule spring = new SpringTestRule();
@Autowired(required = false)
private Service service;
@After
public void cleanup() {
SecurityContextHolder.clearContext();
}
@Test
public void orderingAutowiredOnEnableGlobalMethodSecurity() {
this.spring.register(AuthenticationTestConfiguration.class, GlobalMethodSecurityAutowiredConfig.class, ServicesConfig.class).autowire();
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER"));
this.service.run();
}
@EnableGlobalMethodSecurity(securedEnabled = true)
static class GlobalMethodSecurityAutowiredConfig {
}
@Test
public void orderingAutowiredOnEnableWebSecurity() {
this.spring.register(AuthenticationTestConfiguration.class, WebSecurityConfig.class, GlobalMethodSecurityAutowiredConfig.class, ServicesConfig.class).autowire();
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER"));
this.service.run();
}
@EnableWebSecurity
static class WebSecurityConfig {}
@Test
public void orderingAutowiredOnEnableWebMvcSecurity() {
this.spring.register(AuthenticationTestConfiguration.class, WebMvcSecurityConfig.class, GlobalMethodSecurityAutowiredConfig.class, ServicesConfig.class).autowire();
SecurityContextHolder.getContext().setAuthentication(new TestingAuthenticationToken("user", "password", "ROLE_USER"));
this.service.run();
}
@EnableWebMvcSecurity
static class WebMvcSecurityConfig {}
@Test
public void getAuthenticationManagerWhenNoAuthenticationThenNull() throws Exception {
this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire();
assertThat(this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager()).isNull();
}
@Test
public void getAuthenticationManagerWhenNoOpGlobalAuthenticationConfigurerAdapterThenNull() throws Exception {
this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, NoOpGlobalAuthenticationConfigurerAdapter.class).autowire();
assertThat(this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager()).isNull();
}
@Configuration
static class NoOpGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {}
@Test
public void getAuthenticationWhenGlobalAuthenticationConfigurerAdapterThenAuthenticates() throws Exception {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, UserGlobalAuthenticationConfigurerAdapter.class).autowire();
AuthenticationManager authentication = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager();
assertThat(authentication.authenticate(token).getName()).isEqualTo(token.getName());
}
@Configuration
static class UserGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser(PasswordEncodedUser.user());
}
}
@Test
public void getAuthenticationWhenAuthenticationManagerBeanThenAuthenticates() throws Exception {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("user", "password");
this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, AuthenticationManagerBeanConfig.class).autowire();
AuthenticationManager authentication = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager();
when(authentication.authenticate(token)).thenReturn(TestAuthentication.authenticatedUser());
assertThat(authentication.authenticate(token).getName()).isEqualTo(token.getName());
}
@Configuration
static class AuthenticationManagerBeanConfig {
AuthenticationManager authenticationManager = mock(AuthenticationManager.class);
@Bean
public AuthenticationManager authenticationManager() {
return authenticationManager;
}
}
//
// //
//
@Configuration
static class ServicesConfig {
@Bean
public Service service() {
return new ServiceImpl();
}
}
interface Service {
void run();
}
static class ServiceImpl implements Service {
@Secured("ROLE_USER")
public void run() {}
}
@Test
public void getAuthenticationWhenMultipleThenOrdered() throws Exception {
this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class, AuthenticationManagerBeanConfig.class).autowire();
AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class);
config.setGlobalAuthenticationConfigurers(Arrays.asList(new LowestOrderGlobalAuthenticationConfigurerAdapter(), new HighestOrderGlobalAuthenticationConfigurerAdapter(), new DefaultOrderGlobalAuthenticationConfigurerAdapter()));
}
static class DefaultOrderGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
static List<Class<?>> inits = new ArrayList<>();
static List<Class<?>> configs = new ArrayList<>();
public void init(AuthenticationManagerBuilder auth) throws Exception {
inits.add(getClass());
}
public void configure(AuthenticationManagerBuilder auth) throws Exception {
configs.add(getClass());
}
}
@Order(Ordered.LOWEST_PRECEDENCE)
static class LowestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
@Order(Ordered.HIGHEST_PRECEDENCE)
static class HighestOrderGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {}
@Test
public void getAuthenticationWhenConfiguredThenBootNotTrigger() throws Exception {
this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire();
AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class);
config.setGlobalAuthenticationConfigurers(Arrays.asList(new ConfiguresInMemoryConfigurerAdapter(), new BootGlobalAuthenticationConfigurerAdapter()));
AuthenticationManager authenticationManager = config.getAuthenticationManager();
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
assertThatThrownBy(() -> authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password")))
.isInstanceOf(AuthenticationException.class);
}
@Test
public void getAuthenticationWhenNotConfiguredThenBootTrigger() throws Exception {
this.spring.register(AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class).autowire();
AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class);
config.setGlobalAuthenticationConfigurers(Arrays.asList(new BootGlobalAuthenticationConfigurerAdapter()));
AuthenticationManager authenticationManager = config.getAuthenticationManager();
authenticationManager.authenticate(new UsernamePasswordAuthenticationToken("boot", "password"));
}
static class ConfiguresInMemoryConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser(PasswordEncodedUser.user());
}
}
@Order(Ordered.LOWEST_PRECEDENCE)
static class BootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.apply(new DefaultBootGlobalAuthenticationConfigurerAdapter());
}
}
static class DefaultBootGlobalAuthenticationConfigurerAdapter extends DefaultOrderGlobalAuthenticationConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
if (auth.isConfigured()) {
return;
}
UserDetails user = User.withUserDetails(PasswordEncodedUser.user()).username("boot").build();
List<UserDetails> users = Arrays.asList(user);
InMemoryUserDetailsManager inMemory = new InMemoryUserDetailsManager(users);
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(inMemory);
auth.authenticationProvider(provider);
}
}
// gh-2531
@Test
public void getAuthenticationManagerWhenPostProcessThenUsesBeanClassLoaderOnProxyFactoryBean() throws Exception {
this.spring.register(Sec2531Config.class).autowire();
ObjectPostProcessor<Object> opp = this.spring.getContext().getBean(ObjectPostProcessor.class);
when(opp.postProcess(any())).thenAnswer(a -> a.getArgument(0));
AuthenticationConfiguration config = this.spring.getContext().getBean(AuthenticationConfiguration.class);
config.getAuthenticationManager();
verify(opp).postProcess(any(ProxyFactoryBean.class));
}
@Configuration
@Import(AuthenticationConfiguration.class)
static class Sec2531Config {
@Bean
public ObjectPostProcessor objectPostProcessor() {
return mock(ObjectPostProcessor.class);
}
@Bean
public AuthenticationManager manager() {
return null;
}
}
@Test
public void getAuthenticationManagerWhenSec2822ThenCannotForceAuthenticationAlreadyBuilt() throws Exception {
this.spring.register(Sec2822WebSecurity.class, Sec2822UseAuth.class, Sec2822Config.class).autowire();
this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager();
// no exception
}
@Configuration
@Import(AuthenticationConfiguration.class)
static class Sec2822Config {}
@Configuration
@EnableWebSecurity
static class Sec2822WebSecurity extends WebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication();
}
}
@Configuration
static class Sec2822UseAuth {
@Autowired
public void useAuthenticationManager(AuthenticationConfiguration auth) throws Exception {
auth.getAuthenticationManager();
}
// Ensures that Sec2822UseAuth is initialized before Sec2822WebSecurity
// must have additional GlobalAuthenticationConfigurerAdapter to trigger SEC-2822
@Bean
public static GlobalAuthenticationConfigurerAdapter bootGlobalAuthenticationConfigurerAdapter() {
return new BootGlobalAuthenticationConfigurerAdapter();
}
static class BootGlobalAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { }
}
// sec-2868
@Test
public void getAuthenticationWhenUserDetailsServiceBeanThenAuthenticationManagerUsesUserDetailsServiceBean() throws Exception {
this.spring.register(UserDetailsServiceBeanConfig.class).autowire();
UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class);
AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager();
when(uds.loadUserByUsername("user")).thenReturn(PasswordEncodedUser.user(), PasswordEncodedUser.user());
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
assertThatThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid")))
.isInstanceOf(AuthenticationException.class);
}
@Configuration
@Import({AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class})
static class UserDetailsServiceBeanConfig {
UserDetailsService uds = mock(UserDetailsService.class);
@Bean
UserDetailsService userDetailsService() {
return this.uds;
}
}
@Test
public void getAuthenticationWhenUserDetailsServiceAndPasswordEncoderBeanThenEncoderUsed() throws Exception {
UserDetails user = new User("user", "$2a$10$FBAKClV1zBIOOC9XMXf3AO8RoGXYVYsfvUdoLxGkd/BnXEn4tqT3u",
AuthorityUtils.createAuthorityList("ROLE_USER"));
this.spring.register(UserDetailsServiceBeanWithPasswordEncoderConfig.class).autowire();
UserDetailsService uds = this.spring.getContext().getBean(UserDetailsService.class);
AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager();
when(uds.loadUserByUsername("user")).thenReturn(User.withUserDetails(user).build(), User.withUserDetails(user).build());
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
assertThatThrownBy(() -> am.authenticate(new UsernamePasswordAuthenticationToken("user", "invalid")))
.isInstanceOf(AuthenticationException.class);
}
@Configuration
@Import({AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class})
static class UserDetailsServiceBeanWithPasswordEncoderConfig {
UserDetailsService uds = mock(UserDetailsService.class);
@Bean
UserDetailsService userDetailsService() {
return this.uds;
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
//gh-3091
@Test
public void getAuthenticationWhenAuthenticationProviderBeanThenUsed() throws Exception {
this.spring.register(AuthenticationProviderBeanConfig.class).autowire();
AuthenticationProvider ap = this.spring.getContext().getBean(AuthenticationProvider.class);
AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager();
when(ap.supports(any())).thenReturn(true);
when(ap.authenticate(any())).thenReturn(TestAuthentication.authenticatedUser());
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
}
@Configuration
@Import({AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class})
static class AuthenticationProviderBeanConfig {
AuthenticationProvider provider = mock(AuthenticationProvider.class);
@Bean
AuthenticationProvider authenticationProvider() {
return this.provider;
}
}
@Test
public void getAuthenticationWhenAuthenticationProviderAndUserDetailsBeanThenAuthenticationProviderUsed() throws Exception {
this.spring.register(AuthenticationProviderBeanAndUserDetailsServiceConfig.class).autowire();
AuthenticationProvider ap = this.spring.getContext().getBean(AuthenticationProvider.class);
AuthenticationManager am = this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager();
when(ap.supports(any())).thenReturn(true);
when(ap.authenticate(any())).thenReturn(TestAuthentication.authenticatedUser());
am.authenticate(new UsernamePasswordAuthenticationToken("user", "password"));
}
@Configuration
@Import({AuthenticationConfiguration.class, ObjectPostProcessorConfiguration.class})
static class AuthenticationProviderBeanAndUserDetailsServiceConfig {
AuthenticationProvider provider = mock(AuthenticationProvider.class);
UserDetailsService uds = mock(UserDetailsService.class);
@Bean
UserDetailsService userDetailsService() {
return this.uds;
}
@Bean
AuthenticationProvider authenticationProvider() {
return this.provider;
}
}
@Test
public void enableGlobalMethodSecurityWhenPreAuthorizeThenNoException() throws Exception {
this.spring.register(UsesPreAuthorizeMethodSecurityConfig.class, AuthenticationManagerBeanConfig.class).autowire();
// no exception
}
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
static class UsesPreAuthorizeMethodSecurityConfig {
@PreAuthorize("denyAll")
void run() {}
}
@Test
public void enableGlobalMethodSecurityWhenPreAuthorizeThenUsesMethodSecurityService() throws Exception {
this.spring.register(ServicesConfig.class, UsesPreAuthorizeMethodSecurityConfig.class, AuthenticationManagerBeanConfig.class).autowire();
// no exception
}
@Configuration
@EnableGlobalMethodSecurity(securedEnabled = true)
static class UsesServiceMethodSecurityConfig {
@Autowired
Service service;
}
}