Asp.Net MVC Antiforgery validation fails when non-null usernames differ...is that reasonable? - asp.net-mvc

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.

Related

Grails - Spring Security Core onAuthenticationSuccess

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.

What are the actions AccountController.SendCode and VerifyCode there for?

This question pertains to the Visual Studio generated code that you get when you open an ASP.NET MVC application in Visual Studio Community 2015 RC.
In this generated code, what is the purpose of the actions SendCode and VerifyCode on the AccountController?
I have read their code but the time investment it requires to read this code and look up the meaning of the functions called within these from the MSDN -- all of which I have done -- and then open their views to see what they do, and then look for references of where they're called -- is too much for the benefit. Microsoft left so many comments in this generated code elsewhere. They could have left a few comments explaining the workflow of these actions and told us where they're meant to be (and are currently) called from.
One big reason for confusion is: these actions aren't called or redirected to from anywhere else.
Anyway, my understanding is that they're there to ask a visitor who has just registered on the website with his email address, to verify his email address by requesting that he be sent a code.
But then in the source code for the SendCode action, there's this drop-down in the code that gets the registered two-factor authentication providers in the View (which I have only seen by reading the code. I haven't been able to run this action because it isn't called from anywhere and I don't know how to get to it with the right arguments).
This leads me to suspect that this has to do with two-factor authentication by email and/or phone.
But two-factor authentication by phone is already covered in the ManageController.AddPhone action and the ManagerController.EnableTwoFactorAuthentication, right?
It seems like one needs an old priest and a young priest to understand what's in the generated code.
Could someone please tell me what these two actions are for and where are they (supposed to be) called from? What's the entire workflow for these two actions?
I believe these methods are in place if you wish to implement signup validation logic. For example, a user signs up to your website and you require them to validate their information (usually email address) before approving their signup.
So the flow would be:
User signs up
System creates user but doesn't activate account yet
System sends email to user email with validation link (AccountController.SendCode())
User opens email
User clicks validation link which navigates to validation page on your website
Page validates user information (AccountController.CheckCode())
If validation is successful, account is activated
If validation is not successful, error message is displayed
I'm not sure if you've seen this post already but it outlines how you can implement something similar using SendGrid as your email provider.
the purpose of sendcode and verifycode is in case you want to leverage MFA (multi factor authentication). hence, after login, you would be redirected to send code where you decide whether to send a code via i.e. mobile or email and once the code is sent, you get to verify code to enter the code you requested to complete the process.

Two tier sign in with Devise (Amazon style)

