5

I'm trying to implement a "remember me" functionality in my website using Spring. The cookie and entry in the persistent_logins table are getting created correctly. Additionally, I can see that the correct user is being restored as the username is displayed at the top of the page.

However, once I try to access any information for this user when they return after they were "remembered", I get a NullPointerException. It looks as though the user isn't being set in the session again.

My applicationContext-security.xml contains the following:

<remember-me data-source-ref="dataSource" user-service-ref="userService"/>

...

<authentication-provider user-service-ref="userService" />

<jdbc-user-service id="userService" data-source-ref="dataSource" 
role-prefix="ROLE_"
users-by-username-query="select email as username, password, 1 as ENABLED from user where email=?" 
authorities-by-username-query="select user.id as id, upper(role.name) as authority from user, role, users_roles where users_roles.user_fk=id and users_roles.role_fk=role.name and user.email=?"/>

I thought it may have had something to do with users-by-username query but surely login wouldn't work correctly if this query was incorrect?

Any help on this would be greatly appreciated.

Thanks, gearoid.

Gerard
  • 4,818
  • 5
  • 51
  • 80
  • 4
    Remember that you will might have TWO key parameters in your security config. On for the RememberMeAuthenticationProvider and one for the TokenBasedRememberMeServices. Make sure they are equal. – kboom Feb 15 '14 at 10:43
  • @kboom Thank you for mentioning that there are TWO keys! – Rüdiger Schulz Jul 28 '17 at 20:29

1 Answers1

5

Can you please include the entire stack trace of the exception? I suspect that because you have not set the key attribute on the remember-me configuration that you specified above that the token is not being set on the SecurityContextHolder.

To see details of how Remember Me works you should take a look at the source for the RememberMeAuthenticationFilter. You can find that source here (directly):

http://grepcode.com/file/repo1.maven.org/maven2/org.springframework.security/spring-security-web/3.0.2.RELEASE/org/springframework/security/web/authentication/rememberme/RememberMeAuthenticationFilter.java

RememberMeAuthenticationFilter is going to call in the RememberMeAuthenticationProvider as a result of:

rememberMeAuth = authenticationManager.authenticate(rememberMeAuth);

Inside the authenticate method you can see that it will throw an exception if you do not specify a key:

 if (this.key.hashCode() != ((RememberMeAuthenticationToken) authentication).getKeyHash()) {
            throw new BadCredentialsException(messages.getMessage("RememberMeAuthenticationProvider.incorrectKey",
                    "The presented RememberMeAuthenticationToken does not contain the expected key"));
        }

The key can literally be any string "your-company-name-{GUID}" or something like that. So then your remember-me would look more like this:

<remember-me key="your-company-name-rmkey-aWeFFTgxcv9u1XlkswUUiPolizxcwsqUmml" token-validity-seconds="3600" data-source-ref="dataSource"/>

Setting the token-validity is a really good idea which you should do.

Grant

Grant Cermak
  • 1,808
  • 1
  • 19
  • 23