ASP.NET Web API – Identifier of the Identity from Membership Provider

I saw this rather interesting question in StackOverflow. Thought I’ll try to answer it in the form of a post here. Okay, the question is how to access the identifier of the identity established by FormsAuthentication (ASP.NET Membership Provider). I’m not going to discuss the suitability of Forms Authentication for Web API but just try to get a solution to the problem.

So, I create a new ASP.NET MVC 4 application (Internet template so that I get the membership provider and stuff by default). The Login method of AccountController logs in the user by calling WebSecurity.Login(model.UserName, model.Password, persistCookie: model.RememberMe)). I change it, like so:

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model, string returnUrl)
{
    if (ModelState.IsValid && Membership
                             .ValidateUser(model.UserName,
                                              model.Password))
    {
        var userId = WebSecurity.GetUserId(model.UserName);

        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket
                                                (1, model.UserName,
                                                DateTime.Now,
                                                DateTime.Now.AddHours(1),
                                                false,
                                                userId.ToString(),
                                                FormsAuthentication
                                                     .FormsCookiePath
                                                );

        // Create and add the ticket cookie to response
        Response.Cookies.Add(new HttpCookie(
                                 FormsAuthentication.FormsCookieName)
        {
            Value = FormsAuthentication.Encrypt(ticket),
            Path = FormsAuthentication.FormsCookiePath
        });

        return RedirectToLocal(returnUrl);
    }

    // If we got this far, something failed, redisplay form
    ModelState.AddModelError("",
                  "The user name or password provided is incorrect.");
    return View(model);
}

That creates the ticket with the identifier of the user in the UserData property. Next, handle PostAuthenticate event to read the ticket and add the NameIdentifier claim by adding the code below in Global.asax.cs. I assume you are on .NET 4.5 where all identities are claims based, by default.

protected void Application_PostAuthenticateRequest(Object sender, 
                                                       EventArgs e)
{
    HttpCookie cookie = Request.Cookies[
                                   FormsAuthentication.FormsCookieName];

    if (cookie != null)
    {
        FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(
                                               cookie.Value);

        var identity = HttpContext.Current.User.Identity
                                                as ClaimsIdentity;
        identity.AddClaim(new Claim(
                    ClaimTypes.NameIdentifier, ticket.UserData));
    }
}

Finally, add a new ApiController, like so:

public class ValuesController : ApiController
{
    public int Get()
    {
        var identity = User.Identity as ClaimsIdentity;
        var claim = identity.FindFirst(ClaimTypes.NameIdentifier);
            
        return Int32.Parse(claim.Value);
    }
}

Of course, I’m really being naive here and do assume quite a few things but this post hopefully illustrates the idea and that it is useful to someone.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s