How to tune spring boot security configuration? - spring

I enabled spring boot security, and added some urls to exclusion list (porperty security.ignored)
in application.yaml.
Now I want to add some new urls to exclusion list programmatically, in my configuration class.
How could i achieve this ?
PS I cannot edit yaml, I'm able to edit only configuration class.

If you are looking to exclude some url patterns in java instead of yaml or properties.
Example:
If you need to exclude,
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login**").permitAll()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
.antMatchers("/**").access("hasRole('ROLE_USER')")
.and()
.formLogin().loginPage("/login").failureUrl("/login?error")
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
If you need to ignore,
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/authFailure");
}
Hope this is useful.

Related

favicon displayed only when user is connected

I use spring boot 2.6.7 with spring security and thymeleaf
I put my favicon in
resources/static/
I see only the icon when the user is connected
I added this code to permit all
#Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.antMatchers(HttpMethod.POST, "/printdownload**").permitAll()
.antMatchers(
"/",
"/help**",
"/css/**",
"/js/**",
"**/favicon.ico",
"/img/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/login").permitAll()
.successHandler(customAuthenticationSuccessHandler)
.and()
.logout();
}
#Override
public void configure(WebSecurity web) {
web.ignoring().antMatchers("/css/**", "/js/**", "/img/**", "**/favicon.ico");
}
But get same result.
If i try to display: http://localhost:8080/favicon.ico
that return me to the login page
You need to use /**/favicon.ico instead of **/favicon.ico.
According to the Javadoc of Spring's AntPathMatcher:
A pattern and a path must both be absolute or must both be relative in order for the two to match. Therefore it is recommended that users of this implementation to sanitize patterns in order to prefix them with "/" as it makes sense in the context in which they're used.
That you can use ** as short-cut for /** to match all requests is a special case. It doesn't work if ** is used at the beginning of a pattern.

Endpoint not accessible after Boot 2.6 upgrade

After upgrading the Boot version in my project to 2.6.0, my endpoint is no longer accessible, I'm automatically redirected to the login page even though I configured it with a permitAll() directive:
#Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("presentations")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin();
}
// ...
}
It seems this is actually related to how Spring Boot processes the mvcMatchers values after the upgrade:
The default strategy for matching request paths against registered Spring MVC handler mappings has changed from AntPathMatcher to PathPatternParser.
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.6-Release-Notes#deferred-openid-connect-discovery
And this new setup requires my presentations pattern to start with /:
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/presentations")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin();
}
Alternatively, if I had several routes and I need a quick fix I could set up the following application property to revert this to its previous behavior:
spring.mvc.pathmatch.matching-strategy=ant-path-matcher
BTW, path-pattern-parser is the default value, as it seems to be more efficient... here is some additional information on this and on the differences between PathPatternParser and AntPathMatcher:
https://spring.io/blog/2020/06/30/url-matching-with-pathpattern-in-spring-mvc
https://docs.spring.io/spring-framework/docs/5.3.13/reference/html/web.html#mvc-ann-requestmapping-uri-templates
EDIT: I also realized that using antMatchers() made some of my MockMvc tests fail, this was a bug that got fixed in Boot 2.6.1.

How to exclude a path from authentication in a spring based reactive application?

In a non reactive spring application I would usually create a configuration class, extend WebSecurityConfigurerAdapter and configure the WebSecurity like such:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/pathToIgnore");
}
How can I do the equivalent in a reactive application?
In your security config class which you have annotated with #EnableWebFluxSecurity and #EnableReactiveMethodSecurity, register a bean as follows:
#Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http.authorizeExchange()
.pathMatchers("/pathToIgnore")
.permitAll()
.anyExchange()
.authenticated()
.and()
.formLogin()
.and()
.csrf()
.disable()
.build();
}
In this config, pathMatchers("/pathToIgnore").permitAll() would configure it to allow the paths matched to be excluded from auth and anyExchange().authenticated() would configure it to authenticate all other requests.

Why does HttpSecurity configuration via DSL not seem to work the same as explicit configuration?

I went through the trouble to write a DSL to configure the HttpSecurity for my custom authentication mechanism, but most of the configuration I apply to it doesn't seem to be in effect when the application runs, while everything works perfectly when I configure it all manually in the webapp.
First, the manual configuration, which results in my EntryPoint firing, authenticationProvider being queried, the filter being added to the chain, and my rememberMeServices being added to that filter. Everything correct.
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/auth/callback").permitAll()
.anyRequest().authenticated()
.and()
.authenticationProvider(authProvider)
.rememberMe()
.rememberMeServices(rememberMeServices)
.and()
.exceptionHandling()
.authenticationEntryPoint(entryPoint)
.and()
.addFilterAfter(filter, UsernamePasswordAuthenticationFilter.class);
/* The following code is basically what gets run when the DSL is in use
http
.apply(new EPIdentityDsl())
// lots of setters called here, removed for clarity
.and()
.authorizeRequests().anyRequest().authenticated();
*/
}
}
However, the code in the DSL looks like this, and when it is used, the authenticationEntryPoint never fires. The rememberMeServices do get configured, and it looks like the filter gets added to the chain correctly, but I just get an error page for a 403 response instead of seeing the entryPoint redirection.
public class EPIdentityDsl extends AbstractHttpConfigurer<EPIdentityDsl, HttpSecurity> {
#Override
public void init(HttpSecurity http) throws Exception {
// any method that adds/removes another configurer
// must be done in the init method
log.debug("dsl init");
http
.exceptionHandling()
.and()
.rememberMe();
}
#Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(filterProcessesUrl).permitAll()
.and()
.authenticationProvider(authProvider)
.exceptionHandling()
.authenticationEntryPoint(entryPoint)
.and()
.rememberMe()
.rememberMeServices(rememberMeServices)
.and()
.addFilterAfter(filter, UsernamePasswordAuthenticationFilter.class);
}
}
Clearly, there's some subtle interaction that I'm missing in the documentation or something, causing my DSL-based configuration of entryPoint to get lost. Any idea why? If I had to guess, it would be that I'm doing something wrong with the way I'm specifying paths, but I can't figure it out.
I had a similar problem. I solved it by moving entryPoint to init

Spring Security mapping uppercase in URL

I work on a JEE project, using the Spring Boot framework.
For the authentification, I use Spring Security, and I specified the pages in my template.
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/token", "/index", "/index.html", "/main", "/main.html", "/main2", "/main2.html", "/recent1", "/recent1.html", "/recent2", "/recent2.html").hasRole("USER");
http
.csrf()
.disable()
.formLogin()
.loginPage("/login")
.failureUrl("/login?error=true")
.defaultSuccessUrl("/index");
http
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login");
}
The issue is that when I run the application and I wrote the URL with uppercase letters like: localhost:8080/INDEX.HTML or I add two letters localhost/index.httml, the page does appear without authantification.
If I understand correctly, here is the desired logic:
/login does not need to be secured by Spring Security (no roles are required)
All the other pages have to be secured with "USER" role.
To implement this, you could try the following:
#Override
public void configure(WebSecurity web) throws Exception {
// configuring here URLs for which security filters
// will be disabled (this is equivalent to using
// security="none")
web
.ignoring()
.antMatchers(
"/login"
)
;
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().hasRole("USER");
http.csrf().disable().formLogin()
.loginPage("/login").failureUrl("/login?error=true")
.defaultSuccessUrl("/index");
http.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login");
}
So item 1 (no security on /login) is moved to configure(WebSecurity), and item 2 is left in the original configure(HttpSecurity).

Resources