Spring security: after log out the login doesn't work anymore if I use maxSessionsPreventsLogin() - spring

I'm using Spring Security to perform log in and log out.
Log in and log out seem to work well everytime I perform them.
If I add maxSessionsPreventsLogin() the log in works during the first attempt; after the log out, I can't log in anymore. The method failureUrl() is called and the user is redirect to /login?error
This is my configure method:
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin()
.loginPage("/login")
.usernameParameter("userId")
.passwordParameter("password");
httpSecurity.formLogin()
.defaultSuccessUrl("/")
.failureUrl("/login?error")
.and()
.sessionManagement()
.maximumSessions(1)
.maxSessionsPreventsLogin(true);
httpSecurity.logout()
.logoutSuccessUrl("/login?logout");
httpSecurity.exceptionHandling()
.accessDeniedPage("/login?accessDenied");
httpSecurity.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/**/add").access("hasRole('ADMIN')")
.antMatchers("/**/market/**").access("hasRole('USER')");
}
The csrf system is enabled, and accordingly to Spring Security needs I put
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
inside the login form and inside the log out form (in which I perform a POST request to "/logout")
Can anybody help me? Thank you

You can also try to invalidate the session upon logout
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
.clearAuthentication(true)
.permitAll();

Related

Excluding a specific page from Spring Security that is redirected from login page

I am having trouble while I am redirecting an authentication link from my login page. I added the link in to my login page in JSF like this:
<div>
Login via Testinium Cloud
</div>
My spring security configuration is like this:
and()
.authorizeRequests()
.antMatchers(DEFAULT_URL).permitAll()
.antMatchers("/javax.faces.resource/**").permitAll()
.antMatchers("/jsfPages/*").permitAll()
.antMatchers("/errorPages/*").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.accessDeniedHandler(jsfAccessDeniedHandler())
.authenticationEntryPoint(jsfAuthenticationEntryPoint())
.and()
.formLogin()
.loginPage(LOGIN_PAGE).permitAll()
.failureUrl(LOGIN_PAGE).permitAll()
.defaultSuccessUrl(DEFAULT_URL)
.successHandler(authSuccessHandler)
.and()
.logout()
.logoutUrl(LOGOUT_URL).permitAll()
.invalidateHttpSession(true)
.logoutSuccessHandler(logoutSuccessHandler)
.and()
.exceptionHandling().accessDeniedPage("/error/403.xhtml");
How could I redirect my link from login page without gettin an authentication error. I tried
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/api/v1/signup");
}
But it didn't work out for me. Thanks!
If you want to exclude a page from your spring security configuration without overriding web security, you can add 'not' method that is connected to 'antMatchers' method in your code with authenticated() method following like this:
.authorizeRequests()
.antMatchers(DEFAULT_URL).permitAll()
.antMatchers("/javax.faces.resource/**").permitAll()
.antMatchers("/jsfPages/*").permitAll()
.antMatchers("/errorPages/*").permitAll()
.antMatchers(LOGIN_TESTINIUM).not().authenticated()
.anyRequest().authenticated()
.and()

When I call logout it changes the jsessionid, but still allows me to access other paths without having to log in

I'm attempting to logout using Spring Security, but any time I call the logout url it changes the jsessionid, but I can still access urls that should be restricted and ask for me to log back in.
public void configure(HttpSecurity httpSecurity) throws Exception{
httpSecurity.httpBasic();
httpSecurity.authorizeRequests()
.mvcMatchers(HttpMethod.GET, "/privateEvent").hasAuthority("REGISTERED_USER")
.mvcMatchers(HttpMethod.DELETE, "/privateEvent/*").hasAuthority("RSVP_ADMIN")
.mvcMatchers("/registerPrivateEvent").hasAuthority("REGISTERED_USER")
.mvcMatchers("/guestList").hasAuthority("EVENT_PUBLISHER")
.mvcMatchers("/eventPublishersList").hasAuthority("RSVP_ADMIN")
.anyRequest().permitAll()
.and()
.logout()
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID")
.deleteCookies("XSRF-TOKEN")
.clearAuthentication(true)
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/allDone")
.permitAll()
.and()
.csrf().disable();
}

Spring boot security: Requested url creates unwanted redis session

