I try to translate the following websecurity configuration written in Java to a plain-yml configuration.
#Order(Ordered.HIGHEST_PRECEDENCE)
#Configuration
#EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UserDetailsService userDetailsService;
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/register/**").permitAll()
.anyRequest().authenticated().and().csrf().disable()
.httpBasic();
}
#Autowired
public void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService);
}
}
This is the security relevant part of my application.yml:
security:
require_ssl: true
basic:
enabled: true
enable_csrf: false
ignored:
- /register/**
When I use the yml-version the endpoints are not accessible without authentication, but also valid users are not permitted to access the site. I think it's because I am using a custom userDetailsService which is not recognised.
How can I define the same behaviour of the registerAuthentication-method part with the yml-version? Is there a security.userDetailsServiceClass property or something similar?
On application properties reference there is nothing related to UserDetailsService, so must be not supported,also it's a advanced condiguration which can be done by normal configuration. Boot provides via properties only simple configuration to get start quickly, like httpBasic, you can combine both, but note your
ignored:
- /register/**
are clashing with Java Config's matchers
Related
I'm developing a library that introduces a new authentication filter, that should be used in the spring-security chain
I know I can add the filter via something like:
#EnableResourceServer
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true)
class AmazingSecurityConfiguration extends WebSecurityConfigurerAdapter {
// filter bean
#Autowired
private MyFilter myFilter;
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
// ... bunch of requirements per path
// ... or ignore path "/bla"
// etc.
.anyRequest().authenticated();
http.addFilterBefore(myFilter.getFilter(),
AbstractPreAuthenticatedProcessingFilter.class);
}
}
However, this wouldn't work alongside a user defined config. Really, I want to be configuring this bean within my library AutoConfigure class, that's triggered by the spring factories.
Looking around online, I see examples where they extend the WebSecurityConfigurerAdapter class themselves, and have the user extend this new config. But I don't know if this blocks a user from doing something else, and it also relies on the user first calling super.configure(http) to have the filter loaded.
What's the correct way here?
I was able to configure my own http configuration by fiddling with the invocation order of the beans within the autoconfiguration
#Configuration
#ConditionalOnClass(WebSecurityConfigurerAdapter.class)
// Two annotations below ensure that this is not the only WebSecurityConfigurerAdapter,
// as it might otherwise disable security for the rest of the application
// The Order ensures that Spring default which uses ConditionalOnMissingBean is still configured before this class
#AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
#ConditionalOnBean(WebSecurityConfigurerAdapter.class)
class LibraryFooSecurityConfig {
#RequiredArgsConstructor
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE)
class WebSecurityConfig extends WebSecurityConfigurerAdapter {
// autowired in from elsewhere in the autoconfig
private final MyFilter filter;
#Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(filter,
AbstractPreAuthenticatedProcessingFilter.class);
}
}
}
This allows a user-defined security config to extend WebSecurityConfigurerAdapter and apply their own rules, while still allowing our library to add it's own items after that of the actual spring-boot application
I am new to JPA and Spring Boot.
http://www.baeldung.com/spring-security-registration-password-encoding-bcrypt
I'm looking to encode the password -- where would I place this bean -- do I just define it in my application.properties or in the pom.xml
Also you can define in your #Configuration beans, but is recommend to define password encoder in your ##EnableWebSecurity beans, it is automatically add #Configuration annotation for you and you can config more security related things.
#EnableWebSecurity
public class YourWebConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
}
I tried disabling all actuator endpoints for production environment in application.yml configuration file:
endpoints.enabled: false
It works for all endpoints except for /info.
How can I turn off all endpoints for given environment?
UPDATE:
Project I am working on is also acting as Eureka client.
In documentation for Spring Cloud Netflix in section Status Page and Health Indicator (http://cloud.spring.io/spring-cloud-netflix/spring-cloud-netflix.html) it says that "Eureka instance default to "/info" and "/health" respectively".
Is there any solution to disable those endpoints?
I was able to disable /health endpoint with endpoints.enabled: false, but not the /info endpoint.
Finally I managed to solve my problem. I enabled only /info and /health endpoints in actuator. And to allow access to /info endpoint only to users with role ADMIN I needed to mix actuator management security and spring security configuration.
So my application.yml looks like this:
endpoints.enabled: false
endpoints:
info.enabled: true
health.enabled: true
management.security.role: ADMIN
And spring security configuration like this (where I needed to change order of ManagementSecurityConfig to have higher priority):
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {
#Configuration
protected static class AuthenticationSecurity extends GlobalAuthenticationConfigurerAdapter {
#Autowired
private AuthenticationProvider authenticationProvider;
public AuthenticationSecurity() {
super();
}
#Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("secret").roles("ADMIN");
}
}
#Configuration
#Order(Ordered.HIGHEST_PRECEDENCE + 2)
public static class ManagementSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requestMatchers()
.antMatchers("/info/**")
.and()
.authorizeRequests()
.anyRequest().hasRole("ADMIN")
.and()
.httpBasic();
}
}
#Configuration
public static class ApiWebSecurityConfigurationAdapter extends WebSecurityConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
// API security configuration
}
}
}
Your sample configuration looks suspicious to me. I guess you meant
endpoints:
enabled: true
In any case, I just tried to add this to a vanilla Spring Boot app (using 1.3.1 and all endpoints were disabled (as expected).
I am working on Spring Security Java-based configuration.
I have created my own MyAuthenticationProvider which I want to register in the ProviderManager (single instance of AuthenticationManager).
I have found that ProviderManager has a list of providers to which I can register my single
MyAuthenticationProvider.
Here is the part of my Configuration:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(MyAuthenticationProvider);
}
}
I found out that AuthenticationManagerBuilder has parentAuthenticationManager, defaultUserDetailsService and many other fields.
My questions are:
Where is this #Autowired annotation adding AuthenticationManagerBuilder auth from?
Is the AuthenticationManagerBuilder already created in the application context?
What would be the default state of AuthenticationManagerBuilder which is being injected? By default state I mean will there be some parentAuthenticationManager, authenticationProviders already registered in the AuthenticationManagerBuilder?
If I am adding auth.authenticationProvider(MyAuthenticationProvider), does this mean that I am adding one more provider in the AuthenticationManagerBuilder?
What does this mean? Taken from Spring Documentation
The name of the configureGlobal method is not important. However, it
is important to only configure AuthenticationManagerBuilder in a class
annotated with either #EnableWebSecurity, #EnableWebMvcSecurity,
#EnableGlobalMethodSecurity, or #EnableGlobalAuthentication. Doing
otherwise has unpredictable results.
Answer for 1:
#EnableWebSecurity is meta-annotated with #EnableGlobalAuthentication
...
#EnableGlobalAuthentication
#Configuration
public #interface EnableWebSecurity {
...
and #EnableGlobalAuthentication imports AuthenticationConfiguration:
...
#Import(AuthenticationConfiguration.class)
#Configuration
public #interface EnableGlobalAuthentication {
}
In AuthenticationConfiguration, you'll see that an AuthenticationManagerBuilder bean is declared:
...
#Bean
public AuthenticationManagerBuilder authenticationManagerBuilder(
ObjectPostProcessor<Object> objectPostProcessor, ApplicationContext context) {
...
}
When you #Autowire an AuthenticationManagerBuilder, this is the one that you will get. You have several methods at your disposal to easily configure in-memory, jdbc, ldap,... authentication.
Answer for 2:
Background:
The Spring Security Java config goes through several stages to seamlessly incorporate your configurations with the ApplicationContext.One place where this comes together is in the getHttp() method in WebSecurityConfigurerAdapter.
For example, this is an excerpt:
AuthenticationManager authenticationManager = authenticationManager();
authenticationBuilder.parentAuthenticationManager(authenticationManager);
To give you an idea of how "not-straightforward" the sequence of configuration is, the authenticationManager variable above will be either:
The authentication manager you added by overriding configure(AuthenticationManagerBuilder auth)
OR: The authentication manager you added in the method that #Autowired the AuthenticationManagerBuilder bean from AuthenticationConfiguration
OR: an AuthenticationManager bean found in the context
By default state I mean will there be some [...] authenticationProviders already registered in the AuthenticationManagerBuilder
If you look at AuthenticationConfiguration, you'll see that by default, the InitializeUserDetailsBeanManagerConfigurer is applied to the AuthenticationManagerBuilder bean. As long as it finds a UserDetailsService bean in the context and no other provider has been added, it will add a DaoAuthenticationProvider. This is why in the Spring Security reference, only providing a #Bean UserDetailsService bean is sufficient.
But once you add an authentication provider as you did, the "default" provider is not registered.
Answer for 3:
Yes. The code of AuthenticationManagerBuilder adds your provider:
public AuthenticationManagerBuilder authenticationProvider(AuthenticationProvider authenticationProvider) {
this.authenticationProviders.add(authenticationProvider);
return this;
}
Answer for 4 is simple:
It means that, once you have one of that annotations, you can name your method as you wish:
#Configuration
#EnableWebSecurity //or #EnableWebMvcSecurity or #EnableGlobalMethodSecurity....
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
public void myCoolMethodName(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(MyAuthenticationProvider);
}
}
"Doing otherwise has unpredictable results"
If you keep the name but not the annotations, it may not work.
I have, what I think is, a very simple and basic setup for locally running a Spring Boot webapp with some authentication.
I would expect that when I run this application through Spring Boot, that my custom security settings would override the default behavior when I specify the local profile.
mvn -Dspring.profiles.active="local" spring-boot:run
Maybe I'm specifying the profiles.active wrong, but when the app runs, it still spits out a generated password to use, and doesn't seem to allow any access to the /login path without said authentication.
I'm also not seeing the active profiles under /env either, which may be a little telling.
I have a WebSecurityConfigurer overridden like so:
#Configuration
#EnableWebSecurity
#Profile("local")
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin().permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("admin").password("admin").roles("ADMIN", "USER")
.and().withUser("user").password("user").roles("USER");
}
}
My main #Configuration class is your standard Spring Java-style base config:
#Configuration
#ComponentScan
#EnableAutoConfiguration
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I think I ran into the same issue. I wanted to use Spring profiles to select between none, basic, form, etc. auth. However, if I put the #Profile, #Configuration, and #EnableWebMvcSecurity on the public class WebSecurityConfig extends WebSecurityConfigurerAdapter class, like they show in the examples, basic auth was active at times when I wanted no auth. (This is with #SpringBootApplication on my Application class.
I achieved what I wanted with making beans out of WebSecurityConfigurerAdapter, instead of #Configurations (code snippet is in Groovy):
#Configuration
#EnableWebMvcSecurity
class SecurityConfig {
#Bean
#Profile('no-auth')
WebSecurityConfigurerAdapter noAuth() {
new WebSecurityConfigurerAdapter() {
#Override
void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll()
}
}
}
#Bean
#Profile('default')
WebSecurityConfigurerAdapter basic() {
new WebSecurityConfigurerAdapter() {
#Override
void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers('/').permitAll()
.anyRequest().authenticated()
.and()
.httpBasic()
}
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
}
}
Second attempt to provide better control of security settings. What's the high level options for controlling security auto configuration:
Switch off security completely and permanently:
remove Spring Security from the classpath
or exlude security auto config - #EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
Switch off default basic auth security by setting security.basic.enabled=false
It is pretty easy to control different security settings if you have a total control of how security settings, security auto configuration and spring profiles are used.
#Configuration
#ComponentScan
public class Application {
public static void main(String[] args) throws Throwable {
SpringApplication.run(Application.class, args);
}
}
#Configuration
public class WebSecurityConfig {
#Configuration
#EnableAutoConfiguration(exclude = SecurityAutoConfiguration.class)
#ConditionalOnExpression("!${my.security.enabled:false}")
protected static class DefaultWebSecurityConfig {
}
#Configuration
#EnableAutoConfiguration
#EnableWebMvcSecurity
#Profile("local")
#ConditionalOnExpression("${my.security.enabled:false}")
protected static class LocalWebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated();
http
.formLogin().loginPage("/login").permitAll().and()
.logout().permitAll();
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("password").roles("USER");
}
}
}
In above classes I basically removed #EnableAutoConfiguration from Application class order to use it conditionally. Created two config classes, DefaultWebSecurityConfig and LocalWebSecurityConfig which are chosen by my.security.enabled flag using a Boot #ConditionalOnExpression.
First config simply excludes SecurityAutoConfiguration if my security is not enabled. Second one enabled security and uses local profile. By creating yet another config with a different profile you can control what happens with different profiles. Then you could choose if security is enabled and which profile is used:
#java -jar build/libs/gs-securing-web-0.1.0.jar
#java -jar build/libs/gs-securing-web-0.1.0.jar --spring.profiles.active=local --my.security.enabled=true
If you have an option to use application.yml, different settings could be automatically applied per profile still defining a default values. This would be good if you just want to disable default basic authentication enabled by default security auto config.
security:
basic:
enabled: false
---
spring:
profiles: local
security:
basic:
enabled: true
---
There are probably a million different ways to do these and it's always case by case which works best for current use case.
maven will spawn a new process to run a boot app and it doesn't inherit your -Dspring.profiles.active="local" which you passed to mvn command itself.
Why don't you just build the boot fat jar and then run it manually as an executable jar and then you can control what command line parameters you pass to your program.
Other than that, Spring Boot reference doc mentions in a security chapter:
If Spring Security is on the classpath then web applications will be secure by default with “basic” authentication on all HTTP endpoints.
So I just tried this with Securing a Web Application Guide and if I added what you wrote in your question, app defaults to basic authentication when using a profile which is not active.
#EnableAutoConfiguration allows you to define excludes for autoconfiguration classes, but you need to find a way to disable this together with a profile. So possibly wrapping #EnableAutoConfiguration in two different #Configuration classes enabled by different profiles so that other would exclude security auto-configuration.
What we do (in more sophisticated way) in framework itself is a usage of #Conditional which provides better way to enable/disable parts of auto-configuration.