views:

345

answers:

1

Hi,

I've been trying to get membership working in ASP.NET MVC. There are some pages that require authentication. Others that can have guests and authorised members. Much like StackOverflow. They can do things anonymously or as a registered user.

We also have a custom database schema of handling members (not the default ASP.NET Membership way). So I'd be looking at writing my own Membership/Principal code. So far its working well, BUT I'm having trouble with sessions expiring and being able to implement the 'Remember me' functionality.

I use FormsAuthentication.SetAuthCookie(username, rememberMe) to set the forms cookie, but say the user leaves the machine for 20mins or IIS recycles my session dies and I get a very inconsistent user state.

Where do I catch the 'Remember me' cookie and how do I handle the user logging in again? Essentially do I store the username and password and then look for the cookie in Application_BeginRequest or something?

+3  A: 

If I read you right, it seems like you are expecting ASP.NET to detect the persistent auth cookie and re-establish that user's last session state. It doesn't work that way: the authentication cookie and asp.net session are two independent things, so indeed you will have instances where a user goes back to the site and passes authentication via a persistent AuthCookie, but has brand new (empty) session data.

Assuming the AuthCookie is being set properly, you can detect that the user is authenticated with User.Identity.IsAuthenticated which is not affected by IIS recycles or session expiring. The username is exposed in User.Identity.Name.

If you need to re-initialize some Session data when a user returns to the site you'll have to do that manually. If this is really what you're asking, then it's hard to answer without knowing more about your app, but consider the Session_Start and Session_End events in the global.asax. Alternatively you can just null-check a session object and re-populate whenever it's empty (after session does expire), eg:

//get some user info from session or db if session is null
string preferredName;
if (User.Identity.IsAuthenticated)
{
    object o = Session["preferredName"];
    if (o == null)
    {
        preferredName = repository.GetUser(User.Identity.Name).PreferredName;
        Session["preferredName"] = preferredName; //save to session so this isn't necessary next time
    }
    else
    {
        preferredName = (string)o;
    }
}
else
{
    preferredName = "anon";
}
Kurt Schindler
just be aware of the cavets with session_end- it doesn't work when session state is stored in SQL server for example
RichardOD
Good point! I included it in the interest of full disclosure, but I too would avoid doing much or anything in session_end.
Kurt Schindler

related questions