I am configuring Spring Security. To authenticate and authorize users, I override configure(AuthenticationManagerBuilder auth) of WebSecurityConfigurerAdapter. This works fine. Below is my code:
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(getPasswordEncoder());
}
But when I try to to enable method level security, per action, using #EnableGlobalMethodSecurity(securedEnabled = true) it throws an exception:
No AuthenticationManager found
As per my understanding AuthenticationManager is used to authenticate and authorize users, which I was already doing using configure(AuthenticationManagerBuilder auth) and Spring was injecting auth object itself.
Why I need to register AuthenticationManager manually?
#Bean #Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
What are the differennt purposes configure(AuthenticationManagerBuilder auth) and authenticationManagerBean() serves?
I am extending WebSecurityConfigurerAdapter. Why I need to provide a custom AuthenticationManager by overriding authenticationManagerBean().
Your configuration class extends WebSecurityConfigurerAdapter, which only configures web security (not method security):
Provides a convenient base class for creating a WebSecurityConfigurer instance. The implementation allows customization by overriding methods.
So your AuthenticationManager is only used for web security.
If you want to configure (change the defaults) method security, you can extend GlobalMethodSecurityConfiguration:
Base Configuration for enabling global method security. Classes may extend this class to customize the defaults, but must be sure to specify the EnableGlobalMethodSecurity annotation on the subclass.
To configure AuthenticationManager for method security, you can
overwrite GlobalMethodSecurityConfiguration#configure:
Sub classes can override this method to register different types of authentication. If not overridden, configure(AuthenticationManagerBuilder) will attempt to autowire by type.
expose your AuthenticationManager as a bean that can be autowired by GlobalMethodSecurityConfiguration, see WebSecurityConfigurerAdapter#authenticationManagerBean:
Override this method to expose the AuthenticationManager from configure(AuthenticationManagerBuilder) to be exposed as a Bean.
use only one global AuthenticationManager by autowiring the global AuthenticationManagerBuild, see Spring Security 3.2.0.RC2 Released:
For example, if you want to configure global authentication (i.e. you only have a single AuthenticationManager) you should autowire the AuthenticationMangerBuilder:
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
// ... configure it ...
}
Related
I'm facing a use where I have to check oauth token against 2 different oauth provider given an input context (private call to may api vs public call)
Is there a simple way to define 2 oauth provider in spring boot and how to configure this balancing between the 2 providers ?
First you will need to implement 2 AuthenticationProvider then in your configuration class that implements WebSecurityConfigurerAdapter you would autowire those providers. Finally override the public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception { to add those providers.
#Configuration
public class SampleAuthConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider1 provider1;
#Autowired
private CustomAuthenticationProvider2 provider2;
#Override
public void configure(AuthenticationManagerBuilder authenticationManagerBuilder) throws Exception {
authenticationManagerBuilder
.authenticationProvider(this.provider1)
.authenticationProvider(this.provider2);
}
}
Below are some tutorials. The may be outdated but may help you to figure it out.
https://dzone.com/articles/spring-security-authentication
https://www.baeldung.com/spring-security-multiple-auth-providers
Hello GUYS I am new in spring security, I found article about authentication global (#Autowired configure) and local authentication (#Override configure)
could you tell me what is the difference between #Autowired configure() and #Override configure.
//Global
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin").password("admin#password").roles("ROLE_ADMIN");
}
}
//local
#Configuration
#EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("admin").password("admin#password").roles("ROLE_ADMIN");
}
}
One way of looking at it is that the global AuthenticationManager is "global" because it can be shared across the application as a bean, so when you #Autowire an AuthenticationManager, you must be configuring the global AuthenticationManager. If not, the AuthenticationManager you configure locally as you do above will only exist within the context of your WebSecurityConfigurerAdapter.
Take a look at this guide in the Spring website.
The Authentication and Access Control guide ( the same NatFar has provided link to) describes the following
Sometimes an application has logical groups of protected resources
(e.g. all web resources that match a path pattern /api/**), and each
group can have its own dedicated AuthenticationManager. Often, each of
those is a ProviderManager, and they share a parent. The parent is
then a kind of "global" resource, acting as a fallback for all
providers.
The image depicts the global (parent) and local resources , which is self explanatory
Also go through the links :
https://github.com/spring-projects/spring-security/issues/4571
https://github.com/spring-projects/spring-security/issues/4324
I'm using Spring Boot 2.0 (leveraging Spring Security 5.0). I'm trying to add a custom AuthenticationProvider to the AuthenticationManager in my WebSecurityConfigurerAdapter subclass. If I override the configure(AuthenticationManagerBuilder) method to supply my new provider, then I do not know how to retrieve the AuthenticationManager as a bean.
Ex:
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(customAuthenticationProvider);
}
}
where customAuthenticationProvider implements AuthenticationProvider.
In the Spring docs, it seems to specify that the two are incompatible:
5.8.4 AuthenticationProvider You can define custom authentication by exposing a custom AuthenticationProvider as a bean. For example, the
following will customize authentication assuming that
SpringAuthenticationProvider implements AuthenticationProvider:
[Note] This is only used if the AuthenticationManagerBuilder has not
been populated
Indeed, if I try to retrieve the AuthenticationManager bean using:
#Bean
public AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManagerBean();
}
then the configure() method is never even called.
So how can I add my own custom provider to the default list of providers, and still be able to retrieve the AuthenticationManager?
You can just override WebSecurityConfigurerAdapter.authenticationManagerBean() method and annotate it with #Bean annotation
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
And there is no Spring Boot 5.0, The latest release is Spring Boot 2.0. I believe you are talking about Spring Security 5.0.
I am trying to add basic authentication for my APIs where the users will be authenticated based on their credential stored in MongoDB. I want to use java config instead of XML based config. So far what I have learnt is I have to create #Configuration by extending WebSecurityConfigurerAdapter and override configure method. In that I can add a custom filter by addFilterBefore().
But how can I get a Authentication header information in the filter, how to proceed if the user is authenticated. I have been googling a lot but didn't find any good example that will help a novice like me whose been into spring just for 1 week.
Does any one have a good tutorial or sample that can help me get started with this? Thanks in advance.
As example, you can use next solution.
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().authenticationEntryPoint(getBasicAuthenticationEntryPoint());
}
#Bean
public BasicAuthenticationEntryPoint getBasicAuthenticationEntryPoint(){
BasicAuthenticationEntryPoint basicAuthenticationEntryPoint = new BasicAuthenticationEntryPoint();
basicAuthenticationEntryPoint.setRealmName("Basic Authentication");
return basicAuthenticationEntryPoint;
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
}
It works for me. But you need to implement UserDetailsService interface.
Spring automatically checks is user authenticated and tries to proceed authentication if not.
I have created additional authentication providers. I am registering them like following:
#Configuration
#EnableWebMvcSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
class SecurityConfig extends WebSecurityConfigurerAdapter{
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(tokenAP());
auth.authenticationProvider(usernameAndPasswordAP());
auth.userDetailsService(getUserDetailsService());
}
Later in my code I am using AuthenticationManager to authenticate users. The issue is that I have only one authentication provider registered in authentication manager which is DaoAuthenticationProvider. It looks like my authentication providers are not registered at all. Should I do some additional config to make it work? I am using spring boot 1.2.6 Thanks in advance for any tips. Best Regards
When you override the configure(AuthenticationManagerBuilder auth), the underlying AuthenticationManager is exposed in one of 2 ways:
1) within SecurityConfig, you can simply call authenticationManager()
2) if you need AuthenticationManager outside of your SecurityConfig you will need to expose it as a bean, for example:
class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(tokenAP());
auth.authenticationProvider(usernameAndPasswordAP());
auth.userDetailsService(getUserDetailsService());
}
#Bean
#Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
The way we have authentication providers configured in our Spring Boot web applications is similar to what is discussed in the example Spring Security Java configuration from the current release reference guide, which modifies the default autowired AuthenticationManagerBuilder. Using your methods, it might look like:
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(tokenAP())
.authenticationProvider(usernameAndPasswordAP())
.userDetailsService(getUserDetailsService());
}
If I am reading the Javadocs for the configure(AuthenticationManagerBuilder) method correctly, when you override this method you must specify your own AuthenticationManager. By using the autowired instance as described above, the default AuthenticationManager (which is ProviderManager, which in turn delegates to one or more configured AuthorizationProvider instances).
You may also need to annotate your configuration class with:
#Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
So that your access control rules are applied before the defaults that Spring Boot will otherwise configure for you.