Boris Zinchenko Boris Zinchenko - 1 year ago 92
ASP.NET (C#) Question

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?

Answer Source

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);

        }
    }