I have a form that allows a user to either login or register.
When the user lands on the page containing the form, the request is saved in a RequestCache object (I'm using Spring Security).
In the case that the user decides to register, I want to mimic the behavior of the Spring Security onAuthenticationSuccess code, where the user is redirected to whatever page they were trying to get to before logging in (or, in my case, before registering).
To accomplish that, I added the following code to the RegistrationController:
authenticationSuccessHandler.onAuthenticationSuccess(request, response, springSecurityService.authentication)
My question is, is this a reasonable approach to handle the on registration success use case? Am I doing enough?
Best way would be to keep a link to the original requested URL in a hidden formitem on the registration page and redirect after registration. Try to keep the security layer as simple and close to the original intend as possible.
Related
My question is about the MVC Antiforgery system (described here).
Consider a simple app which posts todos to /Todo/Create. The corresponding action method has the ValidateAntiForgeryToken attribute. Consider the following client workflow:
User A logs on and goes to the page to create a todo, but doesn't do it yet.
User B (physically on the same computer) opens a new tab in the same browser, logs out of User A's account, logs in as User B. The browser then gets User B's validation cookie.
Some time later, User A switches back to their original tab and hits 'create' on the todo they were making.
In this scenario, the Antiforgery verification will not pass because the form token was meant for User A, while the validation cookie is for User B.
I'm sure there are valid security reasons for this behavior (e.g. a script on another site that manages to login as malicious user so that the 'todo' data is posted to their account instead), but it doesn't stop the above scenario happening for my legitimate users sometimes.
My questions are:
Is there a 'best practices' way to handle this scenario? Is it usually just a case of showing a custom error, telling them to reload the page and/or login again etc?
Is there any way to know when the out-of-the-box MVC Antiforgery system runs into this error? It seems to only ever throw the same kind of Exception (HttpAntiForgeryException). Would I need to revert to using/modifying their source?
I see two ways of handling it:
Use Javascript callback to the server before hitting a button to detect if the user is still logged in. If not - display him a message. It should be relatively easy to do this. But it requires one additional call, and little bit more time to execute your request.
One solution to avoid callbacks could be using html 5 localStorage (and you can support that on other browsers using modernizr, for example). It is shared between tabs. But I'm not sure if this approach is good. Additional research required.
Catch HttpAntiForgeryException on the server, check if the user is logged in. If the user is not logged in, display him a message.
Usually approach (1) is used. On banking websites they detect with JavaScript when you logged out in other browser tab.
I want to allow a new login to 'kick' a prior login session by the same account, in ASP.NET MVC.
It seems pretty clear that I'll give each browser a cooking representing the session ID. I'll track the currently active session ID in a server-side cache. If an already-active user attempts to log in, I'll verify the business logic (username, password, has been at least 15 minutes since last activity), and then update the active session ID cached at the server.
Now my issue is, a browser is holding an invalid session ID. What is the best point for me to inject a rejection or redirect to sign-in for this scenario?
I could modify the AuthorizeAttribute, but it seems like there should be a cleaner place to do this that won't require me to search and replace all my Authorize attributes, for example via a Global.asax event, or a controller event (I've already extended Controller in my project).
For example, if PreAuthorize existed, I would write some code there to test the request's cookies for a valid user/session ID pair, and if it didn't exist, I could simply remove the authentication cookie from the request, which would result in a standard unauthorized redirection.
So after a bit of research, it seems that a custom AuthorizeAttribute would typically be the correct approach. However, in my case, since I already had a custom role provider implemented, it was just a line of code to do it there. This also benefited me because I only wanted session concurrency for a single role. A side effect is that any use of web.config to control access to static files by role is also in-effect for session concurrency.
We have some shopping cart pages which work with both guest and user paths. We want to allow a user to login at any time during the process but don't really want to create yet another login page. I'd prefer that we can simply redirect the user to the existing login and tell Spring Security what URL to come back to.
I know this happens automatically when sessions timeout and/or protected pages are requested without a session, but is there a way I can give the URL to Spring Security myself?
If you just need a simple return-to URL to retrieve the cart, then you are probably best to implement that yourself in an AuthenticationSuccessHandler. You can look at the source for SimpleUrlAuthenticationSuccessHandler and its parent for inspiration.
The default login mechanism uses the RequestCache and a SavedRequest, but that is intended to actually replay a request which would not otherwise be authorised. That's probably overkill in your case.
I'm using PrettyFaces 3.3.3. I have a requirement that if a user tries to view a page, but is not logged in, they are sent to the login page, and then redirected to the original page they wanted to view. Just wondering what would be the best approach for this.
You probably want a security framework here. The basic idea is that you'd want to intercept the requested URL in your security filter, save it into the user's session, then once authentication is complete (e.g. user has submitted the form with their credentials, or whatever mechanism you're using) you retrieve the saved URL from the user's session and perform a 302 Redirect to it.
This is not something PrettyFaces will help you with directly, except that you can use it to capture the URL more easily using PrettyContext.getCurrentInstance(request).getRequestURL();
There is an article about this here: http://ocpsoft.org/java/jsf-java/spring-security-what-happens-after-you-log-in/
Using OCPsoft Rewrite (core of PrettyFaces 4) you can do this programatically as well, and even do the authentication directly in your security rules or annotation config: https://github.com/ocpsoft/prettyfaces/blob/master/annotations/src/test/java/org/ocpsoft/prettyfaces/annotation/jaas/JaasRolesBean.java
This is an upcoming feature but is not yet complete - we would love feedback.
Here is the issue:
We have to implement two-step login process. First step - user enters name/password and is being authenticated. Second step - user may be presented with secondary select screen where he chooses an option via simple click. When this is done user is finally authorized for certain set of actions. This concludes authentication/authorization process for current user session.
We do use Spring Security in its standard form: first login screen is handled by default Spring Security stack and as soon as user is in - Spring considers the login process done.
The secondary selection screen is completely outside of Spring Security and all we do upon user selection is set the properly configured object back into security context. This works for current session as expected.
We do have remember-me functionality as well which is implemented via checkbox named _spring_security_remember_me in the first login screen and also an overridden UserDetailsService bean.
The remember-me works fine for as long as there is no secondary select screen option. Since the secondary screen has nothing to do with Spring Security, the remember-me mechanism would not be activated for secondary option and all it is capable of is to remember only the first login step. This results with having to ask remembered user the option and we are tasked to avoid this.
Having both login form and secondary selection on the same page is not an option.
We could use additional cookie if the secondary selection is required and based on that cookie "silently" pass the needed parameter when authenticating. But this would mean that we have to do bunch of manual stuff which Spring Security "ought" to offer, also this puts some security logic and tokens outside of Spring managed security and remember-me functionality.
So here is the question to security gurus: how to "force" remember-me functionality to accept the secondary presented option? If it was possible for Remember-Me filter to "inspect" the passed URL and identify that remember-me option is chosen, we could add this parameter. But this does not sound like it is possible.
Is it possible/feasible to use yet another login form on secondary screen and "silently" pass just needed additional parameters? I know we won't include the user name/password in this case, at least not in clear form. The option sounds like it can be done, but I am still believing that there might be an easier way to just force the Remember-Me to do what it does. Or is there?
Thanks,
Nikolay
You could store the last selected option for each user in the database. Then you implement an AuthenticationSuccessHandler that reads the stored option from the database and sets it in the security context. If the option is not found, the user is redirected to the selection screen.
This should work regardless of the authentication type (form, basic or remember-be) only if you are using Spring Security 3.1 or later, as the possibility to register an AuthenticationSuccessHandler has been introduced in that version. There's a discussion on this topic in the Spring Forums.