title: How to Customize ASP.NET Web API AuthorizeAttribute for Unusual Requirements
body: <p>I am inheriting from <strong>System.Web.Http.AuthorizeAttribute</strong> to create a custom authorization/authentication routine to meet some unusual requirements for a web application developed using ASP.NET MVC 4. This adds security to the Web API used for Ajax calls from the web client. The requirements are:</p>
  
  <ol>
  <li>The user must logon each time they perform a transaction to verify
  someone else has not walked up to the workstation after someone has
  logged on and walked away.</li>
  <li>Roles cannot be assigned to the web service methods at program time.
  They must be assigned at run time so that an administrator can
  configure this. This information is stored in the system database.</li>
  </ol>
  
  <p>The web client is a <a href="http://en.wikipedia.org/wiki/Single-page_application">single page application (SPA)</a> so the typical forms authentication does not work so well, but I am trying reuse as much of the ASP.NET security framework as I can to meet the requirements.  The customized <strong>AuthorizeAttribute</strong> works great for requirement 2 on determining what roles are associated with a web service method. I accept three parameters, application name, resource name and operation to determine which roles are associated with a method.</p>
  
  <pre><code>public class DoThisController : ApiController
  {
      [Authorize(Application = "MyApp", Resource = "DoThis", Operation = "read")]
      public string GetData()
      {
          return "We did this.";
      }
  }
  </code></pre>
  
  <p>I override the <strong>OnAuthorization</strong> method to get the roles and authenticate the user. Since the user has to be authenticated for each transaction I reduce the back and forth chatter by performing authentication and authorization in the same step.  I get the users credentials from the web client by using basic authentication which passes the encrypted credentials in the HTTP header. So my <strong>OnAuthorization</strong> method looks like this:</p>
  
  <pre><code>public override void OnAuthorization(HttpActionContext actionContext)
  {
  
       string username;
       string password;
       if (GetUserNameAndPassword(actionContext, out username, out password))
       {
           if (Membership.ValidateUser(username, password))
           {
               FormsAuthentication.SetAuthCookie(username, false);
               base.Roles = GetResourceOperationRoles();
           }
           else
           {
               FormsAuthentication.SignOut();
               base.Roles = "";
           }
       }
       else
       {
           FormsAuthentication.SignOut();
           base.Roles = "";
       }
       base.OnAuthorization(actionContext);
   }
  </code></pre>
  
  <p><strong>GetUserNameAndPassword</strong> retrieves the credentials from the HTTP header. I then use the <strong>Membership.ValidateUser</strong> to validate the credentials. I have a custom membership provider and role provider plugged in to hit a custom database. If the user is authenticated I then retrieve the roles for the resource and operation. From there I use the base <strong>OnAuthorization</strong> to complete the authorization process.  Here is where it breaks down.</p>
  
  <p>If the user is authenticated I use the standard forms authentication methods to log the user in (FormsAuthentication.SetAuthCookie) and if they fail I log them out (FormsAuthentication.SignOut).  But the problem seems to be that base <strong>OnAuthorization</strong> class does not have access to <strong>Principal</strong> that is updated so that <strong>IsAuthenticated</strong> is set to the correct value. It is always one step behind. And my guess is that it is using some cached value that does not get updated until there is a round trip to the web client.</p>
  
  <p>So all of this leads up to my specific question which is, is there another way to set <strong>IsAuthenticated</strong> to the correct value for the current <strong>Principal</strong> without using cookies? It seems to me that cookies do not really apply in this specific scenario where I have to authenticate every time.  The reason I know <strong>IsAuthenticated</strong> is not set to the correct value is I also override the <strong>HandleUnauthorizedRequest</strong> method to this:</p>
  
  <pre><code> protected override void HandleUnauthorizedRequest(HttpActionContext filterContext)
   {
       if (((System.Web.HttpContext.Current.User).Identity).IsAuthenticated)
       {
           filterContext.Response = new HttpResponseMessage(System.Net.HttpStatusCode.Forbidden);
       }
       else
       {
           base.HandleUnauthorizedRequest(filterContext);
       }
   }
  </code></pre>
  
  <p>This allows me to return a status code of Forbidden to the web client if the failure was because of authorization instead of authentication and it can respond accordingly.</p>
  
  <p>So what is the proper way to set <strong>IsAuthenticated</strong> for the current <strong>Principle</strong> in this scenario?</p>