This is an odd problem but I can reproduce it 100% of the time.
As per login automatically with Grails Spring Security the recommended way to programatically log in a user is with springSecurityService.reauthenticate(username), and this is used in the Spring-Security-UI plugin after registration confirmation.
But my application has this very odd behaviour where it doesn't seem to take effect immediately (I try to redirect to an authenticated page right after), but only if no previous login attempt has been made on my domain from that browser. Note I see this behaviour both in my code and in the spring-security-ui 'verify registration' which uses this method to supposedly log the user in.
To clarify, if I:
- Clear my JSESSIONID cookie for my.domain.com (my grails app runs here, but I can reproduce on localhost too)
- Hit a controller to enter a userid, which on submit should automatically log in the user and then redirect them to a page where they require to be logged in
- I end up not on the page, but rather kicked to login screen (which happens if you try and access that page without authentication). Note the jsessionid on the URL (it of course changes everytime), I don't put this there. https://my.domain.com/login/auth;jsessionid=B1C9A849E222476A9C9987923D439D13
- Note it doesn't appear to be a race condition where I redirect before the login takes effect, as if I try to go the authenticated page manually, it still fails. I'm just not logged in.
NOTE Hitting the controller in step 2, or any other controller actually does give me a JSESSIONID immediately, with a different value than ends up on the URL.
However if I:
- Make sure I have a JSESSIONID cookie from a previous login attempt, successful or not. Ensure I am logged out.
- Repeat step 2 from above (for any user, not the one that was in the first attempt)
- Everything works as expected! I'm successfully logged in and on the page that requires authentication. And it will continue to work for any future attempts until I clear that cookie again.
I'm quite baffled. Somehow I'm getting conflicted JSESSIONID values. Do I need to do something else after I call springSecurityService.reauthenticate(username) but before I call redirect(...securepage...). Note I do use channel security, which bounces me between http and https throughout the redirects - but I'm not sure how this relates to the odd behaviour of working only if there has been one previous authentication attempt.
Note normal logins via the login screen with username and password work the first time with clean cookies.