Search code examples
c#asp.netasp.net-web-apiasp.net-identity

Overload WEB API Token Controller


Visual Studio provides a nice ready template for ASP.NET WEB API project. There we have a set of account management functions dealing with ASP.NET Identity. However, one most fundamental function is missing both from automatically generated controllers and documentation. Namely, "~/Token" URL, which is used to grant WEB API access tokens is not mentioned anywhere.

I would like to write a custom controller to intercept all "~/Token" calls to make some logging and additional processing in a way similar to other WEB API controllers. How can I do it in a simple and natural way?


Solution

  • It seems you need OWIN OAuth 2.0 Authorization Server. This is the Microsoft extension to add the required functionality. It creates an oauth endpoint (e.g. /token) that you can use to get a token. You don't have a controller directly, but there is a special OWIN class connected to it that you will need to extend to add whatever you need.

    You can find more details here and here.

    It's a bit long reading, but it works and I have used it in a few projects.

    Here is a simple example how you can do it (GrantResourceOwnerCredentials is the most important method for you):

        public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider
        {
    
            public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
            {
                // Add CORS e.g.    
                context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
    
                using (AuthRepository _repo = new AuthRepository())
                {
                    IdentityUser user = await _repo.FindUser(context.UserName, context.Password);
    
                    if (user == null)
                    {
                        context.SetError("invalid_grant", "The user name or password is incorrect.");
                        return;
                    }
                }
    
                var identity = new ClaimsIdentity(context.Options.AuthenticationType);
                identity.AddClaim(new Claim("sub", context.UserName));
                identity.AddClaim(new Claim("role", "user"));
    
                context.Validated(identity);
    
            }
        }