Forms Authentication understanding context.user.identity
The full workflow for Remember Me requires: 1. Write custom data to the cookie. 2. Read that custom data.
Even if you can authenticate a request via cookie, it does not mean an HttpSession object is resumable for that request.
http://www.codeproject.com/Articles/779844/Remember-Me
The way your code is written logins will persist across browser sessions. It might help to understand the basics of what is going on.
For cookie based authentication methods, there are really three actions:
1) Login - validates user's credentials and creates and stores a cookie on their browser.
2) Logout - simply removes the cookie from the browser (by expiring the cookie or deleting it)
3) Per Request Validation (the part that is is your Application_AuthenticateRequest) - check to see if a cookie exists, and if so, get the user's Identity and Roles and set HttpContext.Current.User.
Typically, the FormsAuthentication module hides most of this from you. It looks like your code is trying to use some of the elements of FormAuthentication (like the FormsAuthenticationTicket and FormsIdentity. This is fine as long as you get what you want.
Your Login_Authenticate method looks fine EXCEPT you are setting an expiration on the cookie. This will make the cookie persist even if you close and reopen the browser. Since this is not the behavior you want, I would not set a cookie expiration. Setting this is like checking the "remember me" checkbox.
The code in Application_AuthenticateRequest gets run every time a page is served from your application. It's primary job is to set HttpContext.Current.User. Typically, if no user is logged in, User is either null or an Anonymous user. If a user is logged in, this should represent your user.
If you are doing these three things, then anywhere in your code you can reference HttpContext.Current.User to decide what level of information you want to display. For instance, if you want to restrict a page to administrators only, you could call HttpContext.Current.Users.IsInRole("Administrators"), and redirect them away from the page if the call returns false.
Hope this helps.
There's a problem in your authorization tag, should be:
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
because you want to deny anonymous users. If you fix this, you can safely remove all the stuff from the master page and global.asax - you don't have to remap the forms identity to your own custom identity stored in session. It's the waste of resources and I don't think it raises the security of your solution in a significant way. You can rely on the forms cookie.
I am a bit late on the subject, but for those trying to implement forms authentication while keeping things simple (like I was trying to), here is the relevant most current documentation I have found from Microsoft: https://docs.microsoft.com/en-us/previous-versions/aspnet/xdt4thhy(v=vs.100)
In short, do not mess up with setting cookies, checking them, instantiating tickets or principal, ... Leave-it to FormsAuthentication
class.
On log on, when your code has check credentials and if they are valid, just call:
FormsAuthentication.RedirectFromLoginPage(yourUserId, false);
It does set the authentication cookie for you, which, combined with the redirect, is enough. The "false
" is for not persisting the authorization: it will be lost on browser close (or authorization timeout).
On already authenticated request, there is nothing to check by code for ensuring your authentication is valid. Use Context.User.Identity.Name
to know who is connected (would be the string yourUserId
above).
On explicit logout, call
FormsAuthentication.SignOut();
FormsAuthentication.RedirectToLoginPage();
And have forms authentication configured in web.config.
<system.web>
<authentication mode="Forms">
<forms loginUrl="yourLoginPage" defaultUrl="yourDefaultPageAfterLogin">
</forms>
</authentication>
<authorization>
<deny users="?" />
</authorization>
</system.web>
Note that for MVC applications the authorization part should be removed from configuration and handled with AuthorizeAttribute
registered as a global filter attribute, with usage of AllowAnonymousAttribute
on controllers or actions needing it. (MVC 4; prior to this one, it was required to create its own attributes for handling that.)