Let's imagine I have following scenario
User receives an email that there is a new item waiting for her
Clicks on a link and is able to either confirm or reject item (details skipped)
Can then access a list of all her items
The trick is that I would like to allow all this happen without user signing in but then limit access to other parts of the website (like sending an item to another user)
How I see it is that:
when user clicks a link she is signed in but only on tier 1 - with access only to confirm/reject action and read only to index of items (that's when Devise session is created)
when user wants to access other part of the website the sign in page is presented
when user comes to the website just by typing in the url http://example.com and wants to access own account she is asked to sign in.
after sign in session is "promoted" to tier which allows full access
after some time of inactivity session is downgraded to tier 1 for security reasons
My inspiration comes from how Amazon works - you can access in read-only most parts of the account but before performing any destructible actions you need to sign in.
Does anyone have any experience with such approach or can share some blog posts, etc?
I didn's find anything on SO and Google mostly returned things about two-factor auth which is not the case here.
I also understand that there are security concerns with links in email.
I have implemented a very similar behavior few months ago. I don't have very interesting resources to show you but I can explain a bit how you could organize or think about the problem to solve.
Description
For the problem you state, it looks like once you have identified a user, you have two different states you can give him:
limited access (perform certain actions, read most of the resources, etc)
full access (allows them to do anything they would normally do).
Having stated that, what you need to do is figure out in which cases you will give a user each access state (for example):
signing in with email token -> limited access
password -> full access
authentication_token -> full access
omniauth -> full access
After that, you will need to save this information in the user session. This should be done anytime the user is authenticated, as you will know what strategy was used to authenticate the user.
To know if a user can or cannot perform an action you will need two things, know what the user can do, and the current "access state". Depending on those you will decide wether the user is allowed or not to perform a certain action.
Whenever a user can't perform an action and is logged in with limited access you should bring him to the flow for verifying his crendetials. This flow is pretty simple, almost like a sign in but just with the password. Once you verify his crendetials you can upgrade his authorization to a full access one.
Implementation details
I recommend you to create a Authorization model which will represent the "access states" that I mentioned. This model will have to be serialized in the session so you should be able to build it from a simple structure and serialize it again into that structure. The simplest the better (a boolean flag, an array or maybe a hash). For the case mentioned, it looks like a boolean would do the job.
Regarding implementation details, I recommend you implementing this with a Warden after_atuhentication callback.
You could implement this with CanCan by creating you own Ability that would be built with an Authorization instance and a User instance.
I think you're confusing authorization and authentication. Devise is an authentication solution, meaning it handles the "proof me you are who you say you are" part. Authorization is the "Ok, I know who you are, now let's see what can you do". Devise doesn't provide an authorization system beyond the simple "logged/not logged". If you need a more complex authorization system, use an authorization gem. CanCan is very popular.

When does the .NET FormAuthentication ticket get checked and how do I tap into this event?

We are attempting to integrate an ASP.NET MVC site with our client's SSO system using PingFederate. I would like to use the built in FormsAuthentication framework to do this. The way I've gone about it so far is:
Set up my Web.config so that my FormsAuthentication LoginURL goes to my site's "BeginAuthentication" action on a "Security" controller. From this action, I set up some session variables (what URL was being accessed, for example, since Ping won't send this info back to me), and then redirect to our client's login page on an external site (www.client.com/Login for example).
From here, the authentication takes place and a cookie is generated on the same domain as the one that our application is running on which contains the unique identifier of the authenticated user, I've set it up so that once this happens, the Ping server will redirect to my "EndAuthentication" action on my "Security" controller.
In this action, I call my membership class's "ValidateUser" method which takes this unique identifier from the cookie and loads in the user on our application that this ID refers to. I save that logged in user in our Session (Session["LoggedInAs"], for example) and expire the cookie that contains the id of the authenticated user that the SSO system provided for me.
All of this works well. The issue I'm wondering about is what happens after our user has already authenticated and manually goes back to our client's login page (www.client.com/login) and logs in as another user. If they do that, then the flow from #2 above to number 3 happens as normal - but since there already exists an authenticated user on our site, it seems as though the FormsAuthentication system doesn't bother kicking off anything so I don't get a chance to check for the cookie I'm looking for to login as this new user. What I'd like to do is, somewhere in my Global.asax file (probably FormsAuthenticate_OnAuthenticate), check to see if the cookie that the SSO system sends to me exists, and if so, sign out of the application using FormsAuthentication.SignOut().
Another issue that seems to be related is that if I let my Session expire, the FormsAuthentication still seems to think I am authenticated and it lets me access a page even though no currently logged in user exists in my Session, so the page doesn't render correctly. Should I tap into the Session_End event and do FormsAuthentication.SignOut() here as well?
Basically, I want to know when the authentication ticket created by
System.Web.Security.FormsAuthentication.SetAuthCookie(..) gets checked in the flow of a request so that I can determine whether I need to SignOut() and force revalidation or not.
Thanks for any help. Sorry for the length of this message, trying to be as detailed as possible.
Mustafa
Welcome to the small section of Hades that is mixing session with formsauth.
If your needs are as complex as presented, you would get more sleep if you implement a full provider stack to share amongst the participating sites. Easier said than done, I know.
But to address your question:
from http://www.codeproject.com/Articles/39026/Exploring-Web-config-system-web-httpModules.aspx
On the way in....Check ticket and set identity #
app.AuthenticateRequest += System.Web.Security.FormsAuthenticationModule.OnEnter-->OnAuthenticate
On the way out... set the ticket and redirect as necessary
app.EndRequest += System.Web.Security.FormsAuthenticationModule.OnLeave
Reflector is your friend. ;-)
I don't know about a specific event for when the cookie is checked, but you could place the appropriate logic in Application_BeginRequest() and check the user's authentication state there.
Another issue that seems to be related
is that if I let my Session expire,
the FormsAuthentication still seems to
think I am authenticated and it lets
me access a page even though no
currently logged in user exists in my
Session, so the page doesn't render
correctly.
The life of the cookie (how long until ASP.NET feels it needs to ask for a password again) and how you are managing state are unrelated. The ASP.NET authentication is cookie based so that, should a developer want to, he could turn off viewstate, session, use no query strings or hidden fields and authentication still works.
If you want to tie the interval at which you request the password to how you are persisting data, then you will want your session expiration to be roughly the same as the cookie expiration, but they will never quite match up. It would be better to have two policies (one for how fast you throw away a users session data and one for how long you are willing to wait before you need to reask for a password)

ASP.NET MVC permitting only one logged in user

I have an experience with CakePHP and now started coding on ASP.NET MVC framework.
I have a problem with the login system. How can I restrict users from logging only one time simultaneously on my system?
I can create a field in my DB where Customer becomes active when logs in. If he logs out I can make active false. But what if the session just ends? How can I catch this?
This article provides a possible solution.
This is, unfortunately, something of a challenge due to the way that the session end event are implemented as you don't have access to the information you need when they fire.
So turn the problem on its head a little, if you track the session that they last logged in on then if you get a request from that same authenticated user in a different session then remove the auth for that session (in effect the older session) with an appropriate redirect to a suitable message.
The key here is tracking not only who is currently logged in but also the session ID for that login.
Details are a bit more complicated - but you can perform the test at a request level or by adding your own base page class, deriving all your "real" pages from that and checking in a page event.

Resources