I want to display a custom error page on authentication denial (I am using a pre-authenticated secnario) and also access denial from Spring Security 3.0.X
Understand we can use the following to perform this:
<beans:bean id="authenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/error.jsp"/>
</beans:bean>
<beans:bean id="accessDeniedHandler" class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
<beans:property name="errorPage" value="/error.jsp"/>
</beans:bean>
but doing this results in a redirect and not a forward to the error page. Anyway to perform forward to an error page (so that we can set some attributes in the request)
Thanks
In my security-context.xml, for authentication failure I do like this (pay attention to the authentication-failure-url attribute):
<security:form-login login-page="/auth/login"
authentication-failure-url="/auth/login?error=true"
default-target-url="/mvc/home"
always-use-default-target="true" />
And for access denied I use this:
<security:access-denied-handler error-page="/auth/access-denied"/>
Both tags inside <security:http use-expressions="true">. For me works like a charm, I don't know why you are trying to configure it in the way you are doing when Spring provides such nice tags easy to use.
I don't know if it answers your question, I hope it helps.
EDIT:
Using the configuration provided above, means that you are using the default authentication failure handler (SimpleUrlAuthenticationFailureHandler) at the background. You can change the default behavior (which as default performs a redirect when a failed authentication is produced) by changing the attribute forwardToDestination value. This is what SimpleUrlAuthenticationFailureHandler does:
/**
* Performs the redirect or forward to the {#code defaultFailureUrl} if set, otherwise returns a 401 error code.
* <p>
* If redirecting or forwarding, {#code saveException} will be called to cache the exception for use in
* the target view.
*/
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
if (defaultFailureUrl == null) {
logger.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage());
} else {
saveException(request, exception);
if (forwardToDestination) {
logger.debug("Forwarding to " + defaultFailureUrl);
request.getRequestDispatcher(defaultFailureUrl).forward(request, response);
} else {
logger.debug("Redirecting to " + defaultFailureUrl);
redirectStrategy.sendRedirect(request, response, defaultFailureUrl);
}
}
}
So I guess that I you declare your SimpleUrlAuthenticationFailureHandler in your security-context.xml and set the mentioned property value using the setUseForward(boolean forwardToDestination) method it should work. Could be something like:
<bean id="simpleUrlAuthenticationFailureHandler" class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="useForward" value="true">
</bean>
And then:
<security:form-login login-page="/auth/login"
authentication-failure-handler-ref="simpleUrlAuthenticationFailureHandler"
default-target-url="/mvc/home"
always-use-default-target="true" />
Good luck.
Related
I already try the whole day, to get my custom authentication failure handler to work with Spring 3.1.3.
I think it is properly configured
<http use-expressions="true" disable-url-rewriting="true">
<intercept-url pattern="/rest/login" access="permitAll" />
<intercept-url pattern="/rest/**" access="isAuthenticated()" />
<intercept-url pattern="/index.html" access="permitAll" />
<intercept-url pattern="/js/**" access="permitAll" />
<intercept-url pattern="/**" access="denyAll" />
<form-login username-parameter="user" password-parameter="pass" login-page="/rest/login"
authentication-failure-handler-ref="authenticationFailureHandler" />
</http>
<beans:bean id="authenticationFailureHandler" class="LoginFailureHandler" />
My implementation is this
public class LoginFailureHandler implements AuthenticationFailureHandler {
private static final Logger log = LoggerFactory.getLogger(LoginFailureHandler.class);
public LoginFailureHandler() {
log.debug("I am");
}
#Autowired
private ObjectMapper customObjectMapper;
#Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
AuthenticationException exception) throws IOException, ServletException {
log.debug("invalid login");
User user = new User();
user.setUsername("invalid");
try (OutputStream out = response.getOutputStream()) {
customObjectMapper.writeValue(out, user);
}
}
}
In the console I see
2013-04-11 14:52:29,478 DEBUG LoginFailureHandler - I am
So it is loaded.
With wrong username or passwort, when a BadCredentialsException is thrown, I don't see invalid login.
The Method onAuthenticationFailure is never invoked.
Instead the service redirects the browser onto /rest/login again and again...
Edit
2013-04-11 15:47:26,411 DEBUG de.pentos.spring.LoginController - Incomming login chuck.norris, norris
2013-04-11 15:47:26,412 DEBUG o.s.s.a.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider
2013-04-11 15:47:26,415 DEBUG o.s.s.a.d.DaoAuthenticationProvider - Authentication failed: password does not match stored value
2013-04-11 15:47:26,416 DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver - Resolving exception from handler [public de.pentos.spring.User de.pentos.spring.LoginController.login(de.pentos.spring.User)]: org.springframework.security.authentication.BadCredentialsException: Bad credentials
2013-04-11 15:47:26,419 DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver - Resolving exception from handler [public de.pentos.spring.User de.pentos.spring.LoginController.login(de.pentos.spring.User)]: org.springframework.security.authentication.BadCredentialsException: Bad credentials
2013-04-11 15:47:26,419 DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver - Resolving exception from handler [public de.pentos.spring.User de.pentos.spring.LoginController.login(de.pentos.spring.User)]: org.springframework.security.authentication.BadCredentialsException: Bad credentials
2013-04-11 15:47:26,426 DEBUG o.s.web.servlet.DispatcherServlet - Could not complete request
org.springframework.security.authentication.BadCredentialsException: Bad credentials
This happens in DEBUG Mode
Where is my mistake?
Judged from the logs you attached I think you've made a mistake in implementing the login process. I cannot be absolutely sure, but I guess you call ProviderManager.authenticate() in your LoginController. The method throws a BadCredentialsException that causes Spring MVC's exception handling mechanism to kick in, which of course has no knowledge about the AuthenticationFailureHandler configured for Spring Security.
From the login controller you should normally just serve a simple login form with action="j_spring_security_check" method="post". When the user submits that form, the configured security filter (namely UsernamePasswordAuthenticationFilter) intercepts that request and handles authentication. You don't have to implement that logic yourself in a controller method.
Reply to your comment:
You do use ProviderManager (it's the implementation of the autowired AuthenticationManager interface). The mistake you make is that you try to rewrite the logic already implemented and thoroughly tested in auth filters. This is bad in itself, but even that is done in a wrong way. You select just a few lines from a complex logic, and among other things you forget e.g. invoking the session strategy (to prevent session fixation attacks, and handling concurrent sessions). The original implementation invokes the AuthenticationFailureHandler
as well, which you also forgot in your method, this is the very reason of the problem your original question is about.
So you end up with an untested, brittle solution instead of nicely integrating with the framework to leverage its roboustness and full capacity. As I said, the config you posted in your answer is a definite improvement, because it uses the framework provided filter for authentication. Keep that config and remove LoginController.login(), it won't be called anyway by requests sent to /rest/login.
A more fundamental question is if it's really a good solution to use sessions and form-based login mechanism if you implement RESTful services. (On form-based login I mean that the client sends its credentials once in whatever format, and then gets authenticated by a stateful session on subsequent requests.) With REST services it's more prevalent to keep everything stateless, and re-authenticate each new request by information carried by http headers.
It's a problem with the order in the security-app-context.xml.
If I first define all my beans and then all the rest it works.
I tried a lot, so don't wonder, that it now looks a little different then in the question
<beans:bean id="authenticationProcessingFilterEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<beans:property name="loginFormUrl" value="/rest/login" />
</beans:bean>
<beans:bean id="authenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<beans:property name="authenticationManager" ref="authenticationManager" />
<beans:property name="filterProcessesUrl" value="/rest/login" />
<beans:property name="authenticationSuccessHandler" ref="authenticationSuccessHandler" />
<beans:property name="authenticationFailureHandler" ref="authenticationFailureHandler" />
</beans:bean>
<beans:bean id="authenticationSuccessHandler" class="de.pentos.spring.LoginSuccessHandler" />
<beans:bean id="authenticationFailureHandler" class="de.pentos.spring.LoginFailureHandler" />
<http use-expressions="true" disable-url-rewriting="true" entry-point-ref="authenticationProcessingFilterEntryPoint"
create-session="ifRequired">
<intercept-url pattern="/rest/login" access="permitAll" />
<intercept-url pattern="/rest/**" access="isAuthenticated()" />
<intercept-url pattern="/index.html" access="permitAll" />
<intercept-url pattern="/js/**" access="permitAll" />
<intercept-url pattern="/**" access="denyAll" />
<custom-filter position="FORM_LOGIN_FILTER" ref="authenticationFilter" />
</http>
<authentication-manager alias="authenticationManager">
<authentication-provider>
<user-service>
<user name="chuck.norris" password="cnorris" authorities="ROLE_ADMIN" />
<user name="user" password="user" authorities="ROLE_USER" />
</user-service>
</authentication-provider>
</authentication-manager>
Does not look bad to me. Did you try to use the debug mode of your IDE ?
Did you see things like this in your logs :
Authentication request failed: ...
Updated SecurityContextHolder to contain null Authentication
Delegating to authentication failure handler ...
The AuthenticationFailureHandler will be called automatically, only if the authentication is done in one of the authentication filter : UsernamePasswordAuthenticationFilter normally in your case.
(Looking at your requirements), You don't need a custom AuthenticationFailureHandler as the with default SimpleUrlAuthenticationFailureHandler of Spring and properly implementing AuthenticationProvider should serve the purpose.
<form-login login-page="/login" login-processing-url="/do/login" authentication- failure-url ="/login?authfailed=true" authentication-success-handler-ref ="customAuthenticationSuccessHandler"/>
If you have handled the Exceptions well in Authentication Provider:
Sample Logic:
String loginUsername = (String) authentication.getPrincipal();
if (loginUsername == null)
throw new UsernameNotFoundException("User not found");
String loginPassword = (String) authentication.getCredentials();
User user = getUserByUsername(loginUsername);
UserPassword password = getPassword(user.getId());
if (!password.matches(loginPassword)) {
throw new BadCredentialsException("Invalid password.");
}
If we want the exceptions thrown to be reflected at the client interface, add the following scriplet on the JSP responding to authentication-failure-url="/login?authfailed=true"
<%
Exception error = (Exception) request.getSession().getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
if (error != null)
out.write(error.getMessage());
%>
How I get remember me value when login failed and reopen the login page?
Can i get the value of _spring_security_remember_me on controller?
I just need to keep the value of the checkbox when login error occurs!
You can try the following solution:
1. insert custom filter into spring security filter chain
2. inside this filter obtain http session and store there the value of request parameter
As we change the login form (adding another parameter) we need to customize spring representation of login form and spring login processing filter.
Here is the configuration:
<authentication-manager alias="authenticationManager"/>
<beans:bean id="myFilter" class="test.MyAuthenticationProcessingFilter">
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />
<beans:property name="defaultTargetUrl" value="/initialize.action"/>
<beans:property name="authenticationFailureUrl" value="/login_failed.action"/>
<beans:property name="authenticationManager" ref="authenticationManager"/>
<beans:property name="alwaysUseDefaultTargetUrl" value="true"/>
<beans:property name="filterProcessesUrl" value="/perform_login"/>
</beans:bean>
<beans:bean id="entryPoint" class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
<beans:property name="loginFormUrl" value="/login.action"/>
</beans:bean>
MyAuthenticationProcessingFilter extends spring's org.springframework.security.ui.webapp.AuthenticationProcessingFilter, wraps attemptAuthentication method obtaining request parameter and storing it inside http session. This class is written just to show the idea, for better practice browse AuthenticationProcessingFilter code for username and password parameters.
public class MyAuthenticationProcessingFilter extends AuthenticationProcessingFilter {
#Override
public Authentication attemptAuthentication(HttpServletRequest request)
throws AuthenticationException {
String param = request.getParameter("_spring_security_remember_me");
HttpSession session = request.getSession();
if (session != null || getAllowSessionCreation()) {
session.setAttribute("_spring_security_remember_me", param);
}
return super.attemptAuthentication(request);
}
}
You may notice that "myFilter" and "entryPoint" beans together define parameters that are otherwise defined by element inside . You use when you want the default behavior. But in our case we use custom beans, so you should remove element completely.
Now we need to tell use our beans. "myFilter" bean is passed to spring chain by using element inside bean definition:
<beans:bean id="myFilter" class="test.MyAuthenticationProcessingFilter">
<custom-filter position="AUTHENTICATION_PROCESSING_FILTER" />
...
</beans:bean>
"entryPoint" is passed to using attribute:
<http entry-point-ref="entryPoint">
...
<!-- no form-login here -->
</http>
your question is a bit unclear, or you have a wrong image of how remember me with spring security works. Read the Spring Security Reference Chapter 11 "Remember-Me Authentication"
Briefly it works this way:
If a user log in successfully with his user name and password and have enabled the remember me checkbox, Spring Security will create a cookie that verify the user and "send" it to the user
Not logged in User request a secured page (Authentication required) spring will check if he as a valid cookie.
If he has such a cookie spring security will "login" him "automatically" and show him the page
If he has no valid cookie spring will forward him to the login page (see above)
I hope this helps you.
I want to redirect to home page if session get invalid.
My spring-servlet.xml is
<mvc:interceptors>
<bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor" />
<mvc:interceptor>
<mvc:mapping path="/**" />
<bean class="com.xxx.MyInterceptor" />
</mvc:interceptor>
</mvc:interceptors>
Interceptor :
public boolean preHandle(HttpServletRequest request,
HttpServletResponse response, Object handler) throws Exception {
if ((null == request.getSession(false))
|| (null == request.getSession(false).getAttribute(
"user"))) {
System.out.println("user logged out...");
RequestDispatcher rd = request.getRequestDispatcher("loginForm.htm");
rd.forward(request, response);
return false;
}
return super.preHandle(request, response, handler);
}
But its not working...
Whenever application get started, the message get printed multiple times and at the end it gives stack overflow..
Thank You.
It seems like the problem is in your mapping path. Since its mapped with /** your loginForm.htm is also getting intercepted. You have two solutions available to resolve this problem.
Either define <mvc:resources location="/resources/" mapping="/resources/**" /> so that the *.htm requests will not be intercepted. Replace the location and mapping values as per your path where the *.htm files are.
And another option is to change your mapping in intercepter with something like /*.do or something else.
Hope this helps you. Cheers.
I want to redirect users to the login page when a session timeout occurs. This works out-of-the-box with spring security, but only on non-ajax calls.
On an ajax-call you have to react on the session timeout by yourself. Therefore I have created
my own filter(filter implemented like in this question) who checks if a session is timed out. The filter is registered via custom-filter tag in spring security config.
<http use-expressions="true">
<custom-filter ref="customTimeoutHandler" after="LAST"/>
</http>
The problem is, that the session timeout is not recognized by the filter. If I check for request.isRequestedSessionIdValid() it returns true even if the session is timed out. When I enter a new secured URL manually, the standard spring security filter recognizes the timeout correctly and does a redirect to the login page.
What could be wrong here? How recognizes spring security the session timeout?
UPDATE
It seems, that the session management filter of spring security replaces the timed-out session with a new anonymous one. Therefore everytime I check for session timeout it returns true, because the new anonymous session is, of course, not timed-out.
You can check the SecurityContext.
Grab the Authentication object and check the authorities looking for an ANONYMOUS one. Something like:
SecurityContext sc = SecurityContextHolder.getContext();
Authentication a = sc.getAuthentication();
if(!a.isAuthenticated() || a.getAuthorities().contains(new GrantedAuthorityImpl("ROLE_ANONYMOUS"))) {
//user not authenticated or ANONYMOUS
} else {
//user authenticated
}
This solution works like a charm for me.
The basic concept is to point to a servlet instead of the login page. The servlet then determines if the request was a ajax request and if that is true, it returns the redirect to the login page as xml fragment. The browser can interpret that fragment and redirects to the login page.
I am developing enterprise application including gwt/gwtp and spring security .
I add some issue with session time out , casue the SimpleRedirectInvalidSessionStrategy which used by default is executing response.sendRedirect() , the html page response I wanted to redirect is swallow by gwt com.google.gwt.user.client.rpc.InvocationException as the exception message . and no actully redirect is taking place .
for solving this
1 . I define my cosutom session-manamgemt-filter
for doing this you need in your spring-security.xml configuration file set
<session-management session-fixation-protection="none"/> by this spring secuirty will not take it default session managment filter .
define your session managment filter
enter code here
{
<custom-filter position="SESSION_MANAGEMENT_FILTER" ref="mySessionManagmentFilter"/>
<beans:bean id="mySessionManagmentFilter"
class="org.springframework.security.web.session.SessionManagementFilter">
<beans:constructor-arg index="0" ref="mySessionSecurityContextRepository"/>
<beans:constructor-arg index="1" ref="mySessionAutenticationStrategy"/>
<beans:property name="invalidSessionStrategy">
<beans:ref local="myInvalidSessionStrategy"/>
</beans:property>
</beans:bean>
<beans:bean id="mySessionSecurityContextRepository"
class='org.springframework.security.web.context.HttpSessionSecurityContextRepository'>
<beans:property name='allowSessionCreation' value='false'/>
</beans:bean>
<beans:bean id="mySessionAutenticationStrategy"
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlStrategy">
<beans:constructor-arg name="sessionRegistry" ref="sessionRegistry"/>
<beans:property name="maximumSessions" value="1"/>
<beans:property name="exceptionIfMaximumExceeded" value="false"/>
<beans:property name="alwaysCreateSession" value="true"/>
</beans:bean>
<beans:bean id="myInvalidSessionStrategy"
class="com.my.project.MyInvalidSessionStrategy">
<beans:constructor-arg value="/login.jsp?timeout=1"/>
</beans:bean>
}
here custom - MyInvalidSessionStrategy
{
public class MyInvalidSessionStrategy implements InvalidSessionStrategy {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final String destinationUrl;
public OperationalInvalidSessionStrategy(String invalidSessionUrl) {
this.destinationUrl = invalidSessionUrl;
}
#Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String exMsg =session timeout ! , need to redirect to login page
logger.warn(exMsg);
throw new TimeOutException(exMsg);
}
}
}
so when time out taking place the new implementation is throwing an exception ..
the exception can be truck on gwt callback onFailure method
check the type of the exception and on onFailure method redirect the user to login page .
with Window.Location.replace(GWT.getHostPageBaseURL() + "/login.jsp")
Probably the answer is simple: How can I manually logout the currently logged in user in spring security?
Is it sufficient to call:
SecurityContextHolder.getContext().getAuthentication().setAuthenticated(false);
?
It's hard for me to say for sure if your code is enough. However standard Spring-security's implementation of logging out is different. If you took a look at SecurityContextLogoutHandler you would see they do:
SecurityContextHolder.clearContext();
Moreover they optionally invalidate the HttpSession:
if (invalidateHttpSession) {
HttpSession session = request.getSession(false);
if (session != null) {
session.invalidate();
}
}
You may find more information in some other question about logging out in Spring Security and by looking at the source code of org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler.
In Servlet 3.0 container Spring logout functionality is integrated with servlet and you just invoke logout() on your HttpServletRequest. Still need to write valid response content.
According to documentation (Spring 3.2):
The HttpServletRequest.logout() method can be used to log the current user out.
Typically this means that the SecurityContextHolder will be cleared
out, the HttpSession will be invalidated, any "Remember Me"
authentication will be cleaned up, etc.
I use the same code in LogoutFilter, reusing the LogoutHandlers as following:
public static void myLogoff(HttpServletRequest request, HttpServletResponse response) {
CookieClearingLogoutHandler cookieClearingLogoutHandler = new CookieClearingLogoutHandler(AbstractRememberMeServices.SPRING_SECURITY_REMEMBER_ME_COOKIE_KEY);
SecurityContextLogoutHandler securityContextLogoutHandler = new SecurityContextLogoutHandler();
cookieClearingLogoutHandler.logout(request, response, null);
securityContextLogoutHandler.logout(request, response, null);
}
You can also use SessionRegistry as:
sessionRegistry.getSessionInformation(sessionId).expireNow();
If you want to force logout in all sessions of a user then use getAllSessions method and call expireNow of each session information.
Edit
This requires ConcurrentSessionFilter (or any other filter in the chain), that checks SessionInformation and calls all logout handlers and then do redirect.
To log out a user in a web application you can also redirect him to the logout page. The LogoutFilter is then doing all the work for you.
The url of the logout page is set in the security configuration:
<sec:http ...>
...
<sec:logout logout-url="/logout" logout-success-url="/login?logout_successful=1" />
...
</sec:http>
new SecurityContextLogoutHandler().logout(request, null, null);
Right Oledzki, I am using the following for example inside my controller to logout and redirect the user to the login page in spring security 4.2.3
SecurityContextHolder.clearContext();
if(session != null)
session.invalidate();
return "redirect:/login";
Simply do like this (the ones commented by "concern you") :
Authentication auth = SecurityContextHolder.getContext().getAuthentication(); // concern you
User currUser = userService.getUserById(auth.getName()); // some of DAO or Service...
SecurityContextLogoutHandler ctxLogOut = new SecurityContextLogoutHandler(); // concern you
if( currUser == null ){
ctxLogOut.logout(request, response, auth); // concern you
}
Recently we had to implement logout functionality using Spring-security 3.0.5. Although this question is already answered above, I will post the complete code which would definitely help novice user like me :)
Configuration in Spring-security.xml
<http auto-config="false" lowercase-comparisons="false" use-expressions="true">
<custom-filter position="LOGOUT_FILTER" ref="logoutFilter" />
</http>
<beans:bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
<beans:constructor-arg name="logoutSuccessHandler" ref="xxxLogoutSuccessHandler" />
<beans:constructor-arg name="handlers">
<beans:list>
<beans:ref bean="securityContextLogoutHandler"/>
<beans:ref bean="xxxLogoutHandler"/>
</beans:list>
</beans:constructor-arg>
<beans:property name="filterProcessesUrl" value="/logout"/>
</beans:bean>
<beans:bean id="XXXLogoutSuccessHandler" class="com.tms.dis.sso.XXXLogoutSuccessHandler"/>
<beans:bean id="securityContextLogoutHandler" class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">
<beans:property name="invalidateHttpSession" value="true"/>
</beans:bean>
<beans:bean id="XXXLogoutHandler" class="com.tms.dis.sso.XXXLogoutHandler"/>
Here i have created two custom classes
XXXLogoutHandler which will implement org.springframework.security.web.authentication.logout.LogoutHandler and will override the logout() method.
XXXLogoutSuccessHandler which will implement org.springframework.security.web.authentication.logout.LogoutSuccessHanlder and will override onLoguoutSuccess() method. Within the XXXLogoutSuccessHandler.onLogoutSuccess() method call the redirectStrategy.sendRedirect() method which logout the user to the particular targetURL.
org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler does the task of invalidating the user session.
Hope this would help and give the correct direction to the starter
Note: Intentionally have not posted code for custom implementation.
Very simple, to logout of spring security manually,
just make use of the Servlet request itself.
i.e. As below :
#PostMapping("/manualLogout")
public String customLogut(Model models, HttpServletRequest request) throws ServletException
{
request.logout();
return "redirect:/";
}
Thanks for the question.
In you controller >> signOut method do not return "/logout" but redirect to the /logout method in the spring security context: return "redirect:/logout";