SpringSecurity: Capturing RememberMe Success Event

I really like Spring Security because with very little configuration, you can add a bunch of powerful features to your application. Form based logins, auto-logins based upon remember me cookies, password hashing, session management, powerful access control to name a few. For basic purposes, you don’t even need to know how these things actually work because Spring Security hides all of these complexities behind a few simple XML configuration tags.

However moving towards more advanced operations could become a daunting task. I needed to add some logs in database each time user would auto-login using Remember Me cookie. This seemingly simple task actually took me countless hours, and drove me to explore deeper down in the framework. Eventually I had to override most of the default configurations with my custom implementations. Here I will try to share them as simple as possible.

Spring Security actually has a chain of filters that perform different operations each time an HTTP request reaches the application. One of them is RememberMeAuthenticationFilter. RememberMeAuthenticationFilter has a method onSuccessfulAuthentication which is invoked if a user is successfully auto-logged in using a remember me cookie. So solution to our problem is to extend RememberMeAuthenticationFilter and override onSuccessfulAuthentication.

public class MyRememberMeAuthenticationFilter extends
		RememberMeAuthenticationFilter {
	protected void onSuccessfulAuthentication(HttpServletRequest request,
			HttpServletResponse response, Authentication authResult) {
		// TODO: User has been auto-logged using a remember me cookie, do your stuff here

Simple as cake, no?

Don’t be deceived, you haven’t yet told Spring Security about your new filter. This is the point where complexity begins. Here is what you need to do now:

<!-- Yes, auto-config needs to switch off, otherwise you will get loads of errors. -->
<http auto-config="false">
    <session-management session-fixation-protection="none"/>			
    <!-- Since we are using our custom implementation of UsernamePasswordAuthenticationFilter, we need to make sure that we don't use <form-login/> element. -->	
    <custom-filter ref="myUsernamePasswordAuthenticationFilter" position="FORM_LOGIN_FILTER"/>
    <!-- Similarly we need to remove <remember-me/> element if we have any. -->
    <custom-filter ref="myRememberMeAuthenticationFilter" position="REMEMBER_ME_FILTER"/>
    <!-- And also <logout/> element if we have any. -->
    <custom-filter ref="myLogoutFilter" position="LOGOUT_FILTER"/>		

<!-- 'alias' is like bean id, with which you can refer following AuthenticationManager to other beans. -->
<authentication-manager alias="authenticationManager">
    <!-- AuthenticationProvider for form based authentication. 'user-service-ref' should refer to a bean, which implements UserDetailsService. -->
    <authentication-provider user-service-ref="userManager">
        <password-encoder hash="md5"><salt-source user-property="creationDate"/></password-encoder>
    <!-- This one is for remember me authentication. -->
    <authentication-provider ref="myRememberMeAuthenticationProvider"/>			

<!-- MyRememberMeServices extends TokenBasedRememberMeServices class. Nothing needs to be overridden here. In fact, you could directly use TokenBasedRememberMeServices or any other RememberMeServices here. -->
<beans:bean id="myRememberMeServices" class="com.emumba.sample.security.MyRememberMeServices">
    <!-- Game of Thrones rocks \m/ -->
    <beans:property name="key" value="HEAR_ME_ROAR"/>
    <beans:property name="userDetailsService" ref="userManager"/>
<beans:bean id="myRememberMeAuthenticationFilter" class="com.emumba.sample.security.MyRememberMeAuthenticationFilter">
    <beans:property name="rememberMeServices" ref="myRememberMeServices"/>
    <beans:property name="authenticationManager" ref="authenticationManager"/>

<!-- It is important to override default UsernamePasswordAuthenticationFilter, because we need to pass reference of myRememberServices to it, otherwise remember me cookie will never be created to client end. -->	
<beans:bean id="myUsernamePasswordAuthenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
    <beans:property name="rememberMeServices" ref="myRememberMeServices"/>
    <beans:property name="authenticationManager" ref="authenticationManager"/>
    <!-- Haven't added bean definitions of myAuthenticationSuccessHandler and myAuthenticationFailureHandler because they are out of scope of this post. Besides, I think they are too simple to implement. -->
    <beans:property name="authenticationSuccessHandler" ref="myAuthenticationSuccessHandler"/>
    <beans:property name="authenticationFailureHandler" ref="myAuthenticationFailureHandler"/>
    <beans:property name="filterProcessesUrl" value="/j_spring_security_check"/>
<!-- Overriding default LogoutFilter is also important because we need to pass reference of myRememberMeServices here as well, otherwise remember me cookie will not be cleared on logout. -->
<beans:bean id="myLogoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
    <!-- Again, definition of LogoutSuccessHandler is beyond scope of this article. -->
    <beans:constructor-arg ref="myLogoutSuccessHandler"/>
	    <beans:ref local="myRememberMeServices"/>
	    <beans:bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
<beans:bean id="myRememberMeAuthenticationProvider" class="com.emumba.sample.security.MyRememberMeAuthenticationProvider">
    <!-- key needs to be same as that provided to myRememberMeServices. -->
    <beans:property name="key" value="HEAR_ME_ROAR"/>

Comments are welcome.

Published by

Umar Ashfaq

Umar Ashfaq is a full-stack web developer. His core strength is building neat UIs with JavaScript on web but he also enjoys server side Java, NodeJS and Objective C. Follow him on twitter @umarashfaq87

14 thoughts on “SpringSecurity: Capturing RememberMe Success Event”

  1. Thanks for the good article. Can you please upload the full source code so that it is easier for us to debug and play around ?

    Thanks once again.

  2. Hello,

    I am implementing a simpler version of the “remember-me” feature, using Spring Security 2.
    I just added the and the checkBox in my jsf page. It all works pretty well, but when I close/reopen the browser and access the application’s webPage, the automatic login is done after the page is loaded and the authentication can be seen on refresh.
    Do you have any ideas?

    Thank you for your time.


      1. I don’t think it’s a JSF related issue, I don’t know how to give the RememberMeAuthenticationFilter a higher position than others

  3. Hi Umar,

    If I am using custom UsernamePasswordAuthenticationFilter , Is it mandatory to pass custom rememberMeServices ?

    As of now I was using Simple Hash-Based Token Approach for remember me cookies, after using Custom UsernamePasswordAuthenticationFilter cookies are not generated.

    Please guide


    1. Hi Noushad,

      It’s been quite a while since I worked on Spring Security, so I am bit out of context. Please ask the question on stackoverflow.com, they might help you better.

      1. Thanks Umar,

        anyway I found some clue in reference doc,
        Yes I need to pass custom rememberMeService. Its working now


  4. Hi Umar,
    We have done something similar. But my controllers are getting executed before my custom authentication filter gets executed. When I saw in debug mode I can see that in filter chain authentication filter is later in the order. Is there any way to force its way up.

Leave a Reply

Your email address will not be published. Required fields are marked *