Bit of Technology

  • Archive
  • About Me
    • Advertise
    • Disclaimer
  • Speaking
  • Contact

JSON Web Token in ASP.NET Web API 2 using Owin

October 27, 2014 By Taiseer Joudeh 332 Comments

Be Sociable, Share!

  • Tweet
  • Email
  • WhatsApp

In the previous post Decouple OWIN Authorization Server from Resource Server we saw how we can separate the Authorization Server and the Resource Server by unifying the “decryptionKey” and “validationKey” key values in machineKey node in the web.config file for the Authorization and the Resource server. So once the user request an access token from the Authorization server, the Authorization server will use this unified key to encrypt the access token, and at the other end when the token is sent to the Resource server, it will use the same key to decrypt this access token and extract the authentication ticket from it.

The source code for this tutorial is available on GitHub.

This way works well if you have control on your Resource servers (Audience) which will rely on your Authorization server (Token Issuer) to obtain access tokens from, in other words you are fully trusting those Resource servers so you are sharing with them the same “decryptionKey” and “validationKey” values.

But in some situations you might have big number of Resource servers rely on your Authorization server, so sharing the same “decryptionKey” and “validationKey” keys with all those parties become inefficient process as well insecure, you are using the same keys for multiple Resource servers, so if a key is compromised all the other Resource servers will be affected.

To overcome this issue we need to configure the Authorization server to issue access tokens using JSON Web Tokens format (JWT) instead of the default access token format, as well on the Resource server side we need to configure it to consume this new JWT access tokens, as well you will see through out this post that there is no need to unify the “decryptionKey” and “validationKey” key values anymore if we used JWT.

Featured Image

What is JSON Web Token (JWT)?

JSON Web Token is a security token which acts as a container for claims about the user, it can be transmitted easily between the Authorization server (Token Issuer), and the Resource server (Audience), the claims in JWT are encoded using JSON which make it easier to use especially in applications built using JavaScript.

JSON Web Tokens can be signed following the JSON Web Signature (JWS) specifications, as well it can be encrypted following the JSON Web Encryption (JWE) specifications, in our case we will not transmit any sensitive data in the JWT payload, so we’ll only sign this JWT to protect it from tampering during the transmission between parties.

JSON Web Token (JWT) Format

Basically the JWT is a string which consists of three parts separated by a dot (.) The JWT parts are: <header>.<payload>.<signature>.

The header part is JSON object which contains 2 nodes always and looks as the following:  { "typ": "JWT", "alg": "HS256" } The “type” node has always “JWT” value, and the node “alg” contains the algorithm used to sign the token, in our case we’ll use “HMAC-SHA256” for signing.

The payload part is JSON object as well which contains all the claims inside this token, check the example shown in the snippet below:

1
2
3
4
5
6
7
8
9
10
11
12
{
  "unique_name": "SysAdmin",
  "sub": "SysAdmin",
  "role": [
    "Manager",
    "Supervisor"
  ],
  "iss": "http://myAuthZServer",
  "aud": "379ee8430c2d421380a713458c23ef74",
  "exp": 1414283602,
  "nbf": 1414281802
}

All those claims are not mandatory  in order to build JWT, you can read more about JWT claims here. In our case we’ll always use those set of claims in the JWT we are going to issue, those claims represent the below:

  • The “sub” (subject) and “unique_claim” claims represent the user name this token issued for.
  • The “role” claim represents the roles for the user.
  • The “iss” (issuer) claim represents the Authorization server (Token Issuer) party.
  • The “aud” (audience) claim represents the recipients that the JWT is intended for (Relying Party – Resource Server). More on this unique string later in this post.
  • The “exp” (expiration time) claim represents the expiration time of the JWT, this claim contains UNIX time value.
  • The “nbf” (not before) claim represent the time which this JWT must not be used before, this claim contains UNIX time vale.

Lastly the signature part of the JWT is created by taking the header and payload parts, base 64 URL encode them, then concatenate them with “.”, then use the “alg” defined in the <header> part to generate the signature, in our case “HMAC-SHA256”. The resulting part of this signing process is byte array which should be base 64 URL encoded then concatenated with the <header>.<payload> to produce a complete JWT.

JSON Web Tokens support in ASP.NET Web API and Owin middleware.

There is no direct support for issuing JWT in ASP.NET Web API or ready made Owin middleware responsible for doing this, so in order to start issuing JWTs we need to implement this manually by implementing the interface “ISecureDataFormat” and implement the method “Protect”. More in this later. But for consuming the JWT in a Resource server there is ready middleware named “Microsoft.Owin.Security.Jwt” which understands validates, and and de-serialize JWT tokens with minimal number of line of codes.

So most of the heavy lifting we’ll do now will be in implementing the Authorization Server.

What we’ll build in this tutorial?

We’ll build a single Authorization server which issues JWT using ASP.NET Web API 2 on top of Owin middleware, the Authorization server is hosted on Azure (http://JwtAuthZSrv.azurewebsites.net) so you can test it out by adding new Resource servers. Then we’ll build a single Resource server (audience) which will process JWTs issued by our Authorization server only.

I’ll split this post into two sections, the first section will be for creating the Authorization server, and the second section will cover creating Resource server.

The source code for this tutorial is available on GitHub.

Section 1: Building the Authorization Server (Token Issuer)

Step 1.1: Create the Authorization Server Web API Project

Create an empty solution and name it “JsonWebTokensWebApi” then add a new ASP.NET Web application named “AuthorizationServer.Api”, the selected template for the project will be “Empty” template with no core dependencies. Notice that the authentication is set to “No Authentication”.

Step 1.2: Install the needed NuGet Packages:

Open package manger console and install the below Nuget packages:

1
2
3
4
5
6
7
Install-Package Microsoft.AspNet.WebApi -Version 5.2.2
Install-Package Microsoft.AspNet.WebApi.Owin -Version 5.2.2
Install-Package Microsoft.Owin.Host.SystemWeb -Version 3.0.0
Install-Package Microsoft.Owin.Cors -Version 3.0.0
Install-Package Microsoft.Owin.Security.OAuth -Version 3.0.0
Install-Package System.IdentityModel.Tokens.Jwt -Version 4.0.0
Install-Package Thinktecture.IdentityModel.Core Version 1.2.0

You can refer to the previous post if you want to know what each package is responsible for. The package named “System.IdentityModel.Tokens.Jwt” is responsible for validating, parsing and generating JWT tokens. As well we’ve used the package “Thinktecture.IdentityModel.Core” which contains class named “HmacSigningCredentials”  which will be used to facilitate creating signing keys.

Step 1.3: Add Owin “Startup” Class:

Right click on your project then add a new class named “Startup”. It will contain the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();
 
            // Web API routes
            config.MapHttpAttributeRoutes();
            
            ConfigureOAuth(app);
            
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
            
            app.UseWebApi(config);
 
        }
 
        public void ConfigureOAuth(IAppBuilder app)
        {
 
            OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
            {
                //For Dev enviroment only (on production should be AllowInsecureHttp = false)
                AllowInsecureHttp = true,
                TokenEndpointPath = new PathString("/oauth2/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
                Provider = new CustomOAuthProvider(),
                AccessTokenFormat = new CustomJwtFormat("http://jwtauthzsrv.azurewebsites.net")
            };
 
            // OAuth 2.0 Bearer Access Token Generation
            app.UseOAuthAuthorizationServer(OAuthServerOptions);
 
        }
    }

