How to log out sucessfully - spring-boot

My login page is http://localhost:8080/nradmin/welcome
and my home page (after successful log in) is http://localhost:8080/nradmin/home
I'd like to log out and not anymore be able anymore to access any other page like the home page but only the welcome (login) page. If I type http://localhost:8080/nradmin/home on the browser after logout I continue to have access to the home page without logging in.
I've implemented the following methods overriden from the abstract class WebSecurityConfigurerAdapter:
#Override
protected void configure(HttpSecurity http) throws Exception { http
.authorizeRequests()
.antMatchers("/welcome").permitAll()
.antMatchers("/home", "/account/**", "/price/**").hasRole("ADMIN")
.antMatchers("/home", "/account/**", "/price/**").access("hasRole('ROLE_ADMIN')")
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/welcome")
.defaultSuccessUrl("/home")
.and()
.logout()
.invalidateHttpSession(true)
.clearAuthentication(true)
.logoutSuccessUrl("/welcome")
.logoutUrl("/welcome")
.deleteCookies()
.permitAll()
.and()
.exceptionHandling()
.accessDeniedPage("/welcome")
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
#Override
protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication() .withUser("username").password(passwordEncoder().encode("12345")).roles(LoginDataConstants.ROLE_ADMIN)
}
#Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
Does anyone have an idea how to do it?

I guess it may be due to having the same url in the methods logoutUrl and logoutSuccessUrl.
I suggest you to change logoutUrl to other path, for example just /logout and then try to perform the logout hitting that url. It should complete the logout task and the redirect to the logoutSuccessUrl, which is /welcome

Add CSRF
Reference from spring docs.
Will perform logout with the URL /logout is requested with any HTTP method
#Override protected void configure(HttpSecurity http) throws Exception {
http.
logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
}
}
You can also reference a good example on stack overflow using this same method here
When I had this issue I used this line
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login");
Where
.logoutSuccessUrl("/login") was the page the user will be redirected to.
You could re-factor your code to something like this
#Override
protected void configure(HttpSecurity http) throws Exception { http
.authorizeRequests()
.antMatchers("/welcome").permitAll()
.antMatchers("/home", "/account/**", "/price/**").hasRole("ADMIN")
.antMatchers("/home", "/account/**", "/price/**").access("hasRole('ROLE_ADMIN')")
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/welcome")
.defaultSuccessUrl("/home")
.and()
.logout()
.and() // This section is re-factored.
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/welcome").deleteCookies("JSESSIONID") //Or try .logoutSuccessUrl("/nradmin/welcome")
.invalidateHttpSession(true)
.permitAll()
.and()
.exceptionHandling()
.accessDeniedPage("/welcome")
.and()
.sessionManagement()
.sessio hinCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
Update : This is a modified version. This is essentially what I use in my project except for this portion:
.and()
.exceptionHandling()
.accessDeniedPage("/welcome")
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
So, I believe it should work; otherwise, I believe it may be a setup issue/configuration that resides somewhere else in your project. Please try the below example.
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/nradmin/welcome", "/home", "/account/**", "/price/**").hasRole("ADMIN")
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/nradmin/welcome")
.permitAll()
.and()
.logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/nradmin/welcome").deleteCookies("JSESSIONID")
.invalidateHttpSession(true)
.permitAll()
.and()
.exceptionHandling()
.accessDeniedPage("/nradmin/welcome")
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}

Related

How to throw user to a page other than /login if user is not authenticated in spring security

I wanted to throw users out on signup page instead of login page when they are not authenticated. One workaroud I did was to pass "/signup" in .loginPage() function in Security configuration of spring boot application.
But now I also need to put a .rememberMe() feature for login page. because of that I have to pass "/login" in .loginPage(). So that I can add .rememberMe() functionality.
To summarize, How can I throw non-authenticated users to /signup page as well as keeping the rememberMe functionality on login page?
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/game*/**").authenticated()
.antMatchers("/contest*/**").authenticated()
.antMatchers("/badges_awards").authenticated()
.antMatchers("/admin*/**").hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login")
.usernameParameter("emailAddress")
.passwordParameter("password")
.permitAll()
.and()
.rememberMe()
.key("remember-me")
.rememberMeParameter("remember-me")
.rememberMeCookieName("rememberlogin")
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
http.csrf().disable();
http.headers().frameOptions().disable();
}
Start your configuration like this to tell Spring Security that /signup URL does not need authentication and therefore won't be redirect to your login page :
http.authorizeRequests()
.antMatchers("/signup").permitAll()
try this
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login.html").permitAll()
.antMatchers("/signup*/**").permitAll()
.and()
.formLogin()
.loginPage("/login")
.failureHandler(LoginAuthFailureHandler)
.and()
.exceptionHandling()
.accessDeniedPage("/signup.html");
}
#Component
public class LoginAuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
getRedirectStrategy().sendRedirect(request, response, "/signup.html");
}
}

