Security problems with autologin and FormsAuthenticationTicket - asp.net-mvc

Im using autologin on my MVC 3 website.
How do I best handle this problem:
A user signs in at his own computer (and gets a 30 day cookie)
Same user signs in at a friends computer (and gets a 30 day cookie)
Its now possible to autologin in at both computers. The user realizes this and changes his password but his friend is still able to autologin from his computer until the cookie expires.
How do I best handle this?
I could of course set at date on the user when password changed and check this up against the date in the cookie.
Or am I missing something?

I know what you're saying, but I think you're implying an association between the "remember me" function and the "password change" function which in practice, isn't there. The auth token you get when authenticating is not generally tied to the value of the password (i.e. when using the membership provider), after all, you're logically keeping the identity authenticated across sessions and in this regard, it works just fine.
To be honest, this sounds like more of a user behaviour problem than a technology problem. In your use case, someone is consciously asking the browser to allow them to remain authenticated for a long period of time and doing so on a machine which they have no control over. Of course I'm assuming you have a "remember me" checkbox and if you don't, there's your answer right there.
The other thing you might want to look at is what OWASP talks about in part 3 of the Top 10 - Broken authentication and session management. This link will put it in a .NET context for you but in short, it talks a lot about reducing the opportunity for exactly what you're describing to happen by things like eager session expiration, disabling sliding sessions and obviously giving end users the control to expire the token at session expiration and log out at any time.

Don't yo have Remember me checkbox on your login form. The value of this checkbox will dictate whether you are going to create persistent cookie or not. if you don't create persistent cookie, it will expire as soon as session ends. In this scenario you user can leave Remember me checkbox unchecked when logging in on his friends computer. If he doesn't he is calling for trouble himself.

Related

how to close activated sessions and force user to re-enter his credentials in identity server 4?

One user can log in through multiple systems with various IP addresses, so is there any way to deactivate one of his sessions? (or all other sessions except the current logged in one) if yes, how?
The thing I want to do is exactly like Telegram which you are able to close any of your activated sessions.
The question is not new here, it appears a couple times a month in different interpretations, and the answer is still: there is no such feature out of the box, but there are a couple approaches:
The first one is to use Reference Token (instead of jwt by default), then look through the persisted grants database and logout all the sessions for the target userId.
The other approach is to implement your custom session store based on a database (instead of the cookie based by default). Then you again have access to all the clients logged in with the given user id. Here is my old (but still valid) example of a hybrid (cookie + IDistributedCache such as REDIS) extension for the DefaultUserSession. Here you have to be careful with access token lifetime (make it reasonably short), as a jwt once issued can not be invalidated before its normal expiration.

ActiveDirectoryMembershipProvider and Forms authentication

I've got a ASP.NET MVC web app which uses forms authentication.
I'm using ActiveDirectoryMembershipProvider to validate users against our domain.
if (Membership.ValidateUser(m.Username, m.Password))
{
FormsAuthentication.SetAuthCookie(m.Username, true);
....
This means the user gets validated only when they log in.
Problem with that is ofcourse that if the user's password changes they still remain logged in. Or worse, user leaves our company with a grudge, and they still have access.
I would have thought such a simple use case would have an obvious answer but I've been stuck on this for a while now.
I could put the users password in the session and then validate it every time, but that doesn't feel right.
What is the suggested/correct way of handling this?
The typical solution is to force log out when users unsubscribes from the service or less commonly when they change password. Use this method:
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
If the user can be deactivated outside of the app (i.e. Active Directory), the typical practice is to rely on the session time-out and perhaps ask for the credentials once more for critical operations. If you absolutely cannot allow the deactivated user to work while the session is still active, then yes, you'll have to check the credentials on every request. Since storing the password in the app is a very bad idea, it means you'll have to ask for credentials on each request which arguably is an even worse idea.
As for the password change, it normally doesn't modify the user's permissions so it should be harmless to allow for them to continue working.
The answer is to periodically (every 30 minutes or so) check User.IsApproved and User.LastPasswordChangedDate to make sure the users credentials are still valid.
To do this you need to manually create the FormsAuthenticationTicket and cookie, rather than using FormsAuthentication.SetAuthCookie.
Put the date you validated the user inside UserData and compare this against LastPasswordChangedDate.
I've implemented this and it works perfectly.
More information here
Check if Active Directory password is different from cookie

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)