Here we’ve created new instance from class “OAuthAuthorizationServerOptions” and set its option as the below:

  • The path for generating JWT will be as :”http://jwtauthzsrv.azurewebsites.net/oauth2/token”.
  • We’ve specified the expiry for token to be 30 minutes
  • We’ve specified the implementation on how to validate the client and Resource owner user credentials in a custom class named “CustomOAuthProvider”.
  • We’ve specified the implementation on how to generate the access token using JWT formats, this custom class named “CustomJwtFormat” will be responsible for generating JWT instead of default access token using DPAPI, note that both are using bearer scheme.

We’ll come to the implementation of both class later in the next steps.

Step 1.4: Resource Server (Audience) Registration:

Now we need to configure our Authorization server to allow registering Resource server(s) (Audience), this step is very important because we need a way to identify which Resource server (Audience) is requesting the JWT token, so the Authorization server will be able to issue JWT token for this audience only.

The minimal needed information to register a Recourse server into an Authorization server are a unique Client Id, and shared symmetric key. For the sake of keeping this tutorial simple I’m persisting those information into a volatile dictionary so the values for those Audiences will be removed from the memory if IIS reset toke place, for production scenario you need to store those values permanently on a database.

Now add new folder named “Entities” then add new class named “Audience” inside this class paste the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
    public class Audience
    {
        [Key]
        [MaxLength(32)]
        public string ClientId { get; set; }
        
        [MaxLength(80)]
        [Required]
        public string Base64Secret { get; set; }
        
        [MaxLength(100)]
        [Required]
        public string Name { get; set; }
    }

Then add new folder named “Models” the add new class named “AudienceModel” inside this class paste the code below:

1
2
3
4
5
6
    public class AudienceModel
    {
        [MaxLength(100)]
        [Required]
        public string Name { get; set; }
    }

Now add new class named “AudiencesStore” and paste the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
    public static class AudiencesStore
    {
        public static ConcurrentDictionary<string, Audience> AudiencesList = new ConcurrentDictionary<string, Audience>();
        
        static AudiencesStore()
        {
            AudiencesList.TryAdd("099153c2625149bc8ecb3e85e03f0022",
                                new Audience { ClientId = "099153c2625149bc8ecb3e85e03f0022",
                                                Base64Secret = "IxrAjDoa2FqElO7IhrSrUJELhUckePEPVpaePlS_Xaw",
                                                Name = "ResourceServer.Api 1" });
        }
 
        public static Audience AddAudience(string name)
        {
            var clientId = Guid.NewGuid().ToString("N");
 
            var key = new byte[32];
            RNGCryptoServiceProvider.Create().GetBytes(key);
            var base64Secret = TextEncodings.Base64Url.Encode(key);
 
            Audience newAudience = new Audience { ClientId = clientId, Base64Secret = base64Secret, Name = name };
            AudiencesList.TryAdd(clientId, newAudience);
            return newAudience;
        }
 
        public static Audience FindAudience(string clientId)
        {
            Audience audience = null;
            if (AudiencesList.TryGetValue(clientId, out audience))
            {
                return audience;
            }
            return null;
        }
    }

Basically this class acts like a repository for the Resource servers (Audiences), basically it is responsible for two things, adding new audience and finding exiting one.

Now if you take look on method “AddAudience” you will notice that we’ve implemented the following:

  • Generating random string of 32 characters as an identifier for the audience (client id).
  • Generating 256 bit random key using the “RNGCryptoServiceProvider” class then base 64 URL encode it, this key will be shared between the Authorization server and the Resource server only.
  • Add the newly generated audience to the in-memory “AudiencesList”.
  • The “FindAudience” method is responsible for finding an audience based on the client id.
  • The constructor of the class contains fixed audience for the demo purpose.

Lastly we need to add an end point in our Authorization server which allow registering new Resource servers (Audiences), so add new folder named “Controllers” then add new class named “AudienceController” and paste the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    [RoutePrefix("api/audience")]
    public class AudienceController : ApiController
    {
        [Route("")]
        public IHttpActionResult Post(AudienceModel audienceModel)
        {
            if (!ModelState.IsValid) {
                return BadRequest(ModelState);
            }
 
            Audience newAudience = AudiencesStore.AddAudience(audienceModel.Name);
 
            return Ok<Audience>(newAudience);
 
        }
    }

This end point can be accessed by issuing HTTP POST request to the URI http://jwtauthzsrv.azurewebsites.net/api/audience as the image below, notice that the Authorization server is responsible for generating the client id and the shared symmetric key. This symmetric key should not be shared with any party except the Resource server (Audience) requested it.

Note: In real world scenario the Resource server (Audience) registration process won’t be this trivial, you might go through workflow approval. Sharing the key will take place using a secure admin portal, as well you might need to provide the audience with the ability to regenerate the key in case it get compromised.

Register Audience

Step 1.5: Implement the “CustomOAuthProvider” Class

Now we need to implement the code responsible for issuing JSON Web Token when the requester issue HTTP POST request to the URI: http://jwtauthzsrv.azurewebsites.net/oauth2/token the request will look as the image below, notice how we are setting the client id for for the Registered resource (audience) from the previous step using key (client_id).

Issue JWT

To implement this we need to add new folder named “Providers” then add new class named “CustomOAuthProvider”, paste the code snippet below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
    public class CustomOAuthProvider : OAuthAuthorizationServerProvider
    {
 
        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {
            string clientId = string.Empty;
            string clientSecret = string.Empty;
            string symmetricKeyAsBase64 = string.Empty;
 
            if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
            {
                context.TryGetFormCredentials(out clientId, out clientSecret);
            }
 
            if (context.ClientId == null)
            {
                context.SetError("invalid_clientId", "client_Id is not set");
                return Task.FromResult<object>(null);
            }
 
            var audience = AudiencesStore.FindAudience(context.ClientId);
 
            if (audience == null)
            {
                context.SetError("invalid_clientId", string.Format("Invalid client_id '{0}'", context.ClientId));
                return Task.FromResult<object>(null);
            }
            
            context.Validated();
            return Task.FromResult<object>(null);
        }
 
        public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        {
 
            context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
 
            //Dummy check here, you need to do your DB checks against memebrship system http://bit.ly/SPAAuthCode
            if (context.UserName != context.Password)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect");
                //return;
                return Task.FromResult<object>(null);
            }
 
            var identity = new ClaimsIdentity("JWT");
 
            identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
            identity.AddClaim(new Claim("sub", context.UserName));
            identity.AddClaim(new Claim(ClaimTypes.Role, "Manager"));
            identity.AddClaim(new Claim(ClaimTypes.Role, "Supervisor"));
 
            var props = new AuthenticationProperties(new Dictionary<string, string>
                {
                    {
                         "audience", (context.ClientId == null) ? string.Empty : context.ClientId
                    }
                });
 
            var ticket = new AuthenticationTicket(identity, props);
            context.Validated(ticket);
            return Task.FromResult<object>(null);
        }
    }

