In Web Api / Owin architecture, where are requests to '/token' handled?

Joe picture Joe · Apr 22, 2014 · Viewed 10.5k times · Source

I am trying to understand the Asp.net Web Api Individual Accounts authentication and authorization. I have see several tutorials on the web including this one. In short, when a user agent provides username and password the API issues a token that the client will use in subsequent calls to the API for to identify itself. The user agent receives the token by making a request, typically to: http://example.com/Token. The path appears to be set in the Startup class like so:

TokenEndpointPath = new PathString("/Token")

My problem is, I can't find any controller methods that match that path. How does this work?

Answer

Jeremie Devillard picture Jeremie Devillard · Apr 22, 2014

When you create a new Project with Individual Authentication in ASP.NET, the solution is created with an OAuth Provider to handle Authentication Request.

If you look at you solution, you should see a Providers Folder with a class ApplicationOAuthProvider.

This class implement all the logic for authenticate your members in you website. The configuration is set at Startup to allow you to customize the url endpoint through the OAuthOption.

OAuthOptions = new OAuthAuthorizationServerOptions
{
    TokenEndpointPath = new PathString("/Token"),
    Provider = new ApplicationOAuthProvider(PublicClientId),
    AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
    AllowInsecureHttp = true
};

The TokenEndPoint Path properties defined the url which will fired the GrantResourceOwnerCredentials method of the GrandResourceOwnerCredentials.

If you use fiddler to authenticate and use this kind of body

 grant_type=password&username=testUserName&password=TestPassword

you should pass in the following method :

public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        var userManager = context.OwinContext.GetUserManager<ApplicationUserManager>();

        ApplicationUser user = await userManager.FindAsync(context.UserName, context.Password);

        if (user == null)
        {
            context.SetError("invalid_grant", "The user name or password is incorrect.");
            return;
        }

        ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(userManager,
           OAuthDefaults.AuthenticationType);
        ClaimsIdentity cookiesIdentity = await user.GenerateUserIdentityAsync(userManager,
            CookieAuthenticationDefaults.AuthenticationType);

        AuthenticationProperties properties = CreateProperties(user.UserName);
        AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, properties);
        context.Validated(ticket);
        context.Request.Context.Authentication.SignIn(cookiesIdentity);
    }

where context.UserName and context.Password are set with the data used in the request. After the identity is confirmed (here using Entity Framework and a couple userName, Password in a database), a Bearer token is sent to the caller. This Bearer token could then be used to be authenticated for the other calls.

Regards.