What's the difference with these two different security approaches?
First one relies on configuring HttpSecurity object from Spring Security.
The second one relies on putting #PreAuthorize("isAuthenticated()") on each method or class.
First case:
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest()
.authenticated();
}
}
Second case:
#PreAuthorize("isAuthenticated()") on each method/class.
First approach looks better cause you secure all endpoints at once, and using #PreAuthorize requires more work. But what is actual difference between those two?
It is possible to authorize all requests on WebSecurityConfigurerAdapter and do the security with PreAuthorize on each service.
The advantage to use WebSecurityConfigurerAdapter is to have an overview of your security access.
But the #PreAuthorize allow you to have a more fine grained security handling. For exemple, you can tell that a user have the permission to edit an article only if he has write this article.
I think in a big application, it's ok to use both.
Related
I want to make a config file to configure TLS and Oauth2 in my SecureConfig.java
The tls config:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.NEVER);
}
The Oauth2.0 config:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.requiresChannel()
.anyRequest()
.requiresSecure();
}
What is the better way to use these two in the same config file and method? Does the and() work fine?
Like that:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER).and()
.requiresChannel()
.anyRequest()
.requiresSecure();
}
Issue with your two filter chain approach (Regardless of what your configure inside the methods
Spring security is a chain of filters see Filters in Spring Security Filter Chain
By implementing configure(HttpSecurity http) twice, you have created two spring-security-filter-chains.
Since you are not providing http.requestMatcher(...), both chains are applicable to every url. And it is a problem for spring security as it will only apply one filter chain to a particular request. So if you try to start up your app, it will fail to start with an error
You can make your app start by defining an #Order annotation so spring security chooses the one with the lower number applicable for a url. But since both chains are applicable to every url as per your config, the filter chain with lower #Order overrides the filter chain with higher #Order making it useless
Solution
Use one class that extends WebSecurityConfigurerAdapter so you have one security filter chain
Channel Security vs Authentication vs Authorisation
Security is mainly 4 aspects. Authentication, Authorisation, Integrity and Confidentiality. Rest API under https security
What you have in the filter is about authentication. You may have also defined some urls need some roles which is Authorisation. So that config was about those 2 aspects
By requiresSecure() you are addressing Confidentiality. i.e If you use requiresSecure() without the first one, you know you are not talking to some middle man but you won't know who you are talking to because that is what the purpose of authentication.
Since they are complimentary security aspects, They can be combined together and spring will create one filter chain where the first filter ensures you are first talking over https by placing ChannelProcessingFilter as the first barrier
While configuring the security of my Spring Boot application, I wanted to secure parts of the API depending on the PathVariable that is entered there. My current configuration is as follows:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//not important
#Override
public void configure(HttpSecurity http) throws Exception {
http.cors();
http.authorizeRequests()
.mvcMatchers("/api").authenticated()
.mvcMatchers("/api/TEST").hasAuthority("SCOPE_dep:TEST")
.and().oauth2ResourceServer().jwt();
}
}
In the the 'api/{PathVariable}' endpoint is the one I want to have customized, making sure that someone with the authority 'SCOPE_dep:TEST' can access the 'api/TEST' endpoint, someone with 'SCOPE_dep:TEST2' authority can access the 'api/TEST2' endpoint, even allowing more then one such endpoint for a user which has multiple of these authorities.
Is there a way to do this by using a type of wildcard/matcher that I'm unaware of, or is the only possiblity hardcoding all these different authorities?
I'm creating a new Spring REST application with some basic services and entities.
I added Spring Security and without overriding any class, i just added to application.properties a user and password.
So far so good, i opened Postman to try out a endpoint and it always return 401 to my requests.
I tried in postman set the authorization via "Basic Auth" (is what header WWW-Authenticate asks), tried "Digest auth" using the "Realm" value from the header. But none of it works.
Here is what i have in my application.properties
spring.security.user.name=root
spring.security.user.password=root
This is my request
https://imgur.com/URM3TGD
(Sorry i can't embbed the image because of my reputation)
And here is the endpoint
#PostMapping("saveUsuario")
public Usuario saveUsuario(Usuario usuario) {
return usuarioRepository.save(usuario);
}
(If possible) i don't want to override any Spring Security class, just "use as it".
Thank you!
So here is what i found.
Thanks to #jzheaux we discover that the problem was with the csrf configuration (Using POST request).
So i was forced to override the class WebSecurityConfigurerAdapter to disable it.
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
}
}
But then, the endpoints could be called without authentication!
So, this is the final code:
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.cors();
http.authorizeRequests().anyRequest().fullyAuthenticated();
http.httpBasic();
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER);
}
}
First disable the CSRF.
Then enable Cors.
I set that i want any request to be fully authenticated
The challenge type is HTTP basic
I disable the creation of cookies so it'll always ask for credentials.
So far so good, it's working!
Per https://docs.spring.io/spring-boot/docs/1.5.0.RELEASE/reference/htmlsingle/#boot-features-security
you should change your password with
security.user.password=root
instead of spring.security.user.password=root
similar security properties that are overridable are in the #ConfigurationProperties class: SecurityProperties.java
See https://github.com/spring-projects/spring-boot/blob/v1.5.0.RELEASE/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/SecurityProperties.java
I am having a difficult time figuring out how to wire up spring security without forcing authentication. My specific app does not require the user to authenticate but the user can authenticate if they want.
I currently have a WebSecurityConfigurerAdapter set up that you can see at the end of this post. With this setup I'm getting a 403 on all /api/* requests and /j_spring_security_check.
Could someone please help me either fix my existing config or point me to a working example that accomplishes this?
Every example I see out there seems to require the user to authenticate and if they don't it throws a 403. In my app, I'm just using it to establish a session and at this point all users should be able to access all end points regardless of if they are authenticated or not.
WebSecurityConfig
#EnableWebSecurity
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private ItAuthenticationProvider customAuthenticationProvider;
#Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(customAuthenticationProvider);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**");
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers("/**").permitAll()
.antMatchers("/j_spring_security_check").permitAll()
.and().formLogin()
.loginProcessingUrl("/j_spring_security_check")
.defaultSuccessUrl("/successful.html")
.loginPage("/#login")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/successful.html");
}
}
You can take a look at this sample Spring Security application we built with Stormpath support. In this example, the home screen does not require authentication. Furthermore, the information that is displayed there is dynamically calculated based on whether the user is authenticated or not.
If I understand your requirement, you can use the anonymous authentication.
The documentation can be found here
Sorry to cross-post this here and the old spring forums, but I didn't get any responses and thought the original post may have gotten lost in the shuffle when the forums were deactivated. Anyhoo...
From the documentation, one can mimic multiple elements in the java config by extending WebSecurityConfigurerAdapter multiple times. I've done this, and added a couple custom filters to just one of them, but the odd thing is that the filters seem to be applied to all requests, even ones it shouldn't be matching. Here is a sample of my config:
#Configuration
class ConfigA extends WebSecurityConfigurerAdapter {
public void configure(HttpSecurity http) {
http
.antMatcher("/foo")
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
.addFilterAfter(myFilter, BasicAuthFilter.class)
...
}
}
#Configuration
class ConfigB extends WebSecurityConfigurerAdapter {
public void configure(HttpSecurity http) {
http
.antMatcher("/bar")
.authorizeRequests()
.anyRequest().fullyAuthenticated()
.and()
...
}
}
What am I missing? Is this by design that that filter is applied to both/all requests? Is the filter itself supposed to figure out which requests it should apply to?
Thanks,
Justin