4

I'm making a new MVC 4 website and I have setup SimpleMembership. I have also created a CustomPrincipal which inherits from RolePrincipal and has one additional property named UserInfo which contains additional information about the user such as LastName, FirstName and IsActive. This is all stored in the cookie via FormsAuthenticationTicket userData property.

My question is the following. Suppose I have a management page where admin user can disable other user's accounts - set IsActive property to false. Suppose at the same the user which is being disabled is actually currently logged in. I don't want this user to be able to continue to navigate the site if he was denied his access rights.

How can I kill his session meaning destroy his FormsAuthentication cookie? Is this the correct thing to do or is there something else in SimpleMembership that I'm missing? What is the proper path to achieve this task? Any advise would be appreciated...

Marko
  • 12,543
  • 10
  • 48
  • 58

1 Answers1

3

I would suggest combining the use of Application_AuthenticateRequest and ASP.NET Cache, as follows:

1) When a user is deleted, write the user ID into the ASP.NET Cache, where it can sit for a finite period of time (perhaps one day):

string cacheKey = "RecentlyDeletedUserId" + userId;
Cache.Add(
    cacheKey,
    true,
    null,
    DateTime.Now.AddDays(1),
    null,
    CacheItemPriority.Normal,
    null
);

2) In global.asax, you can add the Application_AuthenticateRequest handler, which is fired for every request after the forms authentication ticket is successfully received by the server. In this handler, you make one cheap, in-memory cache request to see if that user in on the list of recently deleted users. If they are, you sign them out and redirect them to the login page.

protected void Application_AuthenticateRequest(object sender, EventArgs e) {
    string cacheKey = "RecentlyDeletedUserId" + userId;
    if (Cache[cacheKey] != null)
    {
        FormsAuthentication.SignOut();
        FormsAuthentication.RedirectToLoginPage();
    }
}

If for some reason you don't like the redirect approach, you could otherwise take an approach like this:

protected void Application_AuthenticateRequest(object sender, EventArgs e) {
    string cacheKey = "RecentlyDeletedUserId" + userId;
    if (Cache[cacheKey] != null)
    {
        IPrincipal anonymousPrincipal = new GenericPrincipal(new GenericIdentity(String.Empty), null);
        Thread.CurrentPrincipal = anonymousPrincipal;
        HttpContext.Current.User = anonymousPrincipal;
    }     
}

This simply replaces the user with an anonymous user, which ensures that the user will not be able to do anything on your site. (This alternate approach is from Invalidating ASP.NET FormsAuthentication server side.)

Community
  • 1
  • 1
J.T. Taylor
  • 4,147
  • 1
  • 23
  • 23
  • Thank you for awesome response. I think I like the cache idea better since I would have to implement UserStillValid method and I don't like the idea of running business logic in global.asax. – Marko Feb 10 '13 at 01:57
  • 1
    Sorry I cut and Pasted too much... !UserStillValid in second alternative would just be checking the cache – J.T. Taylor Feb 10 '13 at 03:15
  • what the second set of code will do? what is stored in anonymousPrincipal. what is the meaning of `Thread.CurrentPrincipal = anonymousPrincipal and HttpContext.Current.User = anonymousPrincipal;` instead of signout ? – Thomas Sep 03 '15 at 09:50
  • suppose admin has UI from where admin make a user inactive and at the same time user in a page. so when Application_AuthenticateRequest will fire? does it fire for any page request ? – Thomas Sep 03 '15 at 09:52