As you notice this class inherits from class “OAuthAuthorizationServerProvider”, we’ve overridden two methods “ValidateClientAuthentication” and “GrantResourceOwnerCredentials”

  • The first method “ValidateClientAuthentication” will be responsible for validating if the Resource server (audience) is already registered in our Authorization server by reading the client_id value from the request, notice that the request will contain only the client_id without the shared symmetric key. If we take the happy scenario and the audience is registered we’ll mark the context as a valid context which means that audience check has passed and the code flow can proceed to the next step which is validating that resource owner credentials (user who is requesting the token).
  • The second method “GrantResourceOwnerCredentials” will be responsible for validating the resource owner (user) credentials, for the sake of keeping this tutorial simple I’m considering that each identical username and password combination are valid, in read world scenario you will do your database checks against membership system such as ASP.NET Identity, you can check this in the previous post.
  • Notice that we are setting the authentication type for those claims to “JWT”, as well we are passing the the audience client id as a property of the “AuthenticationProperties”, we’ll use the audience client id in the next step.
  • Now the JWT access token will be generated when we call “context.Validated(ticket), but we still need to implement the class “CustomJwtFormat” we talked about in step 1.3.

Step 1.5: Implement the “CustomJwtFormat” Class

This class will be responsible for generating the JWT access token, so what we need to do is to add new folder named “Formats” then add new class named “CustomJwtFormat” and paste the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
   public class CustomJwtFormat : ISecureDataFormat<AuthenticationTicket>
    {
        private const string AudiencePropertyKey = "audience";
 
        private readonly string _issuer = string.Empty;
 
        public CustomJwtFormat(string issuer)
        {
            _issuer = issuer;
        }
 
        public string Protect(AuthenticationTicket data)
        {
            if (data == null)
            {
                throw new ArgumentNullException("data");
            }
 
            string audienceId = data.Properties.Dictionary.ContainsKey(AudiencePropertyKey) ? data.Properties.Dictionary[AudiencePropertyKey] : null;
 
            if (string.IsNullOrWhiteSpace(audienceId)) throw new InvalidOperationException("AuthenticationTicket.Properties does not include audience");
 
            Audience audience = AudiencesStore.FindAudience(audienceId);
 
            string symmetricKeyAsBase64 = audience.Base64Secret;
  
            var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
 
            var signingKey = new HmacSigningCredentials(keyByteArray);
 
            var issued = data.Properties.IssuedUtc;
            var expires = data.Properties.ExpiresUtc;
 
            var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);
 
            var handler = new JwtSecurityTokenHandler();
 
            var jwt = handler.WriteToken(token);
 
            return jwt;
        }
 
        public AuthenticationTicket Unprotect(string protectedText)
        {
            throw new NotImplementedException();
        }
    }

What we’ve implemented in this class is the following:

  • The class “CustomJwtFormat” implements the interface “ISecureDataFormat<AuthenticationTicket>”, the JWT generation will take place inside method “Protect”.
  • The constructor of this class accepts the “Issuer” of this JWT which will be our Authorization server, this can be string or URI, in our case we’ll fix it to URI with the value “http://jwtauthzsrv.azurewebsites.net”
  • Inside “Protect” method we are doing the following:
    1. Reading the audience (client id) from the Authentication Ticket properties, then getting this audience from the In-memory store.
    2. Reading the Symmetric key for this audience and Base64 decode it to byte array which will be used to create a HMAC265 signing key.
    3. Preparing the raw data for the JSON Web Token which will be issued to the requester by providing the issuer, audience, user claims, issue date, expiry date, and the signing Key which will sign the JWT payload.
    4. Lastly we serialize the JSON Web Token to a string and return it to the requester.
  • By doing this requester for an access token from our Authorization server will receive a signed token which contains claims for a certain resource owner (user) and this token intended to certain Resource server (audience) as well.

So if we need to request a JWT from our Authorization server for a user named “SuperUser” that needs to access the Resource server (audience) “099153c2625149bc8ecb3e85e03f0022”, all we need to do is to issue HTTP POST to the token end point (http://jwtauthzsrv.azurewebsites.net/oauth2/token) as the image below:

Issue JWT2

The result for this will be the below JSON Web Token:

1
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlxdWVfbmFtZSI6IlN1cGVyVXNlciIsInN1YiI6IlN1cGVyVXNlciIsInJvbGUiOlsiTWFuYWdlciIsIlN1cGVydmlzb3IiXSwiaXNzIjoiaHR0cDovL2p3dGF1dGh6c3J2LmF6dXJld2Vic2l0ZXMubmV0IiwiYXVkIjoiMDk5MTUzYzI2MjUxNDliYzhlY2IzZTg1ZTAzZjAwMjIiLCJleHAiOjE0MTQzODEyODgsIm5iZiI6MTQxNDM3OTQ4OH0.pZffs_TSXjgxRGAPQ6iJql7NKfRjLs1WWSliX5njSYU

There is an online JWT debugger tool named jwt.io that allows you to paste the encoded JWT and decode it so you can interpret the claims inside it, so open the tool and paste the JWT above and you should receive response as the image below, notice that all the claims are set properly including the iss, aud, sub,role, etc…

One thing to notice here that there is red label which states that the signature is invalid, this is true because this tool doesn’t know about the shared symmetric key issued for the audience (099153c2625149bc8ecb3e85e03f0022).

So if we decided to share this symmetric key with the tool and paste the key in the secret text box; we should receive green label stating that signature is valid, and this is identical to the implementation we’ll see in the Resource server when it receives a request containing a JWT.

jwtio

Now the Authorization server (Token issuer) is able to register audiences and issue JWT tokens, so let’s move to adding a Resource server which will consume the JWT tokens.

Section 2: Building the Resource Server (Audience)

Step 2.1: Creating the Resource Server Web API Project

Add a new ASP.NET Web application named “ResourceServer.Api”, the selected template for the project will be “Empty” template with no core dependencies. Notice that the authentication is set to “No Authentication”.

Step 2.2: Installing the needed NuGet Packages:

Open package manger console and install the below Nuget packages:

1
2
3
4
5
Install-Package Microsoft.AspNet.WebApi -Version 5.2.2
Install-Package Microsoft.AspNet.WebApi.Owin -Version 5.2.2
Install-Package Microsoft.Owin.Host.SystemWeb -Version 3.0.0
Install-Package Microsoft.Owin.Cors -Version 3.0.0
Install-Package Microsoft.Owin.Security.Jwt -Version 3.0.0

The package “Microsoft.Owin.Security.Jwt” is responsible for protecting the Resource server resources using JWT, it only validate and de-serialize JWT tokens.

Step 2.3: Add Owin “Startup” Class:

Right click on your project then add a new class named “Startup”. It will contain the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            HttpConfiguration config = new HttpConfiguration();
 
            config.MapHttpAttributeRoutes();
 
            ConfigureOAuth(app);
 
            app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
          
            app.UseWebApi(config);
 
        }
 
        public void ConfigureOAuth(IAppBuilder app)
        {
            var issuer = "http://jwtauthzsrv.azurewebsites.net";
            var audience = "099153c2625149bc8ecb3e85e03f0022";
            var secret = TextEncodings.Base64Url.Decode("IxrAjDoa2FqElO7IhrSrUJELhUckePEPVpaePlS_Xaw");
 
            // Api controllers with an [Authorize] attribute will be validated with JWT
            app.UseJwtBearerAuthentication(
                new JwtBearerAuthenticationOptions
                {
                    AuthenticationMode = AuthenticationMode.Active,
                    AllowedAudiences = new[] { audience },
                    IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                    {
                        new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
                    }
                });
 
        }
    }