Users are able to access all endpoints after setting antMachers in Spring Security

I'm developing a spring-boot application and its spring security configuration is as follows:
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.authorizeRequests()
.antMatchers("/actuator/**", "/login*", "/logout*")
.permitAll();
httpSecurity
.cors().and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/taas/v1/**").hasRole("admin")
.antMatchers("/taas/v1/teams", "/taas/v1/profiles", "/taas/v1/tests/summary").hasRole("tester")
.antMatchers( "/taas/v1/teams", "/taas/v1/tests/summary").hasRole("user")
.anyRequest().authenticated()
.and()
.exceptionHandling().accessDeniedHandler(customAccessDeniedHandler)
.and()
.httpBasic()
.and()
.formLogin()
.successHandler(customAuthenticationSuccessHandler)
.failureHandler(customAuthenticationFailureHandler)
.and()
.logout()
.logoutSuccessHandler(customLogoutSuccessHandler())
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
}
}
Even though i have set the url pattern for each roles. All users are able to access all endpoints as mentioned in antMatchers(). A user with role user is not supposed to access /taas/v1/profiles. But when I try to access that endpoint by logging in as user, I'm getting the response but expected response is 403 forbidden.
I request someone to provide a workaround for me.
I got this issue resolved by doing some minor changes in my antMatchers(). Below is the modified code.
The main issue is that antMatcher() pattern must not contain the context path, see Spring security antMatcher does not work
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors()
.and()
.authorizeRequests()
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/profiles").hasAnyRole("TESTER")
.antMatchers( "/teams", "/tests/summary").hasAnyRole("USER", "TESTER", "ADMIN")
.anyRequest().authenticated()
.and().csrf().disable()
.exceptionHandling()
.accessDeniedHandler(customAccessDeniedHandler)
.and()
.httpBasic()
.and()
.formLogin()
.successHandler(customAuthenticationSuccessHandler)
.failureHandler(customAuthenticationFailureHandler)
.and()
.sessionManagement()
.invalidSessionUrl("/invalidSession.html")
.maximumSessions(1).sessionRegistry(sessionRegistry()).and()
.sessionFixation().none()
.and()
.logout()
.logoutSuccessHandler(customLogoutSuccessHandler())
.invalidateHttpSession(true)
.deleteCookies("JSESSIONID");
}
}
Please verify the code that you're sharing because as you've mentioned. A user with role user is not supposed to access /ptaas/v1/profiles. But when I try to access that endpoint by logging in as user.
Where your mapping says you've not configured access to user role as given.
.antMatchers( "/taas/v1/teams", "/taas/v1/tests/summary").hasRole("user")
As per your comments it should have been .antMatchers( "/taas/v1/teams", "/taas/v1/tests/summary", "/ptaas/v1/profiles").hasRole("user")

Setting a DefaultAuthenticationEventPublisher in WebSecurityConfigurerAdapter for Spring Security 5

I've updated some of our services to Spring Security 5 from a SS 4 version where it had external support for OAuth2. I've been able to update our services for the most part.
Previously our WebSecurityConfigurerAdapter had the following configure function where we set an applicationEventPublisher on a OAuth2AuthenticationProcessingFilter so we can output logs messages about AuthenticationEvents.
But OAuth2AuthenticationProcessingFilter went away in SS5 because OAuth2 support is now directly supported.
Is their an easier way of setting the AuthenticationEventPublisher without creating my own filter and recreating the part of checking authentication to just have it done again by Spring?
#Override
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
OAuth2AuthenticationProcessingFilter filter = new OAuth2AuthenticationProcessingFilter();
filter.setAuthenticationManager(authenticationManager);
filter.setStateless(true);
filter.setAuthenticationEventPublisher(
new DefaultAuthenticationEventPublisher(applicationEventPublisher));
filter.afterPropertiesSet();
http.csrf()
.disable()
.anonymous()
.disable()
.httpBasic()
.disable()
.logout()
.disable()
.formLogin()
.disable()
.addFilterBefore(filter, SessionManagementFilter.class)
.antMatcher("/actuator/**")
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS)
.permitAll()
.antMatchers("/actuator/**")
.access("#oauth2.hasScope('auditor')")
.anyRequest()
.authenticated()
.accessDecisionManager(accessDecisionManager);
}
#Bean
public ApplicationListener<AuditApplicationEvent> onEventListener() {
return (AuditApplicationEvent event) -> {
LoggingUtil loggingFormat = new LoggingUtil();
loggingFormat.setUser(event.getAuditEvent().getPrincipal());
loggingFormat.setEvent("Resource Authentication");
loggingFormat.setOutcome(event.getAuditEvent().getType());
loggingFormat.setMessage(
event.getAuditEvent().getData().containsKey("message")
? event.getAuditEvent().getData().get("message").toString()
: "");
String info = loggingFormat.toString();
logger.info(info);
};
}
For our SS 5 we have
protected void configure(HttpSecurity http) throws Exception {
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
SessionManagementFilter as;
//TODO how do we setup the authenticationEventPublisher
//filter.setAuthenticationEventPublisher(
// new DefaultAuthenticationEventPublisher(applicationEventPublisher));
http.csrf()
.disable()
.anonymous()
.disable()
.httpBasic()
.disable()
.logout()
.disable()
.formLogin()
.disable()
// .addFilterBefore(filter, SessionManagementFilter.class)
.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS)
.permitAll()
.antMatchers("/actuator/**").hasAuthority("SCOPE_auditor")
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer().jwt();
}

Spring OAuth2 server : WebSecurityConfigurerAdapter how to allow another request than the login page

I' d like to allow another page than the login one in my configuration, a registration page. I use the authorization_code grant to connect the users from another service, the client, so they are redirected to the oauth2 server to login then they are redirected back to the client.
I created a registration form accessible from the login page, but I 'm not able to reach it I' m automaticly redirected to the login page.
Here is my configuration
#Override
protected void configure(HttpSecurity http) throws Exception { // #formatter:off
http.requestMatchers()
.antMatchers("/login**", "/oauth/**")
.and()
.authorizeRequests()//autorise les requetes
.anyRequest()//pour n'importe quel path
.authenticated()//aux utilisateur authentifié
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login.do")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.userDetailsService(userDetailsServiceBean());
}
I'd like to allow a /registration path but I don't know how to do that.
Here is the solution
#Override
protected void configure(HttpSecurity http) throws Exception { // #formatter:off
http.requestMatchers()
.antMatchers("/login**", "/registration"/*, "/logout.do"*/, "/oauth/**")
.and()
.authorizeRequests()
.antMatchers("/registration")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login.do")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.userDetailsService(userDetailsServiceBean());
}

