Return JWT Token generated by OAuthAuthorizatioServer from controller in Web API Return JWT Token generated by OAuthAuthorizatioServer from controller in Web API asp.net asp.net

Return JWT Token generated by OAuthAuthorizatioServer from controller in Web API


Below is some code similar to what I'm doing in my application, which is using Asp.Net Core 1.0. Your signin and user registration will differ if you're not using Core 1.0.

public async Task<string> CreateUser(string username, string password)    {        string jwt = String.Empty;        if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password))        {            Response.StatusCode = (int)HttpStatusCode.BadRequest;        }        var user = await _userManager.FindByNameAsync(username);        if (user == null) // user doesn't exist, create user        {            var newUser = await _userManager.CreateAsync(new ApplicationUser() { UserName = username }, password);             if (newUser.Succeeded) //user was successfully created, sign in user            {                user = await _userManager.FindByNameAsync(username);                var signInResult = await _signInManager.PasswordSignInAsync(user, password, false, true);                if (signInResult.Succeeded) //user signed in, create a JWT                {                    var tokenHandler = new JwtSecurityTokenHandler();                    List<Claim> userClaims = new List<Claim>();                    //add any claims to the userClaims collection that you want to be part of the JWT                    //...                    ClaimsIdentity identity = new ClaimsIdentity(new GenericIdentity(user.UserName, "TokenAuth"), userClaims);                    DateTime expires = DateTime.Now.AddMinutes(30); //or whatever                    var securityToken = tokenHandler.CreateToken(                        issuer: _tokenOptions.Issuer,  //_tokenAuthOptions is a class that holds the issuer, audience, and RSA security key                        audience: _tokenOptions.Audience,                        subject: identity,                        notBefore: DateTime.Now,                        expires: expires,                        signingCredentials: _tokenOptions.SigningCredentials                        );                    jwt = tokenHandler.WriteToken(securityToken);                    Response.StatusCode = (int)HttpStatusCode.Created;                    await _signInManager.SignOutAsync(); //sign the user out, which deletes the cookie that gets added if you are using Identity.  It's not needed as security is based on the JWT                }            }            //handle other cases...        }    }

Basically, the user is created and then signed in automatically. I then build a JWT (add in any claims you want) and return it in the response body. On the client side (MVC and Angular JS) I get the JWT out of the response body and store it. It is then passed back to the server in the Authorization header of each subsequent request. Authorization policies for all server actions are based on the set of claims supplied by the JWT. No cookies, no state on the server.

EDIT: I suppose you don't even need to call the signIn method in this process as you can just create the user, create a JWT, and return the JWT. When a user logs in on a future request you would use the Sign-In, create token, Sign-Out approach.


The idea of sending a response with access_token, token_type and expires_in, when the user is created is a great idea. But, I would stick to calling the "/token" end point with HttpClient to achieve this task. There are quite a few security checks that needs to be performed before token is generated. Since this is security I would not take any risk. I feel comfortable using the libraries/ code provided by industry experts.

That said, I tried to come up with a class you can call to create the token once the user is created. This code has been taken from the Microsoft's implementation of OAuth Authorization Server in their Katana project. You can access the source here. As you can see there is quite a lot happening when creating the token.

Here is the modified version of that middleware class for generating the token. You have to provide the proper OAuthAuthorizationServerOptions, Context, username, password, Scopes and clientid to get an access token. Please note that this is a sample implementation to guide you in the right direction. Please test it thoroughly if you want to use this.

