6

I've been reading a ton of stuff online about authentication and authorization and finally settled on some code that seems to be working...but I don't fully understand everything that it's doing (as far as the FormsAuthenticationTicket).

The MVC app I'm working with will be handling some sensitive data and I want to triple check everything I do that is related to authentication and authorization.

I am using Windows auth;

<authentication mode="Windows" />
<authorization>    
  <deny users="?"/>
</authorization>

I have a set of tables in SQL Server with additional User and Permission information.

  • Users
  • Roles
  • UsersInRoles
  • Other tables that define objects in the application and associated permissions.

In my Global.asax I have the following methods inspired from

http://www.codeproject.com/Articles/5182/Insight-into-Security-Model-using-Principal-and-Id

protected void WindowsAuthentication_OnAuthenticate(object sender, WindowsAuthenticationEventArgs e)
{
  if (e.Identity == null || !e.Identity.IsAuthenticated)
  {
    //Redirect to error or access denied page
  }

  string userData = e.Identity.AuthenticationType;          

  var cachedUser = HttpContext.Current.Cache[e.Identity.Name] as User;

  if (cachedUser == null)
  {
    var user = repo.GetUserByFullUserName(e.Identity.Name);
    HttpContext.Current.Cache.Insert(e.Identity.Name, user, null, DateTime.Now.AddMinutes(2), Cache.NoSlidingExpiration);
    cachedUser = HttpContext.Current.Cache[e.Identity.Name] as User;
  }

  var userIdentity = e.Identity.Name;

  var formsAuthTicket = new FormsAuthenticationTicket(1, e.Identity.Name, DateTime.Now, DateTime.Now.AddMinutes(2), false, userData);

  var encryptedTicket = FormsAuthentication.Encrypt(formsAuthTicket);
  var httpcook = new HttpCookie("authCookie", encryptedTicket);
  Response.Cookies.Add(httpcook);
}



protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
  if (Request.IsAuthenticated)
  {
    var httpcook = Context.Request.Cookies["authCookie"];
    var formsAuthTicket = FormsAuthentication.Decrypt(httpcook.Value);

    var cachedUser = GetCachedUser(formsAuthTicket.Name);
    if (cachedUser == null)
      {
      cachedUser = CreateCachedUser(formsAuthTicket.Name);
      } 

    var genIdentity = new GenericCustomIdentity(cachedUser, Request.IsAuthenticated, formsAuthTicket.UserData);

    var genPrincipal = new GenericCustomPrincipal(genIdentity, cachedUser);

    HttpContext.Current.User = genPrincipal;
  }
}

So here are my questions:

  1. Why have a FormsAuthenticationTicket in the WindowsAuthentication_OnAuthenticate method? Can't I just build my Identity and Principal objects in the WinAuth method?

  2. Is storing User data in HttpContext.Current.Cache a security risk? Since these methods are called numerous times I don't want to hit the db every single request. Is there a better/more secure alternative?

  3. I am unfamiliar with using FormsAuthenticationTickets, Identity, and Principal so any comments or suggestions would be greatly appreciated. Sorry, this wasn't a question.

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • [Never use the web.config to lock down ASP.Net MVC](http://stackoverflow.com/questions/11765030/how-to-lock-down-paths-in-asp-net-mvc-4) – Erik Philips Jun 13 '13 at 22:49
  • Does this also apply to Windows Authentication? There is no registration form or login screen. I'll most likely get the User.Identity and create a 'default' record in my database and then let an admin apply other permissions or restrictions at another time. I don't have all the details yet but any user with a valid AD account should be allowed access and anyone else should not. In this case should I follow the suggestions in the link or leave the web.config as is? – killerbunnyattack Jun 13 '13 at 23:04

1 Answers1

3

Why have a FormsAuthenticationTicket in the WindowsAuthentication_OnAuthenticate method? Can't I just build my Identity and Principal objects in the WinAuth method?

The Identity and Principal objects only exist during the current call/request from the client. They are part of the HttpContext and are, for lack of a better term, disposed of at the end of the request. Once the person who was authenticated connects again, there is a new request created, and by default they are not authenitcated.

The FormsAuthenticationTicket (By Default) uses a cookie on the client side to store authentication information for each subsequent request. This allows the Application_AuthenticateRequest method to use the cookie to reauthorize the request.

Is storing User data in HttpContext.Current.Cache a security risk? Since these methods are called numerous times I don't want to hit the db every single request. Is there a better/more secure alternative?

The HttpContext.Cache is stored in memory. If the server resets or the app pool restarts for any reason the cache is gone.

Yes it's a security risk, you're storing user information is server memory. The risk however is very small, unless someone had your code to see how you were using the cache, and could upload code to read the cache.

I am unfamiliar with using FormsAuthenticationTickets, Identity, and Principal so any comments or suggestions would be greatly appreciated. Sorry, this wasn't a question.

How about links to HttpContext.User (IPrincipal) with it's property Identity of type IIdentity. Not the most descriptive answer, but both interfaces are extremely basic.

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • 1
    I also forgot to mention, another security risk is editing a user so they cannot log in. If this user information is in the cache, then the user can still log in, because it's a cached version. – Erik Philips Jun 14 '13 at 00:15