Lets say the login url is "/login".
There are two protected resources:
"/protected"
"/" which is a 302 redirect to "/protected"
When a unauthenticated user tries to access "/protected" he is being redirected to "/login". In background there is a session created, where SPRING_SECURITY_SAVED_REQUEST is stored in order to redirect user to the "/protected" url after successful login.
This is the default behaviour of spring security.
My issue:
Sessions are being created even when users call "/". So all the bots and penetration tests, which call the domain without valid login information do create sessions in the underlying redis layer.
How can I prevent these sessions from being created when there is no redirect request stored or at least limit them to a defined list of valid backend endpoints?
My security configuration:
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/password/forgot/**").permitAll()
.antMatchers("/password/reset/**").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/img/**").permitAll()
.antMatchers( "/favicon.ico").permitAll()
.antMatchers("/login").permitAll()
.anyRequest().fullyAuthenticated();
http
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(authSuccessHandler)
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login")
.deleteCookies("SESSION")
.clearAuthentication(true)
.invalidateHttpSession(true)
.permitAll();
http.sessionManagement()
.maximumSessions(1)
.and()
.sessionCreationPolicy(SessionCreationPolicy.NEVER);
http.headers().frameOptions().disable();
http.csrf().disable();
}
You could avoid having SPRING_SECURITY_SAVED_REQUEST created by setting NullRequestCache, but I guess that wouldn't work for your use case.
or at least limit them to a defined list of valid backend endpoints?
This could be done by providing a requestCache and setting the RequestMatcher -
final HttpSessionRequestCache requestCache = new HttpSessionRequestCache();
requestCache.setRequestMatcher(new AntPathRequestMatcher("/**"));
http
.authorizeRequests()
.antMatchers("/", "/home").permitAll()
.anyRequest().authenticated()
.and()
.requestCache().requestCache(requestCache)
.and()...

Do not start sessions for anonymous users

How can I disable sessions for anonymous users in spring boot 2.0?
My current configuration:
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/password/forgot/**").permitAll()
.antMatchers("/password/reset/**").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/img/**").permitAll()
.antMatchers("/manage/**").permitAll()
.antMatchers( "/favicon.ico").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(authSuccessHandler)
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login")
.invalidateHttpSession(true)
.permitAll();
}
}
When I open the login page, there is still a session created:
Perhaps the session is being automatically created by Spring Security. That behavior can be disabled by setting create-session to never. This means Spring Security will not attempt to automatically create a session.
<http create-session="never">
[...]
</http>
Some more details here: https://www.baeldung.com/spring-security-session
try adding "anonymous.disable()" after http in FormLoginWebSecurityConfigurerAdapter class.
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.anonymous.disable()
.authorizeRequests()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/password/forgot/**").permitAll()
.antMatchers("/password/reset/**").permitAll()
.antMatchers("/css/**").permitAll()
.antMatchers("/js/**").permitAll()
.antMatchers("/img/**").permitAll()
.antMatchers("/manage/**").permitAll()
.antMatchers( "/favicon.ico").permitAll()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/login")
.permitAll()
.successHandler(authSuccessHandler)
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login")
.invalidateHttpSession(true)
.permitAll();
}
Enjoyy!
In my case I had to do 3 things:
Add http.anonymous.disable() to my WebSecurityConfigurerAdapter.
Also add http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.NEVER). I don't know why, but this DOES create sessions for my authenticated users, even though the docs say that it will never create sessions for you.
Deleted all my cookies before testing. I discovered that if you made a request with an old session cookie, the server would use said cookie to create a new session, ignoring completely the SessionCreationPolicy we just set.

Spring Boot, Spring Security specify redirect login url

At my Spring Boot application I need to implement a following scenario:
Anonymous User visits the following page: http://example.com/product-a.html
This User wants to ask a question about this product. It can be done at another page, located by the following address: http://example.com/product-a/ask. User press Ask Question button at the http://example.com/product-a.html and login/registration popup is shown. After successful login User should be automatically redirected to http://example.com/product-a/ask (but currently with a default Spring Security implementation User are redirecting back to the page originator http://example.com/product-a.html)
How to properly with Spring Boot/Spring Security implement/configure this redirect ?
UPDATED
This is my web security config:
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
http
.csrf().ignoringAntMatchers("/v1.0/**", "/logout")
.and()
.authorizeRequests()
.antMatchers("/oauth/authorize").authenticated()
//Anyone can access the urls
.antMatchers("/images/**").permitAll()
.antMatchers("/signin/**").permitAll()
.antMatchers("/v1.0/**").permitAll()
.antMatchers("/auth/**").permitAll()
.antMatchers("/actuator/health").permitAll()
.antMatchers("/actuator/**").hasAuthority(Permission.READ_ACTUATOR_DATA)
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.failureUrl("/login?error=true")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl(logoutSuccessUrl)
.permitAll();
// #formatter:on
}
I use OAuth2/JWT + Implicit Flow for AngularJS client
I think you should not use spring's default /login processing url, but create your own e.g /mylogin in a controller. And then you can inject the HttpServletRequest in the method and take the action based on the context of the request for example:
#PostMapping("/mylogin")
public ResponseEntity<> processingLogingURL(HttpServletRequest request){
// switch bases on the request URL after checking security off course
switch(request.getRequestURL()){
//redirect based on the caller URL
}
}
and finally change your .loginProcessingUrl("/login") to .loginProcessingUrl("/mylogin")

Resources