using System;using System.Collections.Generic;using System.Threading.Tasks;using AspNetIdentity.WebApi.Providers;using Microsoft.Owin;using Microsoft.Owin.Security;using Microsoft.Owin.Security.Infrastructure;using Microsoft.Owin.Security.OAuth;namespace WebApi.AccessToken{    public class TokenGenerator    {        public string ClientId { get; set; }        public string UserName { get; set; }        public string Password { get; set; }        public IList<string> Scope { get; set; }        private OAuthAuthorizationServerOptions Options { get; } =            new OAuthAuthorizationServerOptions()            {                //For Dev enviroment only (on production should be AllowInsecureHttp = false)                AllowInsecureHttp = true,                TokenEndpointPath = new PathString("/oauth/token"),                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),                Provider = new CustomOAuthProvider(),                AccessTokenFormat = new CustomJwtFormat("http://localhost:59822")            };        public async Task<IList<KeyValuePair<string, string>>>  InvokeTokenEndpointAsync(IOwinContext owinContext)        {            var result = new List<KeyValuePair<string, string>>();            DateTimeOffset currentUtc = Options.SystemClock.UtcNow;            // remove milliseconds in case they don't round-trip            currentUtc = currentUtc.Subtract(TimeSpan.FromMilliseconds(currentUtc.Millisecond));            AuthenticationTicket ticket = await InvokeTokenEndpointResourceOwnerPasswordCredentialsGrantAsync(owinContext, Options, currentUtc);            if (ticket == null)            {                result.Add(new KeyValuePair<string, string>("ERROR", "Failed to create acess_token"));                return result;            }            ticket.Properties.IssuedUtc = currentUtc;            ticket.Properties.ExpiresUtc = currentUtc.Add(Options.AccessTokenExpireTimeSpan);            ticket = new AuthenticationTicket(ticket.Identity, ticket.Properties);            var accessTokenContext = new AuthenticationTokenCreateContext(                owinContext,                Options.AccessTokenFormat,                ticket);            await Options.AccessTokenProvider.CreateAsync(accessTokenContext);            string accessToken = accessTokenContext.Token;            if (string.IsNullOrEmpty(accessToken))            {                accessToken = accessTokenContext.SerializeTicket();            }            DateTimeOffset? accessTokenExpiresUtc = ticket.Properties.ExpiresUtc;            result.Add(new KeyValuePair<string, string>("access_token", accessToken));            result.Add(new KeyValuePair<string, string>("token_type", "bearer"));            TimeSpan? expiresTimeSpan = accessTokenExpiresUtc - currentUtc;            var expiresIn = (long)expiresTimeSpan.Value.TotalSeconds;            if (expiresIn > 0)            {                result.Add(new KeyValuePair<string, string>("expires_in", "bearer"));            }            return result;        }        private async Task<AuthenticationTicket> InvokeTokenEndpointResourceOwnerPasswordCredentialsGrantAsync(IOwinContext owinContext, OAuthAuthorizationServerOptions options, DateTimeOffset currentUtc)        {            var grantContext = new OAuthGrantResourceOwnerCredentialsContext(                owinContext,                 options,                 ClientId,                 UserName,                 Password,                 Scope);            await options.Provider.GrantResourceOwnerCredentials(grantContext);            return grantContext.Ticket;        }    }}

Please let me know if you have any questions.

Thank you,Soma.


I assume you are referring to the following article: http://bitoftech.net/2015/02/16/implement-oauth-json-web-tokens-authentication-in-asp-net-web-api-and-identity-2/

The general approach to authenticating a user in this case is

  1. Make an HTTP call to the token endpoint
  2. User Enters the credentials at the UI that is rendered
  3. IdP verifies the credentials and issues a token
  4. User makes another call to an authorized endpoint and OWIN will validate this (JWT) token (as configured in the ConfigureOAuthTokenConsumption method) and if successfull will set a user session with expiry same as the token expiry. The session is set using session cookies.

Now try to understand that in general, this whole process of authentication is required because your server does not trust the user logging in to be the user the person is claiming to be. However, in your case, you (or your server code) just created a user and you know for sure that the person accessing your website is the user you have just created. In this case you don't need to validate a token to create a session for this user. Just create a session with an expiry that suits your use-case.

The next time the user will have to log-in and prove him/herself to the server using a token but this time the user does not need to prove him/her self.

Note: If you absolutely are adamant about requiring a token to log in a user who you yourself have just created using their credentials here are a couple of issues.

  • You are taking on the responsibility of storing (having access to) the user credentials, which might not be with you over the lifetime of the application (in most cases you might want to act as a relying party rather than an IdP).
  • Even if you want to then doing it is not trivial. You will have to make the calls to the token end point in code (server or client side) on behalf of the user, enter their credentials for them, retrieve the token, call an authenticated endpoint on your site and retrieve the session cookie all while hiding all this from the user, which probably is something you will either do if you hate yourself :) but also isn't very secure way of doing things especially when you are taking all the trouble to implement OAuth in the first place.

Also, take a look at Windows Server 2016 (technical preview 5 at this time) which supports implicit grants and might take writing all this custom code off your plate if you can wait a bit for RTM.