After a new user submits a 'New account' form, I want to manually log that user in so they don't have to login on the subsequent page.
The normal form login page going through the spring security interceptor works just fine.
In the new-account-form controller I am creating a UsernamePasswordAuthenticationToken and setting it in the SecurityContext manually:
SecurityContextHolder.getContext().setAuthentication(authentication);
On that same page I later check that the user is logged in with:
SecurityContextHolder.getContext().getAuthentication().getAuthorities();
This returns the authorities I set earlier in the authentication. All is well.
But when this same code is called on the very next page I load, the authentication token is just UserAnonymous.
I'm not clear why it did not keep the authentication I set on the previous request. Any thoughts?
- Could it have to do with session ID's not being set up correctly?
- Is there something that is possibly overwriting my authentication somehow?
- Perhaps I just need another step to save the authentication?
- Or is there something I need to do to declare the authentication across the whole session rather than a single request somehow?
Just looking for some thoughts that might help me see what's happening here.
Turn on debug logging to get a better picture of what is going on.
You can tell if the session cookies are being set by using a browser-side debugger to look at the headers returned in HTTP responses. (There are other ways too.)
One possibility is that SpringSecurity is setting secure session cookies, and your next page requested has an "http" URL instead of an "https" URL. (The browser won't send a secure cookie for an "http" URL.)
Ultimately figured out the root of the problem.
When I create the security context manually no session object is created. Only when the request finishes processing does the Spring Security mechanism realize that the session object is null (when it tries to store the security context to the session after the request has been processed).
At the end of the request Spring Security creates a new session object and session ID. However this new session ID never makes it to the browser because it occurs at the end of the request, after the response to the browser has been made. This causes the new session ID (and hence the Security context containing my manually logged on user) to be lost when the next request contains the previous session ID.
I couldn't find any other full solutions so I thought I would post mine. This may be a bit of a hack, but it resolved the issue to the above problem:
I was trying to test an extjs application and after sucessfully setting a testingAuthenticationToken this suddenly stopped working with no obvious cause.
I couldn't get the above answers to work so my solution was to skip out this bit of spring in the test environment. I introduced a seam around spring like this:
User is a custom type here.
I'm then wrapping it in a class which just has an option for the test code to switch spring out.
The test version just looks like this:
In the calling code I'm still using a proper user loaded from the database:
Obviously this wont be suitable if you actually need to use the security but I'm running with a no-security setup for the testing deployment. I thought someone else might run into a similar situation. This is a pattern I've used for mocking out static dependencies before. The other alternative is you can maintain the staticness of the wrapper class but I prefer this one as the dependencies of the code are more explicit since you have to pass CurrentUserAccessor into classes where it is required.
I had the same problem as you a while back. I can't remember the details but the following code got things working for me. This code is used within a Spring Webflow flow, hence the RequestContext and ExternalContext classes. But the part that is most relevant to you is the doAutoLogin method.
The new filtering feature in Servlet 2.4 basically alleviates the restriction that filters can only operate in the request flow before and after the actual request processing by the application server. Instead, Servlet 2.4 filters can now interact with the request dispatcher at every dispatch point. This means that when a Web resource forwards a request to another resource (for instance, a servlet forwarding the request to a JSP page in the same application), a filter can be operating before the request is handled by the targeted resource. It also means that should a Web resource include the output or function from other Web resources (for instance, a JSP page including the output from multiple other JSP pages), Servlet 2.4 filters can work before and after each of the included resources. .
To turn on that feature you need:
web.xml
RegistrationController