Spring Security HTTP FormLogin

I have a problem with my Spring Security
#Configuration
#EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private UsuarioService usuarioService;
#Autowired
private PasswordEncoder passwordEncoder;
#Override
protected void configure(HttpSecurity http) throws Exception {
// #formatter:off
http
.authorizeRequests()
.antMatchers(
"/",
"/index/**",
"/register",
"/doregister",
"/login",
"/dologin",
"/logout-success",
"/confirmregister",
"/invaliduser",
"/expiredtoken",
"/userstatuslog",
"/verifyemail")
.permitAll()
.anyRequest()
.authenticated()
.and()
.authorizeRequests()
.antMatchers(
"/login",
"logout")
.permitAll()
.and()
.authorizeRequests()
.antMatchers(
"/static/css/**",
"/css/custom.css",
"/js/**",
"/images/**"
)
.permitAll()
.and()
.authorizeRequests()
.antMatchers(
"/forbidden",
"/edit-profile-about",
"/doeditprofileabout",
"/profile"
)
.hasRole("USER")
.and()
.authorizeRequests()
.antMatchers(
"/controlpanel",
"/forbidden",
"/edit-profile-about",
"/doeditprofileabout",
"/profile"
)
.hasRole("ADMIN")
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout()
.deleteCookies("remove")
.invalidateHttpSession(true)
.logoutUrl("/logout")
.logoutSuccessUrl("/logout-success")
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
// #formatter:on
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(usuarioService).passwordEncoder(passwordEncoder);
}
Everytime, I do login it sends me to the bootstrap file...
localhost:8080/css/bootstrap-3.3.7-dist/css/bootstrap.min.css
or...
localhost:8080/css/custom.css
or...
localhost:8080/js/jquery-2.1.4.min.js
but not to the same one (it seems random! :-)
Then sometimes the CSS works and sometimes not. In the login form it has no styles, but only sometimes, because when I run the app, it has the styles. And when I do login too, but not when I logout or try to login again. So when the user is correctly logged in, it has styles again.
And when I tried to access "/controlpanel" with a user (with ROLE_USER) it allows access (and it should not), but when I do it with a user (Role_ADMIN) it works fine.
It happens when your static resources are filtered by Spring Security.
Try to ignore these resources at all:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/path/**");
}
define patterns to meet all your locations.
The problem is that your css files is not accessible by guest. So after logging in, you will be redirected back to it. Sometime css in login page works because of browser caching.
Try to change your configuration to
http
.authorizeRequests()
.antMatchers(
"/",
"/index/**",
"/register",
...).permitAll()
.antMatchers(
"/login",
"logout").permitAll()
.antMatchers( // You need to add all css file here
"/static/css/**",
"/css/custom.css",
"/css/bootstrap-3.3.7-dist/css/bootstrap.min.cs‌​‌​‌​s",
"/js/**",
"/images/**").permitAll()
.antMatchers(
"/forbidden",
"/edit-profile-about",
"/doeditprofileabout",
"/profile").hasRole("USER")
.antMatchers(
"/controlpanel",
"/forbidden",
"/edit-profile-about",
"/doeditprofileabout",
"/profile").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
...

Resources