Handling website access changes when using cookies

If I have a site that uses cookies for authorisation, so when the user returns they don't have to login again.
If for some reason the site admin cancel this users account what is the best way to check for this. I don't want to have to hit the database every time the user visits a page to make sure their account is still live.
So how should I handle this situation?
Several options. Set a shorter expiration on the cookie so they'd have to get authenticated afresh sooner.
Another alternative is to have any important action require that they be authenticated against the database. Thus you would only be hitting the database for more privileged actions that would more likely overlap with the high priority things you'd want a cancelled user be unable to do.

Implementation of "Remember me" in a Rails application

My Rails-app has a sign in box with a "remember me" checkbox. Users who check that box should remain logged in even after closing their browser. I'm keeping track of whether users are logged in by storing their id in the user's session.
But sessions are implemented in Rails as session cookies, which are not persistent. I can make them persistent:
class ApplicationController < ActionController::Base
before_filter :update_session_expiration_date
private
def update_session_expiration_date
options = ActionController::Base.session_options
unless options[:session_expires]
options[:session_expires] = 1.year.from_now
end
end
end
But that seems like a hack, which is surprising for such common functionality. Is there any better way?
Edit
Gareth's answer is pretty good, but I would still like an answer from someone familiar with Rails 2 (because of it's unique CookieSessionStore).
You should almost certainly not be extending the session cookie to be long lived.
Although not dealing specifically with rails this article goes to some length to explain 'remember me' best practices.
In summary though you should:
Add an extra column to the user table to accept a large random value
Set a long lived cookie on the client which combines the user id and the random value
When a new session starts, check for the existence of the id/value cookie and authenticate the new user if they match.
The author also recommends invalidating the random value and resetting the cookie at every login. Personally I don't like that as you then can't stay logged into a site on two computers. I would tend to make sure my password changing function also reset the random value thus locking out sessions on other machines.
As a final note, the advice he gives on making certain functions (password change/email change etc) unavailable to auto authenticated sessions is well worth following but rarely seen in the real world.
I have spent a while thinking about this and came to some conclusions. Rails session cookies are tamper-proof by default, so you really don't have to worry about a cookie being modified on the client end.
Here is what I've done:
Session cookie is set to be long-lived (6 months or so)
Inside the session store
An 'expires on' date that is set to login + 24 hours
user id
Authenticated = true so I can allow for anonymous user sesssions (not dangerous because of the cookie tamper protection)
I add a before_filter in the Application Controller that checks the 'expires on' part of the session.
When the user checks the "Remember Me" box, I just set the session[:expireson] date to be login + 2 weeks. No one can steal the cookie and stay logged in forever or masquerade as another user because the rails session cookie is tamper-proof.
I would suggest that you either take a look at the RESTful_Authentication plug in, which has an implementation of this, or just switch your implementation to use the RESTful Authentication_plugin. There is a good explanation about how to use this plug in at Railscasts:
railscasts #67 restful_authentication
Here is a link to the plugin itself
restful_authentication
The restful_authentication plugin has a good implementation of this:
http://agilewebdevelopment.com/plugins/restful_authentication
Note that you don't want to persist their session, just their identity. You'll create a fresh session for them when they return to your site. Generally you just assign a GUID to the user, write that to their cookie, then use it to look them up when they come back. Don't use their login name or user ID for the token as it could easily be guessed and allow crafty visitors to hijack other users' accounts.
This worked like a charm for me:
http://squarewheel.wordpress.com/2007/11/03/session-cookie-expiration-time-in-rails/
Now my CookieStore sessions expire after two weeks, whereby the user must submit their login credentials again in order to be persistently logged-in for another two weeks.
Bascially, it's as simple as:
including one file in vendor/plugins directory
set session expiry value in application controller using just one line
I would go for Devise for a brilliant authentication solution for rails.

Resources