I'm migrating an application from Spring Boot 1.5 to 2.0.5.
I have a property set as security.enable-csrf=true in 1.5 version which is not available in 2.0 version of Spring Boot.
I read the documents and it is said that in Spring Boot 2.0:
CSRF protection is enabled by default in the Java configuration.
So by default it is enabled ok fine, but there is also one class created which extends WebSecurityConfigurerAdapter this means Spring Boot default security configuration has been turned off. Is this also means security.enable-csrf is disabled now?
If yes how do I enable it like I had it in the application for 1.5 version.
I didn't get any document which gives a clear confirmation on how to handle security.enable-csrf property in Spring Boot 2.0 and while declaring the WebSecurityConfigurerAdapter.
Does anyone know about it? Also any document link which I have missed to read about this would be great help.
In order to have backward compatibility with the property already been set in you application, security.enable-csrf=true, you can use the following code:
#EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {
#Value("${security.enable-csrf}")
private boolean csrfEnabled;
#Override
protected void configure(HttpSecurity http) throws Exception {
if (!csrfEnabled) {
http.csrf().disable();
}
}
}
As you might guess the magic comes from http.csrf().disable(); that
in the above code you can control enabling/disabling it by the
property you have set in you application.properties file.
More Info:
For more details you can also refer to the spring documents:
https://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#csrf
WebSecurityConfigurerAdapter is an abstract class, when you create a class which extends WebSecurityConfigurerAdapter, you will override void configure(HttpSecurity http) method.
You can disable csrf in this method, like that;
http.csrf().disable();
You can read this comment on top of the csrf() method (in HttpSecurity class).
Adds CSRF support. This is activated by default when using
WebSecurityConfigurerAdapter's default constructor. You can disable it ...."
This comment says that, when you extends this class, default constructor of WebSecurityConfigurerAdapter works and csrf is activated.
Related
In an attempt to develop a generic identity service for a project I am working on, I need to support Azure ADFS-based SAML security for UI pages and Oauth2 based security for my REST APIs in a single spring-boot application
I have a spring boot application attempting to provide SAML based protection for some of my UI resources and Oauth2 based protection for my REST APIs. The UI pages and the REST APIs are hosted in the same spring boot based application. I have a SecurityConfiguration class that extends WebSecurityConfigurerAdapter and that contains my SAML configuration. I also have a ResourceServerConfig class that extends ResourceServerConfigurerAdapter where I have tried to configure the Oauth2 authentication for my REST APIs.
Here is what my code looks like
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
/////// Other methods //////
#Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests().anyRequest().authenticated();
http.httpBasic().authenticationEntryPoint(samlEntryPoint());
http.csrf().disable();
http.addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class).addFilterAfter(samlFilter(), BasicAuthenticationFilter.class);
http.authorizeRequests().antMatchers("/oauth/token").permitAll().anyRequest().authenticated();
}
The ResourceServerConfig class looks something like the following
#Configuration
#EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter
{
#Override
public void configure(HttpSecurity http) throws Exception
{
http
.csrf().disable()
.anonymous().and()
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS).permitAll()
.antMatchers("/api/**").authenticated();
}
My problem is, with the above configuration in place, I can either get SAML protection on my UI pages OR Oauth2 protection on my APIs but not both. If I remove #EnableResourceServer from the ResourceServerConfig class and try to access one of my UI pages, I am reliably redirected to the microsoft Azure login page which redirects me back to my UI page after successful authentication. But with this, any attempt to access my apis (with valid bearer tokens) results in a redirection to the microsoft Azure login page. If I re-enable #EnableResourceServer my APIs get protected and behave as expected but SAML protection for all UI pages gets completely disabled with spring allowing unhindered access to all UI resources.
I can't figure out how to tell spring boot to use which authentication framework for the two kinds of URL patterns I have. Is such a thing even possible?
Any help with this would be appreciated.
Regards,
Dipak Jha
I think I have found an answer to my own question. This reply here provides a workable solution. A properly configured OAuthRequestedMatcher seems to do the trick. Please let me know if someone thinks this can be done in a better way.
Regards
Dipak Jha
I recently upgraded from Spring Boot 1.x to Spring Boot 2.0.3 and I am trying to disable basic auth with no success.
#Configuration
#EnableWebSecurity(debug=true)
#EnableGlobalMethodSecurity(securedEnabled = true)
public class CustomSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.httpBasic().disable();
// the rest of my config
}
}
What hidden gem am I missing to just simply turn off basic auth?
Why does turning things off in Spring need to be so difficult now?
I was reading this:
https://github.com/spring-projects/spring-boot/issues/10306
and I have to agree that it should be much easier and a clearer explanation should be provided on how to turn this off.
EDIT
This link https://spring.io/blog/2017/09/15/security-changes-in-spring-boot-2-0-m4 talks about how the property was removed but doesn't say anything about how to continue to use the configuration as it exists in current application that utilize it.
I faced issue trying to get my roles updated from DB. Is it possible to programmatically add configuration to spring security. e.g.
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN");
Can i add a new configuration say .antMatchers("/user-service/**").hasRole("USER_DRIVER"); programmatically?
I tried adding a scheduled job using spring boot to refresh the configuration. However, they are not accepted.
Help appreciated.
Many thanks.
So i have a simple spring boot app with out-of-the-box security configuration. In my 'dev' profile I've open access to all URLS with these properties
# dev
security.basic.enabled=false
management.security.enabled=false
and I can enable authentication for all URL's in my 'production' profile by changing the values to
# production
security.basic.enabled=true
management.security.enabled=true
The real security requirement for the application is that it has two pages
The '/' index page should be public to all.
The '/admin' page should be restricted.
I know from countless other stackoverflow questions in spring-boot-security and spring-security that I can override the default spring-boot security config by using the #EnableWebSecurity and then defining custom rules
#EnableWebSecurity
public class WebMvcConfig extends WebMvcConfigurerAdapter {
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()....
}
I'm wondering is there not a simpler way which configures spring-boot only, and which doesn't involve the customisation of the spring-security to achieve this requirement?
There's a difference between overriding and configuring. By using #EnableWebSecurity, you're still just configuring Spring Security to work the way you want it to work. So to answer your question, no, there is not a "simpler way". This is how you do it and it isn't difficult.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.and()
.authorizeRequests()
.antMatchers("/admin/**").authenticated();
}
}
Something like that is more or less all you need based on your requirements.
The documentation for Spring Security states that in order to use the Java Config we can extend the AbstractSecurityWebApplicationInitializer class which will set up all nesesarry beans for Spring Security to work. This approach is working fine, the initializer is run automatically and Spring Security is initialized correctly during application startup.
But right now i am facing a scenario when this initialization should be depended on a system property. So i would like to include my initializer class only when some system property is set (for example: app.enablesecurity=true) and NOT execute this initializer in any other case.
I failed to come up with any solution for that scenario because:
In AbstractSecurityWebApplicationInitializer the onStartup method is
marked final so i cannot override it and add a condition
If i just extend AbstractSecurityWebApplicationInitializer it is
always automatically picked up by Spring and instantiated (or at least Spring tries to create instance of it, it may fail), even if i
declare it as a private/inner/nested class.
So as far as i know the only possibility of conditionally including this initializer is to use cglib/javassist in order to dynamically create a class that extends AbstractSecurityWebApplicationInitializer.
Is there any other way? Maybe there is some method that will allow me to hide my implementation from being picked up by Spring and run it by hand at a later time?
You can use Config Class like this to configure your security behavior
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Value("${app.enablesecurity}")
private boolean securityEnabled;
#Override
protected void configure(HttpSecurity http) throws Exception {
if (securityEnabled) {
http.csrf().disable();
...
} else {
http. ...
}
}
}