This is the most important step in configuring the Resource server to trust tokens issued by our Authorization server (http://jwtauthzsrv.azurewebsites.net), notice how we are providing the values for the issuer, audience (client id), and the shared symmetric secret we obtained once we registered the resource with the authorization server.

By providing those values to JwtBearerAuthentication middleware, this Resource server will be able to consume only JWT tokens issued by the trusted Authorization server and issued for this audience only.

Note: Always store keys in config files not directly in source code.

Step 2.4: Add new protected controller

Now we want to add a controller which will serve as our protected resource, this controller will return list of claims for the authorized user, those claims for sure are encoded within the JWT we’ve obtained from the Authorization Server. So add new controller named “ProtectedController” under “Controllers” folder and paste the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    [Authorize]
    [RoutePrefix("api/protected")]
    public class ProtectedController : ApiController
    {
        [Route("")]
        public IEnumerable<object> Get()
        {
            var identity = User.Identity as ClaimsIdentity;
 
            return identity.Claims.Select(c => new
            {
                Type = c.Type,
                Value = c.Value
            });
        }
    }

Notice how we attribute the controller with [Authorize] attribute which will protect this resource and only will authentic HTTP GET requests containing a valid JWT access token, with valid I mean:

  • Not expired JWT.
  • JWT issued by our Authorization server (http://jwtauthzsrv.azurewebsites.net).
  • JWT issued for the audience (099153c2625149bc8ecb3e85e03f0022) only.

Conclusion

Using signed JSON Web Tokens facilitates and standardize the way of separating the Authorization server and the Resource server, no more need for unifying machineKey values nor having the risk of sharing the “decryptionKey” and “validationKey” key values among different Resource servers.

Keep in mind that the JSON Web Token we’ve created in this tutorial is signed only, so do not put any sensitive information in it 🙂

The source code for this tutorial is available on GitHub.

That’s it for now folks, hopefully this short walk through helped in understanding how we can configure the Authorization Server to issue JWT and how we can consume them in a Resource Server.

If you have any comment, question or enhancement please drop me a comment, I do not mind if you star the GitHub Repo too 🙂

Follow me on Twitter @tjoudeh

References

  • JSON Web Tokens Owin and Angularjs
  • Securing ASP.NET Web API endpoints – Using OWIN, OAuth 2.0 and Claims

Be Sociable, Share!

  • Tweet
  • Email
  • WhatsApp

Related Posts

  • Integrate Azure AD B2C with ASP.NET MVC Web App – Part 3
  • Secure ASP.NET Web API 2 using Azure AD B2C – Part 2
  • Azure Active Directory B2C Overview and Policies Management – Part 1
  • ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 – Part 5
  • ASP.NET Identity 2.1 Roles Based Authorization with ASP.NET Web API – Part 4

Filed Under: ASP.NET, ASP.Net Web API, Owin, RESTful API, Web API Security, Web API Tutorial Tagged With: ASP.NET, Autherization Server, JSON Web Tokens, JWT, OAuth, Resource Server, RESTful. Web API, Web API Security

Comments

  1. Cesar says

    October 6, 2016 at 3:43 am

    Hi. Thanks for the thorough article.
    I would like to know why making a CustomJwtFormat class instead of using JwtFormat from the nuget packages.

    Thanks.

    Reply
  2. K1 says

    October 12, 2016 at 6:23 pm

    Hi,

    I have implemented the whole thing and it works wonderfully, I have a question though.
    for each client I set its unique Base64Secret
    back in ResourceServer.Api in startup.cs in ConfigureOAuthyou have declared the audience and secret.
    now this is different for different request, Can you help out here.

    thanx

    Reply
    • Taiseer Joudeh says

      October 16, 2016 at 1:15 pm

      Hello K1,
      Can you please elaborate more? I didnt get your question.

      Reply
      • Xandrix Enrico says

        October 16, 2016 at 4:32 pm

        I think he’s saying that what if a new Audience is created, it will then have newly generated GUID value as audience, problem is the allowed audience is hardcoded in the startup.cs for [Authorize] attribute to controllers. I suggest making a custom [Authorize] attribute class handler for this.

        Reply
        • K1 says

          October 31, 2016 at 8:34 am

          Thanx man, exactly what I was trying to say 😀

          Reply
      • K1 says

        October 17, 2016 at 8:29 am

        Hi,

        I made a mistake, I was trying to set a secret key for each member who register. I realized the secret key is for each source, such as web api, web site …

        here’s another question, we are trying to test the following code

        $(document).ready(function () {
        $.ajax({
        url: ‘http://authz.novin.solutions/oauth2/token’,
        data: {
        ‘username’: ‘mrkeivan’,
        ‘password’: ‘09126101185’,
        ‘client_Id’: ‘ddaffb84-acf6-4aca-ac02-203a69a4d3ea’,
        ‘grant_type’: ‘password’
        },
        ‘headers’: {
        ‘cache-control’: ‘no-cache’,
        ‘content-type’: ‘application/x-www-form-urlencoded’
        },
        error: function () {
        alert(‘error’);
        },
        type: ‘POST’,
        dataType: ‘json’,
        success: function (data) {
        },
        });
        });

        But I get Access-Control-Allow-Origin error (for local host) how can I figure this out so I can call the method locally ?

        Reply
        • Sabrina Ahmed Khan says

          August 20, 2020 at 10:54 am

          You have to add a nugget package to enable CORS. I was having this error while implementing OWIN and resolved it by doing this.

          Reply
  3. sepehr says

    October 17, 2016 at 2:19 pm

    Hello sir ,
    I’d really really appreciate you Taiseer , you saved my life…
    I followed this tutorial and also that famous( (: ) 5 part tutorial too and this is OK.
    Let me ask you a question:
    Is it possible to consume APIs from another web api project (as client)?
    I always receive “Authorization has been denied for this request.” response when there are two web api projects.
    Thanks in advance for your reply

    Reply
    • Taiseer Joudeh says

      October 28, 2016 at 3:44 pm

      Yes you can do this for sure, but you need to do the correct authentication in your calling API (Client app) correctly in order to access the protected API.

      Reply
      • Donald Mafa says

        October 1, 2018 at 5:37 pm

        Please may you elaborate this part as I am getting the same message and not sure how to overcome this. I clone your repo and still get the same message

        Reply
      • Chandresh says

        December 12, 2019 at 9:17 pm

        Hello,

        Could I get some more explanation to fix this error ? I have read the article. I have both project running from same machine. I was able to verify the responses for authorization. Stuck at this error for api/protected api Authorization server.

        In the screenshot, you show Authorzation value for this GET api for Authorization. I just pulled it from my response of previous api to Authorization Server (using the symmetric key value as per above article)

        Reply
        • Chandresh says

          December 12, 2019 at 11:30 pm

          I take this back.. I was sending the GET request without Secret code (set in the source code).. I am sharing my comments here.

          When you use the jwt.io , you must change two values (I missed setting the Secret code first time)
          A) Use the symmatric key (099…..)
          B) Use the Secret Code from the existing source file – AudienceStore.cs
          IxrAjDoa2FqElO7IhrSrUJELhUckePEPVpaePlS_Xaw

          Let these two changes regenerate the input string in the left pane of jwt.io
          Copy this and put it into GET request in Postman

          Note – Using Postman,
          You must need to paste the generated string from jwt.io (left pane) as the value for the Bearer Token field inside Authorization tab in the Postman

          Reply
  4. Erick says

    October 18, 2016 at 8:27 am

    Hi Taiseer,

    Great tutorial. It works perfectly.

    Need some insights

    I want to ask Audience will be all ‘client’s that will consume my WebAPI right?
    Then how to authorize new Audience if since it is hardcoded (099153c2625149bc8ecb3e85e03f0022) in Audience Server?

    thx,
    erick

    Reply
    • SarSha says

      November 24, 2016 at 9:53 am

      The web api IS the audience.

      Reply
  5. Jawand Singh says

    October 19, 2016 at 1:01 pm

    Hello Taiseer,

    Thanks for nice and easy explanation and implementation. I have few questions.

    suppose i have multiple Resource Server’s and for each and every Resource Server(audience) i have clientId and Secret (Base64). But, now we have multiple Resource server (which mean multiple clientId and Secret). Now, in Resource Server API, How i am going to identify to which Resource Server (audience) this JWT Token Belong and use correct Secret (Base64) to de-serialize JWT Token. How Secret(Base64) should be shared ?

    Bottom Line, we want to implement it in Production Environment. What we need is to Host Authorization Server as a Separate Service on Azure. and Host Different Resource API on different azure app service. The main concern is how we can share the Secret (Base64) between Authorization Server and Resource Server.

    We are trying to implement custom authentication and authorization on azure app service. currently Microsoft Azure App Service only provide for (AD, Twitter, Google, Microsoft, Facebook).

    I hope my question is clear 🙂

    Thanks & Regards,
    Jawand Singh

    Reply
    • Jawand Singh says

      October 19, 2016 at 3:24 pm

      or should i send ClientId along with JWT Token ?

      and then on my Resource Server i will check in database with that clientId and Audience Name and get Secret from database ?

      Will it work ? is it secure way ?

      Thanks,
      Jawand Singh

      Reply
  6. K1 says

    October 31, 2016 at 8:32 am

    Dear Taiseer,
    I have implemented the code and it worked smoothless, thanx.
    on the web and using postmaster it works flawlessly however when calling on mobile appliation I get the following error
    XMLHttpRequest cannot load http://authz.novin.solutions/oauth2/token. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost’ is therefore not allowed access. The response had HTTP status code 400.

    i’m using cordova to develope the application.

    Reply
    • nicky says

      May 31, 2017 at 1:02 am

      Hi K1,

      I allow myself to answer (hoping you’ve solved it since the time), and that it could at least serve others.

      I’ve had the same issue in the beginning. Meaning, in my case, I did try to post the “login/passwor” as a formatted json payload. Wrong!

      The answer is to follow the exact steps and syntax provided by the author.

      The good way to do it (I am using javascript):
      Given your variables: userName and password:
      The request payload must be of type “string” as follows: “grant_type=password&userName=” + userName + “&password=” + password

      And Important! the headers must be of type: { “Content-Type”: “application/x-www-form-urlencoded” }

      Cheers

      Reply
  7. jack says

    November 9, 2016 at 9:01 pm

    hello what about if we want to generate an anonymous token

    Reply
    • Taiseer Joudeh says

      November 12, 2016 at 12:15 am

      Hi Jack,
      What is the need for Anonymous token? You could allow users to access the controller without having a token by adding the attribute [AllowAnonymous]

      Reply
  8. Salman says

    December 2, 2016 at 11:27 am

    Excellent. This is what I was looking for 🙂

    Reply
  9. Mateusz Migała says

    December 21, 2016 at 11:40 am

    Great articles! 🙂 Thanks a lot

    Reply
    • Taiseer Joudeh says

      December 23, 2016 at 2:18 am

      You are welcome, happy to help 🙂

      Reply
  10. Arun says

    December 23, 2016 at 11:41 pm

    Hi

    I have generated the JWT from Authorization server. My question is how to test the Resource server Protected controller in Postman

    Reply
  11. Arun says

    December 24, 2016 at 3:02 pm

    Hi

    Your article is excellent. I have one question for you. With the help of Postman I can generate Json Web Token from Authorization server. I dont know how to pass the generated token to Resource server to access it data.
    Can you please help me in sorting out my issue.

    Reply
    • suman says

      March 19, 2017 at 2:33 pm

      Hi Arun,

      have you found any way to pass the generated token to Resource server to access it data.

      Reply
      • suman says

        March 20, 2017 at 4:40 pm

        Got it..It is very helpful article.

        Reply
  12. Dmitry says

    December 29, 2016 at 4:35 am

    Hi. I did copy-paste with adding required namespaces, is it only for me this:
    var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);
    shows 2 errors:
    – The best overloaded method match for ‘System.IdentityModel.Tokens.Jwt.JwtSecurityToken.JwtSecurityToken(string, string, System.Collections.Generic.IEnumerable, System.DateTime?, System.DateTime?, Microsoft.IdentityModel.Tokens.SigningCredentials)’ has some invalid arguments
    – cannot convert from ‘Thinktecture.IdentityModel.Tokens.HmacSigningCredentials’ to ‘Microsoft.IdentityModel.Tokens.SigningCredentials’

    Reply
    • Alftuga says

      January 4, 2017 at 7:20 pm

      Great articles! 🙂 Thanks a lot!
      I have the same behavior as Dmitry.
      var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);

      Argument 6: cannot convert from ‘Thinktecture.IdentityModel.Tokens.HmacSigningCredentials’ to ‘Microsoft.IdentityModel.Tokens.SigningCredentials’

      Reply
      • Taiseer Joudeh says

        January 8, 2017 at 9:38 pm

        Hello Alftuga,
        This is regard a breaking compatibility with latest NuGet package you used, you can refer back to the version I used, make it work, then update your NuGet packages and fix the breaking compatibility issue. Sorry for not being more helpful But I do not have the time to check this issue.

        Reply
      • ben says

        February 14, 2017 at 4:33 am

        var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);

        //var signingKey = new HmacSigningCredentials(keyByteArray);
        var signingKey = new SigningCredentials(
        new SymmetricSecurityKey(keyByteArray),
        “http://www.w3.org/2001/04/xmldsig-more#hmac-sha256”);

        var issued = data.Properties.IssuedUtc;
        var expires = data.Properties.ExpiresUtc;

        var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);

        works with latest – you don’t need thinktecture anymore

        Reply
        • ben says

          February 14, 2017 at 5:01 am

          var signingKey = new SigningCredentials(
          new SymmetricSecurityKey(keyByteArray),
          “HS256”);

          Reply
          • Taiseer Joudeh says

            February 18, 2017 at 1:54 am

            Thanks for sharing this Ben, appreciate it.

  13. Ronnie says

    January 3, 2017 at 12:45 pm

    Hello Taiseer,

    Excellent articles/tutorials..!!!

    I’ve built an Auth and API Resource Server solution based on this tutorial and your ‘ASP.NET Identity 2.1 with ASP.NET Web API 2.2 (Accounts Management)’ series. Both work great..!!! Thanks again..!

    I built a 3rd Resource as an MVC Web Client to maintain the API Resource. This is where I’m having problems.

    – Both Resources (API and MVC) share the same client_id (Audience) and secret.

    – When using Fiddler, I can successfully request a JWT from the Auth Server, then pass it in the header and make a request to the MVC Resource’s controller actions with [Authorize].

    – But from the MVC Resource itself, via code, I can successfully get a JWT , but then I don’t know how/where to add it to each request (within the MVC Resource)

    I’m thinking somehow add in Startup.cs: if (token != null), add header ‘Authorization: bearer token’ but no success.
    Then I tried using JwtSecurityToken(token) method to decode and directly access the claims and use it in the AccountController’s SignIn().

    Any assistance in pointing me in the right direction, or if its even possible would be appreciated.

    Regards,
    Ronnie

    Reply
    • Ronnie says

      January 4, 2017 at 9:48 am

      Never mind, figured it out.
      Rather than directly using the JWT ClaimsIdentity in SignIn(), I had to parse it into new claims with naming structure ASP.NET Identity likes.

      eg: JWT claim for role type is named ‘role’, but ASP.NET Identity requires the type name to be ‘http://schemas.microsoft.com/ws/2008/06/identity/claims/role’

      Thanks again for the tutorial..!!!

      Reply
      • Taiseer Joudeh says

        January 8, 2017 at 9:35 pm

        You are welcome and sorry for the late reply. Happy to hear posts are useful 🙂

        Reply
    • Taiseer Joudeh says

      January 8, 2017 at 9:26 pm

      Hello Ronnie,

      I think you need to treat your MVC application as a client for the API and use HTTP services to get the token from AuthZ Server, store in a storage cookie and then send this token in the AuthZ header. Maybe this post will give you guide on how to achieve this.

      Reply
  14. Sarang K says

    February 2, 2017 at 9:35 am

    Hello Taiseer,

    Great articles.

    I have implemented JWT in my MVC 5 app & using it to authorise Web APIs that I have created for mobile apps.
    Now what I want to do is, one user should use one account on a single device at a time. That means if user tries to login into app in multiple devices, all previous login should expire. For this at every token request I want to expire all previous tokens of that user. But I didn’t get any help on web. Can you please help me in this?

    Reply
    • Taiseer Joudeh says

      February 14, 2017 at 1:24 am

      Sorry for the late reply, if you need to achieve this, you need to keep track of the device Id user logged from, so with each login for the same user, you can inspect the device id, if it is a new one, then you delete the refresh token for the previous device ids for this user, and you want for the access token to expire. So that means you should issue short lived access tokens, you will never be able to revoke a self-contained access token.

      Reply
  15. Domingo says

    February 4, 2017 at 12:23 pm

    Hi Taiseer,

    Now that the OWIN Authorization Server use JWT, is it necessary to still use “refresh_token” using the same steps mentioned from this post » https://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/?

    Reply
    • Taiseer Joudeh says

      February 14, 2017 at 1:20 am

      Hi,
      Refresh tokens should be used regardless the format of the access token if you need to keep users signed in and refresh the access token “silently” without requesting the user username/password

      Reply
  16. Maksym Pavlov says

    February 15, 2017 at 7:22 pm

    In this particular example, how would one add support for Refresh Tokens? Currently, the validity of the token is short-lived, while refresh tokens are not the part of the shown authorization server solution.

    Reply
  17. Andrey says

    February 18, 2017 at 6:07 pm

    Hi Taiseer,
    could you advise please what could be the reason of 404 errror when calling http://localhost:8000/oauth2/token?

    Reply
    • Taiseer Joudeh says

      March 5, 2017 at 2:56 am

      It is too late to answer now, I’m sorry…but I guess this would be in your Startup class where you configured the TokenEndpoint, check for trailing slashes.

      Reply
  18. Annie says

    March 9, 2017 at 1:33 am

    Hello, I loved this tutorial, but I have a problem, when a token is supposed to be expired is taken by Authorized anyways. ¿Can you help me?

    Reply
    • Taiseer Joudeh says

      March 11, 2017 at 12:52 am

      Hello Annie, could you please elaborate more? I didn’t get your question, apologies about this.

      Reply
  19. suman says

    March 20, 2017 at 5:12 am

    Hi,

    Nice article.

    Is there any way to pass the generated token to Resource server to access it data using postman

    Reply
    • suman says

      March 20, 2017 at 4:39 pm

      Got it..It is very helpful article.

      Reply
      • Ksmit says

        August 14, 2019 at 7:57 am

        Hi Suman! Please show us how.

        Reply
        • Ron says

          October 16, 2019 at 9:54 am

          In Postman, go to Authorization tab
          In the Type dropdown, select Bearer Token
          Then paste the token that you generated in the Token textbox

          Reply
  20. James White says

    March 23, 2017 at 6:39 pm

    Great walk-through, as an absolute noob in this space I found it easy to walk through the steps right up until the point where you actually request the resource. I’ll go track it down elsewhere but it would be awesome if you showed the Postman request/response to the resource server at the end.

    Reply
    • Taiseer Joudeh says

      April 8, 2017 at 6:38 pm

      Thanks James for you comment 🙂

      Reply
  21. Pierre Thalamy says

    May 22, 2017 at 12:46 pm

    Hi Taiseer,

    Your tutorial has been of great help setting up my backend infrastucture, thanks.

    However, there is one aspect of your implementation I am having problems with:

    When requesting a new access_token from your Authorization server through the Resource Owner Credentials grant flow, you are setting the `client_id` parameter to the audience id of the resource server. Shouldn’t `client_id` be a unique identifier relative to the CLIENT instead of the requested AUDIENCE?
    Let’s say I have two clients, a mobile application and a Javascript SPA, both targeting the same resource server. In your implementation it seems that I have no way to distinguish which of those clients are requesting a token from my autorisation server. It becomes problematic once refresh tokens are added, as I want to keep one in database for each user and client, not one for each user and audience.

    I hope my remark was stated clearly enough. Am I missing something?

    Reply
  22. nicky says

    May 31, 2017 at 1:13 am

    Hi Taiseer,

    First of all thanks for your precious work.

    I have a question on the topic: is it possible to minimize the claims included in the encoded token?
    Meaning: is it possible to exclude the user_id for instance?

    Thanks again

    Reply
    • Taiseer Joudeh says

      June 13, 2017 at 12:51 am

      Hi Nicky,
      The userId is the most important claim in the token, without it you will not be able to identify to whom this token belongs, right? For other claims you can remove them.

      Reply
  23. Thomas Moltzen-Bildsøe says

    May 31, 2017 at 11:43 am

    Hi Taiseer,

    Thanks for the great tutorial. It helped me alot.

    I have a question. I use the token in both MVC and Web API by storing the returned token in a cookie. For now I create the cookie in Javascript on the client.

    For security reasons I would like the JWT issuer to return the token as a HttpOnly cookie as opposed to json-payload. Is this possible, could you point me in the right direction?

    BR
    Thomas

    Reply
  24. Jason says

    June 1, 2017 at 8:27 pm

    The ads are making this site unreadable. Browser keeps jumping all over the place.

    Reply
    • Taiseer Joudeh says

      June 13, 2017 at 12:48 am

      Sorry to hear this, I’m planning to use on Google Ads and remove other providers. Again apologies about this.

      Reply
  25. Bruno Grillo says

    July 6, 2017 at 1:21 pm

    Hi Taiseer,

    Thanks for this post and all the serie about “Token Based Authentication using ASP.NET Web API 2, Owin, and Identity”. It has been very helpful to me.

    When trying to update some of the packages used in this tutorial I have encountered some problems, especially with a conflict of “System.IdentityModel” version when using “Microsoft.Owin.Security.Jwt”.

    To solve this, I have implemented the Unprotect method in a new “CustomJwtFormat” class to use for validation on the resource server. That way I use “UseOAuthBearerAuthentication” with “AccessTokenFormat = new CustomJwtFormat …” instead of “UseJwtBearerAuthentication” in the Startup.

    For validation with “System.IdentityModel.Tokens.Jwt” I have based on its own code (http://bit.ly/2tkrbeP) but simplifying it to cover the needs of this example (which are mine 🙂

    I removed “Thinktecture.IdentityModel.Tokens” and “Microsoft.Owin.Security.Jwt” because they are not longer necessary.

    I have commited the updated version with these changes here in case it can be useful for anyone:
    https://github.com/bcgrillo/JWTAspNetWebApi/commit/d10b4018d472bb7cb35bb20c658697e653d0ad56

    Of course, happy to receive any suggestions or comments.

    Once again, thank you very much for your blog. I keep reading you.

    Cheers

    Reply
    • Vitaliy says

      January 2, 2020 at 10:43 pm

      Hey Bruno,
      What if inside of your CustomJwtFormat.Unprotect() you would use JwtFormat.Uprotect().
      So instead of all that logic that you implemented, just delegate this to Microsoft’s version of Unpotect().
      Somewhat like this:

      public AuthenticationTicket Unprotect(string protectedText)
      {
      var key = ConfigurationManager.AppSettings[“jwtKey”]; ;
      byte[] keyBytes = Encoding.UTF8.GetBytes(key);
      var jwtFormat = new JwtFormat(
      “YOUR_AUDIENCE”,
      issuerCredentialProvider: new SymmetricKeyIssuerSecurityKeyProvider(_issuer, keyBytes));
      var ticket= jwtFormat.Unprotect(protectedText);
      return ticket;
      }

      Reply
  26. samoeun says

    July 18, 2017 at 10:10 am

    Great tutorial!
    It is really save me.
    I follow your tutorial it works fine in the same server even difference project but I have one problem with difference hosting. it show me just 401 unauthorized when access to resource service.

    Reply
  27. Karen says

    August 9, 2017 at 11:57 pm

    Hi Taiseer,
    Your tutorials are absolutely excellent!
    You mentioned that in a real world scenario, the Resource Server might need to regenerate the secret that is being used to sign the token.
    I would like to know more about this. Specifically, how does the resource server pick up this new secret?
    In your examples, the secret is read in at startup, using app.UseJwtBearerAuthentication().
    If the resource server got a new secret, how could it use that secret without restarting the server? Where/how would I update the secret that was initially set in UseJwtBearerAuthentication? Can that be called from anywhere in the application?
    Any help is appreciated!
    Thanks again for the wonderful tutorials – they have been a lifesaver!

    Reply
  28. Mike says

    August 29, 2017 at 7:13 pm

    Hi Taiseer,

    Good article and easy to follow. Just one question… can this be tested on Visual studio rather than postman?

    Kind Regards

    Mike

    Reply
  29. Aziz says

    August 31, 2017 at 11:55 am

    hi Taiser, the Migration thing is not working …as if EF not not installed.
    getting this: update-database -verbose
    update-database : The term ‘update-database’ is not recognized as the name of a cmdlet, function, script file, or
    …

    Reply
  30. Joe says

    September 19, 2017 at 6:46 am

    Hi Taiseer:

    I keep getting “message”: “Authorization has been denied for this request.”. Any ideas?

    I validated the token on the jwt.io website and I got no errors, i.e., it was validated. I can’t seem to figure out where to put a breakpoint that’ll actually get caught but so far I can’t even debug.

    Any thoughts?

    Reply
    • Joe says

      September 19, 2017 at 6:47 am

      Also I’m submitting the request as a POST. The issuer is the same as my website with the port, i.e., http://localhost:24236 .

      Reply
  31. samuel says

    October 5, 2017 at 1:36 pm

    Sir, what an perfect selfless article for lessser Mortals like me. God Bless you.
    Got exactly what I needed.

    Reply
  32. UrsusSoft says

    October 12, 2017 at 6:26 pm

    Great explanation! You saved my life 🙂 I wish you the very best of luck in your job.

    Reply
  33. Banh Cao Quyen says

    October 19, 2017 at 11:54 am

    Hello Sir,
    I got this issue when i try to access to api/protected with postman
    “Authorization has been denied for this request.”

    Reply
  34. Stalin says

    February 28, 2018 at 8:25 pm

    This is a great tutorial, thank you!
    I have a question, how can I set the TokendEndpointPath from a value of a database table?

    Reply
  35. mehdi says

    February 28, 2018 at 10:28 pm

    Hi Bro
    first thnx for your good tutorial really thnx
    I have question from u
    why allowedOrigin is always null ?
    var allowedOrigin = context.OwinContext.Get(“as:clientAllowedOrigin”);

    Reply
  36. RezaAb says

    March 6, 2018 at 7:22 pm

    How to use both of them together (identity and jwt) ?
    When logging in with jwt, I also log in to identity.

    Reply
  37. Mohan says

    March 15, 2018 at 11:14 am

    Hi, I got this issue when i try to access to api/protected with postman
    “Authorization has been denied for this request.”

    I was able to generate the token. I want to check whether the token is valid or not.

    How to check the token.

    Reply
  38. James says

    April 9, 2018 at 5:42 pm

    I implemented all this code, but then when I try to run it, nothing happens, to test if it is working, I just debug this and then do a post ?

    Reply
  39. Nazir says

    April 16, 2018 at 10:27 am

    Hi Taiseer,

    Thank you for the excellent post and series.

    Do you have any pointers on how I would go about sharing the auth with an MVC app?

    Currently it is using the built in identity auth but I would like for the mvc and web.api to share the same auth.

    Thank you so much

    Reply
  40. Nitin says

    February 8, 2019 at 10:12 pm

    Protect method from ExtendedJwtFormat never gets called. So I am getting only access token not JWT token. Please help.

    Reply
  41. Tabssum says

    April 1, 2019 at 1:23 pm

    Hello ,
    i want to apply same logic in .net core,i already convert all files in .net core but when we configur in startup.cs file here you used OWIN IAppBuilder for app.UseOAuthAuthorizationServer(OAuthServerOptions); so in .net core we have IApplicationBuilder so how can i achieve this.

    Please help.

    Reply
  42. Tabssum says

    April 1, 2019 at 1:35 pm

    Hello ,
    I tried to write above application in .net core 2.2,
    I am facing problem in Startup.cs class where below highlighted line is not working for me.

    IAppBuilder is from “using Owin;” and IApplicationBuilder is from Microsoft.AspNetCore.Builder ,so how can i achieve in .net core

    public void ConfigureOAuth(IAppBuilder app)
    {

    OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
    //For Dev enviroment only (on production should be AllowInsecureHttp = false)
    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString(“/oauth2/token”),//new PathString(configurationmanager.appsetting[“as:token”] ==>/arcontoken
    AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
    Provider = new CustomOAuthProvider(),
    AccessTokenFormat = new CustomJwtFormat(“http://jwtauthzsrv.azurewebsites.net”)
    //refreshtokenprovider=new cudtomrefreshtokenprovider
    };

    // OAuth 2.0 Bearer Access Token Generation
    app.UseOAuthAuthorizationServer(OAuthServerOptions);

    }

    Reply
  43. rajwin says

    September 10, 2019 at 11:23 am

    First of all thanks for such a great article(Article:JSON Web Token in ASP.NET Web API 2 using Owin) about Authentication and Authorization.

    I have some doubt about Authorization server and Resource server used in your article, which i have listed below.

    1. When issuing JSON token,in payload claims for “aud” you are passing generated id ,why it is not resource server name.
    (Article:JSON Web Token in ASP.NET Web API 2 using Owin)

    2. Whether AudienceModel class ‘Name’ and Audience class ‘Name’ both are same.(Article:JSON Web Token in ASP.NET Web API 2 using Owin)

    3. If JWT debugger tool is allowed then u easily decode jwt token and get information ,so where goes security and again jwt is insecure?
    (Article:JSON Web Token in ASP.NET Web API 2 using Owin)

    4. Whether jwt generated from here can be used both in asp.net mvc projects and also for angular 2+ projects?

    5. As per your article (i.e Decoupling authorization server from resource server).Whether Authorization server and resource server are in same machine.For eg:- if my server is IIS, then you mean to say that IIS Server can be called as Authrorization Server and also Resource Server.Is it True?

    Eagerly waiting for your Positive reply

    Thanks
    rajwin

    Reply
  44. Jayakumar Vinayagam says

    September 13, 2019 at 10:47 pm

    am able to get this done, much appreciated.
    client request the token then server proceed the sequence of steps to validate the client posted value and finally share token.

    I validate the token for authorized resource, in mean-time where my generated token stored either in server(iis) storage or application in-memory?

    Reply
  45. Madhuri says

    October 1, 2019 at 1:54 pm

    Is there any way to create refresh tokens as lengthy as access tokens?

    Reply
  46. giles says

    November 29, 2019 at 8:42 pm

    would be good to make clear the importance of unique_name – this is where the owin middle where picks for use identity

    Reply
    • giles says

      November 30, 2019 at 2:04 pm

      where = ware

      user = user

      Reply
  47. Vitaliy says

    January 2, 2020 at 12:08 am

    What abt implementing of
    public AuthenticationTicket Unprotect(string protectedText)
    {
    throw new NotImplementedException();
    }

    This method is called when resource method invoked..

    Reply
  48. Vitaliy says

    January 3, 2020 at 12:11 am

    Hi Taiseer,
    In UseJwtBearerAuthentication middleware you have hardcoded audience… but when you create token, you do lookup for audience.
    In real life they must match, right, otherwise authorization fail…?

    Reply
  49. Rukshan says

    February 12, 2020 at 9:00 am

    Hello taiseer ! how can we add a refresh token when the token expires in this code that you have provided? Assuming that it is the most important topic

    Reply
  50. WALEED says

    May 26, 2020 at 2:50 pm

    thank you

    Reply
  51. Mario says

    August 17, 2020 at 10:23 pm

    Hi, I updated your code to run on latest versions of owin selft host weapi, I removed the dependency to Thinktecture, I beleive it was replaced by Microsoft.IdentityModel.JsonWebTokens or Microsoft.IdentityModel.Tokens and changed only 2 parts in the code to make it work:

    https://github.com/tjoudeh/AspNetIdentity.WebApi/blob/master/AspNetIdentity.WebApi/Providers/CustomJwtFormat.cs

    public class CustomJwtFormat : ISecureDataFormat
    {
    …
    public string Protect(AuthenticationTicket data)
    {
    if (data == null) throw new ArgumentNullException(“data”);

    var keyByteArray = TextEncodings.Base64Url.Decode(SymmetricKeyAsBase64);
    var securityKey = new Microsoft.IdentityModel.Tokens.SymmetricSecurityKey(keyByteArray);
    var signingCredentials = new Microsoft.IdentityModel.Tokens.SigningCredentials(securityKey, System.IdentityModel.Tokens.SecurityAlgorithms.HmacSha256Signature);
    var token = new System.IdentityModel.Tokens.Jwt.JwtSecurityToken(Issuer, AudienceId, data.Identity.Claims, data.Properties.IssuedUtc.Value.UtcDateTime, data.Properties.ExpiresUtc.Value.UtcDateTime, signingCredentials);
    var handler = new System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler();
    return handler.WriteToken(token);
    }
    …
    }

    and had to add a “nameid” claim to the users on creation cause the new package didn’t add it in that property:

    var claim = new Claim(“nameid”, appUser.Id);
    var addClaimResult = userManager.AddClaimAsync(appUser.Id, claim).Result;

    Reply
  52. Mario says

    August 17, 2020 at 10:27 pm

    I didn’t had to change anything in the angular side but I will migrate to Blazor asap

    Reply
« Older Comments

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About Taiseer

Husband, Father, Consultant @ MSFT, Life Time Learner... Read More…

Buy me a coffeeBuy me a coffee

Recent Posts

  • Integrate Azure AD B2C with ASP.NET MVC Web App – Part 3
  • Secure ASP.NET Web API 2 using Azure AD B2C – Part 2
  • Azure Active Directory B2C Overview and Policies Management – Part 1
  • ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 – Part 5
  • ASP.NET Identity 2.1 Roles Based Authorization with ASP.NET Web API – Part 4

Blog Archives

Recent Posts

  • Integrate Azure AD B2C with ASP.NET MVC Web App – Part 3
  • Secure ASP.NET Web API 2 using Azure AD B2C – Part 2
  • Azure Active Directory B2C Overview and Policies Management – Part 1
  • ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 – Part 5
  • ASP.NET Identity 2.1 Roles Based Authorization with ASP.NET Web API – Part 4

Tags

AJAX AngularJS API API Versioning ASP.NET Authentication Autherization Server Azure Active Directory B2C Azure AD B2C basic authentication C# CacheCow Client Side Templating Code First Dependency Injection Entity Framework ETag Foursquare API HTTP Caching HTTP Verbs IMDB API IoC Javascript jQuery JSON JSON Web Tokens JWT Model Factory Ninject OAuth OData Pagination Resources Association Resource Server REST RESTful Single Page Applications SPA Token Authentication Tutorial Web API Web API 2 Web API Security Web Service wordpress.com

Search

Copyright © 2021 · eleven40 Pro Theme on Genesis Framework · WordPress · Log in

loading Cancel
Post was not sent - check your email addresses!
Email check failed, please try again
Sorry, your blog cannot share posts by email.