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 341 Comments

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:

JavaScript
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:

MS DOS
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

C#
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:

JavaScript
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:

C#
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:

C#
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:

C#
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

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. Joy says

    October 27, 2014 at 1:46 pm

    Nice article.

    Thanks Taiseer!

    Reply
    • Taiseer Joudeh says

      October 29, 2014 at 12:52 am

      You welcome Joy, glad you liked it 🙂

      Reply
  2. David Spenard says

    October 27, 2014 at 6:21 pm

    Excellent article! Very good follow-up to the article on Token Based Authentication using ASP.NET Web API 2, Owin, and Identity. I’m actually using Ember and not Angular, but your examples across a few of your articles provided enough information for me to implement simple authentication in an Ember app.

    Reply
    • Taiseer Joudeh says

      October 27, 2014 at 6:41 pm

      Hello David, glad you liked the post and the previous series, thanks for taking the time to read it and comment.

      Reply
  3. Robert E. Maurer says

    October 28, 2014 at 5:19 am

    Taiseer,

    Wow, you just keep plowing along! Thanks for the updated post. I like the idea of using JWT instead of the shared machien keys. Can this be combined with your other 5 posts so that I have a Token based authentication that supports external authentication? It would be nice if you extended your 5 part series and added JWT to that.

    Bob

    Reply
  4. abatishchev says

    October 29, 2014 at 3:57 am

    Hi Taiseer,
    I try to validate a JWT produced by Auth0 (https://auth0.com/) and constantly receive 401 error.
    The same for JWT produced by Google OAuth 2.0 Playground (https://developers.google.com/oauthplayground)
    What instruments are available to diagnose the problem?
    Thanks!

    Reply
    • Taiseer Joudeh says

      October 29, 2014 at 11:51 pm

      Hi, what do you mean by validate? to decode it and see the claims inside it? If this is the case I’ll use http://jwt.io. As well you need to know what is the signing algorithm used to sign this token.
      Hope this answers your question.

      Reply
      • abatishchev says

        October 31, 2014 at 6:51 am

        Thanks! Jwt.io is definitely a good tool. I googled for “jwt validate online” and found some more.
        Regarding my problem I just needed to read and debug more 🙂

        Reply
  5. Maraues says

    October 30, 2014 at 7:08 pm

    Hey Taiseer,
    First of all, thanks for this amazing tutorial.
    Is it possible to get a JWT token from a ExternalLogin provider ? Can you please point me a direction in order to achieve this goal ?

    Thanks!

    Reply
    • Taiseer Joudeh says

      October 31, 2014 at 1:22 am

      Hi Maraues,
      Well it depends on the external provider access token format, you can’t control this for sure. For example FB access token format is not JWT and you have no control on this.

      Reply
      • Maraues says

        October 31, 2014 at 5:34 pm

        Thanks for your answer Taiseer!
        I follow your tutorial, but instead of doing it from scratch I started using the WebApi template. So the tokens retrieved from the CustomProvider works just fine. But after the implementation of JWT, the ExternalLogin Endpoint stops working, and allways retrieve 404 response. Is this related to the JWT ?

        Once more, thanks a lot for your amazing articles

        Reply
      • Maraues says

        October 31, 2014 at 7:58 pm

        Let me explain my question a litle better.In the OAuthAuthorizationServer i’m using a provider for issue tokens and set its format as JWT (like your explanation) , and i also set the AuthorizeEndPointPath to handle ExternalLogins. So my provider Options are:
        OAuthOptions = new OAuthAuthorizationServerOptions
        {
        AllowInsecureHttp = true,
        TokenEndpointPath = new PathString(“/oauth2/token”),
        AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
        Provider = new CustomOAuthProvider(),
        AccessTokenFormat = new CustomJwtFormat(“Teste”),
        AuthorizeEndpointPath = new PathString(“/api/Account/ExternalLogin”),
        };

        This means that when I request an external token, it will try to set a jwt format for the external token , and this will fail.

        So is it possible to exclude the JWT format only for external login tokens ?

        Reply
        • Taiseer Joudeh says

          October 31, 2014 at 9:04 pm

          This is the same case I faced when I used the default Web API template, I recommend you to read this post where I implement the external authentication in different way.
          I do not think that JWT has anything to do with the AuthorizationEndPoint and receiving 404, try to return it to default access token format and you might receive the same issue.
          Sorry if I was not able to fully help you here, if you find something it will be great to share it with the readers here.

          Reply
          • Maraues says

            November 3, 2014 at 1:38 pm

            In fact, i´m considering now to implement the Authorization Server without External Login functionality. This will be handled directly on Ressource Servers, so i’m leaving the Authorization Server only with user accounts and jwt tokens management. Do you agree with this aproach ?

          • Taiseer Joudeh says

            November 3, 2014 at 1:42 pm

            Well, the AuthZ server should be your only server for managing authentication and authorization, the Resource servers should rely on it and not be responsible for external logins. So…my recommendation is not to go with approach. As i told you you can check this post which shows how to use external logins and you can use JWT on same time.

  6. Jogchem says

    November 7, 2014 at 12:19 pm

    Thanks for the excellent tutorials and the detailed information in each one of them (and in the comments!). I was wondering, is it possible to combine the Auth and Resource servers? Or is there a specific reason to split them?
    And what about refresh tokens? Do we need them? What happens when a ticket is expired?

    Reply
    • Taiseer Joudeh says

      November 8, 2014 at 7:54 am

      Thanks for reading the articles and taking the time to comment 🙂
      Well I’ve answered all your questions on different parts of the posts.
      For combining AuthZ and Res. server, yes you can do this for sure, nothing forces you to separate them, read the into for this post again carfeuly.
      For refresh tokens please read this again because all have been answered carefully. Refresh tokens are not mandatory but they are good to keep user logged in without issuing a very long lived non revocable access token.

      Reply
      • Jogchem says

        November 8, 2014 at 10:27 am

        In the end, that was exactly what I did. I mixed everything from the articles into one. According to the JWT specification, we should use the access token to request a new refresh token and that is how I’ve implemented it now. Thanks again!

        Reply
        • Chris says

          February 2, 2015 at 7:22 pm

          I’d love to see a sample project that implements both OAuth 2 Refresh Tokens and JWT. I have an implementation of the Refresh Token base on your post about it and now I would like to add in support for JWT. I’d love to see a post for how to modify that code with the existing Client entity to use JWT.

          Reply
          • Taiseer Joudeh says

            February 3, 2015 at 12:47 pm

            Hi Chris, I’m working on this on a different project, hopefully if all is good I will share this with you.

          • forcewill says

            February 9, 2015 at 1:24 pm

            Taiseer have you finished that project i would like to have a look also :p
            Btw greate series of tutorials

          • Sudhir says

            February 18, 2015 at 5:00 am

            Hi Taiseer,

            A big thanks for saving days of research on Token based app authentication using basic token, refresh token and now JWT. Initially, I spent almost two weeks looking for the right article to explain how to’s before came across your posts. Feeling blessed now. 🙂 Thank you!

            Could you please advise if project that implements both Refresh Tokens and JWT is available for learning purpose? Meantime, I will try to merge your two separate posts and make sense out of it.

            Will hugely appreciate a working example by you to make sure I and other people like me on the right path.

            Awaiting your favourable reply.

            Many thanks

            Sudhir

          • E. Timothy Uy says

            March 17, 2015 at 5:05 pm

            I am also interested in how the Refresh Token would work with JWT in this tutorial.

          • cdev says

            March 20, 2015 at 4:37 pm

            I am also interested in how to make refresh token work with JWT. I assume , all mobile devices can handle jwt without any issues ?

  7. Kent Fehribach says

    November 11, 2014 at 12:19 am

    Great job Taiseer, your posts have been very helpful as we get up to speed on this stuff.

    I do have a question. Can you give the explanation on the reasoning for using the approach of using the JwtBearerAuthenticationOptions implementation of verifying the JWT tokens versus implementing it in the Unprotect in the CustomJwtFormat class? It seems a little disjoint and just opposite of what Microsoft did of implementing the Unprotect and not the protect.

    Thanks.

    Reply
    • Taiseer Joudeh says

      November 11, 2014 at 6:58 am

      Hi Kent, glad it was useful.
      I’m not sure if I understood your question 100% but I will try to answer it.
      MS doesn’t have ready made class which helps you to create JWT tokens out of the box, so I need to create my own “CustomJwtFormat” and implement the Protect method and use it in the Authorization server.
      On the other hand, and on the Resource server, MS has out of the box implementation for the Unprotect method in class (JwtBearerAuthenticationOptions) which is responsible to Unprotect the JWT token and check the validity of the signature. So there is no need to re-implement this. If this class was not available you will see that I’ll be writing the concrete implementation for the Unprotect method. You can check the source code of the Unprotect method here.
      Hope this answers your question.

      Reply
      • Sotheayuth says

        May 3, 2015 at 11:24 pm

        HI Taiseer,

        Using the Unprotect() of the Microsoft.Owin.Jwt.JwtFormat that you pointed out, I implemented the Unprotect() under my CustomJwtFormat class.
        Unfortuntely the error expection was thrown while extracting the Token/protectedText using the Unprotect() of JwtFormat.

        This is what the error says:
        > Audience validation failed. Audiences: ‘8b7cf74424034fb180c902d090ca556a’. Did not match: validationParameters.ValidAudience: ‘http://khict.com’ or validationParameters.ValidAudiences: ‘null'”

        Could you please advise what possible to resolve this error?

        Thanks in Advance!

        ======================================================
        == My Unprotect() function in CustomJwtFormat class
        ======================================================

        public AuthenticationTicket Unprotect(string protectedText)
        {

        //throw new NotImplementedException();

        string issuer = “http://khict.com”;
        string clientId = “8b7cf74424034fb180c902d090ca556a”;
        var secret = TextEncodings.Base64Url.Decode(“OikD2sWtM0gZQGjONy3e9zkdRpbSvbVDhkd3tql4mZ8”);

        IIssuerSecurityTokenProvider iis = new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret);

        var jf = new JwtFormat(issuer, iis);

        //Error Thrown here
        var result = jf.Unprotect(protectedText);

        return result;

        }

        ======================================================
        == Error Exception thrown
        ======================================================

        {
        “Message”: “An error has occurred.”,
        “ExceptionMessage”: “IDX10214: Audience validation failed. Audiences: ‘8b7cf74424034fb180c902d090ca556a’. Did not match: validationParameters.ValidAudience: ‘http://khict.com’ or validationParameters.ValidAudiences: ‘null'”,
        “ExceptionType”: “System.IdentityModel.Tokens.SecurityTokenInvalidAudienceException”,
        “StackTrace”: ” at System.IdentityModel.Tokens.Validators.ValidateAudience(IEnumerable1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)\r\n at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateAudience(IEnumerable1 audiences, SecurityToken securityToken, TokenValidationParameters validationParameters)\r\n at System.IdentityModel.Tokens.JwtSecurityTokenHandler.ValidateToken(String securityToken, TokenValidationParameters validationParameters, SecurityToken& validatedToken)\r\n at Microsoft.Owin.Security.Jwt.JwtFormat.Unprotect(String protectedText)\r\n at GeneralPOS.Formats.CustomJwtFormat.Unprotect(String protectedText) in z:\\Vichou\\developments\\khictposserver\\GeneralPOS\\POSServer-JWT-Bearer-Token-Authorizer\\Formats\\CustomJwtFormat.cs:line 82\r\n at GeneralPOS.ApiAuthorizeAttribute.IsAuthorized(HttpActionContext actionContext) in z:\\Vichou\\developments\\khictposserver\\GeneralPOS\\POSServer-JWT-Bearer-Token-Authorizer\\Auth.cs:line 65\r\n at System.Web.Http.AuthorizeAttribute.OnAuthorization(HttpActionContext actionContext)\r\n at GeneralPOS.ApiAuthorizeAttribute.OnAuthorization(HttpActionContext actionContext) in z:\\Vichou\\developments\\khictposserver\\GeneralPOS\\POSServer-JWT-Bearer-Token-Authorizer\\Auth.cs:line 51\r\n at System.Web.Http.Filters.AuthorizationFilterAttribute.OnAuthorizationAsync(HttpActionContext actionContext, CancellationToken cancellationToken)\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n at System.Web.Http.Filters.AuthorizationFilterAttribute.d__2.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\r\n at System.Web.Http.Controllers.AuthenticationFilterResult.d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()”
        }

        Reply
  8. Sandeep Karnik says

    November 20, 2014 at 5:32 am

    Hi Taiseer, Thanks for the great article. I have been following this series and they have helped me learn many concepts. On this article though I have some basic confusion, would appreciate if you can take some time to answer:

    We have three concepts – Auth Server, Resource server and the (real) client. Based upon your previous post, I understand that the client will first get the auth token from Auth Server (after providing client and user credentials) and then supply that token for future requests to Resource server. There may not be direct communication between Auth server and Resource server if we are using JWTs.

    In this article, resource server seems to be acting like a client, providing its id and secret to auth server. How does a true client (e.g. Android App) fit in here? Once we bring in this android app in picture how do we make sure:

    1. The token created by auth server works only for the resource server (there’s no communication between the two) and also created after validating the client id of android app.
    2. The resource server can validate the JWT token (created by our auth server and mean only for this resource server etc) that it receives from the android app on subsequent requests.

    Thanks in advance,
    Sandeep

    Reply
    • Matthew Paul says

      November 21, 2014 at 12:11 am

      I’m similarly confused. Is the client application responsible for passing the audienceId of the resource server? In which case, does this setup support one auth server and multiple resource servers? Should all resource servers beconfigured with the same audience id so they can respond to this token?

      Reply
      • Taiseer Joudeh says

        November 22, 2014 at 10:34 am

        Resource servers should register with the Auth server and obtain unique clientid/secret. If you give them the same clientId/secret then you an consider them one resource server.

        Reply
        • Matthew Paul says

          November 24, 2014 at 8:41 pm

          So:

          Client (in my case your ngAuthApp from earlier articles)

          Resource Server A (registered with my auth server as audience A)

          Resource Server B (registered with my auth server as audience B)

          I want the client to send their credentials to the auth server and get back a token. This token needs to give my client access to resources on the two audiences A and B. I can make my auth server issue a ticket that gives access to a single audience/resource server.

          Where I’m confused is the ‘Protect(AuthenticationTicket data)’ in CustomJwtFormat.cs creates a token with a single audience id. So as far as I can tell this token couldn’t give you access to multiple resource servers? The JwtSecurityToken class has a ‘public IEnumerable Audiences { get; }’ property but not a clear way of setting it. Can you give any pointers as to how this set-up might work with multiple resource servers?

          By the way, thank you for this excellent series! I’ve followed it all the way up to this point, and now have got a bit bamboozled!

          Reply
          • Taiseer Joudeh says

            November 25, 2014 at 8:38 am

            Hi Matthew,
            With my current implementation the token is issued for only one Audience, so in you case and if you want to separate your audiences for design reason you might give them the same clientid and secret, this will work fine for sure.
            Regarding the IEnumerable Audiences { get; } property I recommend you to check the source code for this middleware on github, currently I’ve no answer on how you can use it.
            Hope this answers your question.

    • Taiseer Joudeh says

      November 22, 2014 at 10:29 am

      Hi Sandeep,
      You can’t store secret on your Android App, it is non-confidential client, so in your case the image here represents your situation.
      Your resource server will store the clientId/secret which is received from Auth server so it can use it to validate that token is issued from trusted Auth server. You client application (android) is responsible to just ask the token from Auth server and pass it to the resource server, no validation for token should be done on the android app. Hope this answers your question.

      Reply
      • Sandeep Karnik says

        November 23, 2014 at 6:33 pm

        Hi Taiseer, thanks for reply.

        My question was more related to what change would the architecture in this article undergo if a real client (such as an android app for example) is brought into picture.

        Reply
        • Taiseer Joudeh says

          November 23, 2014 at 6:44 pm

          Hi Sandeep,
          There should be no change and your Android App should act like AngularJS app (Both are non-confidential clients). I believe there are few users who posted comments here telling me that they were able to integrate Android App with the current setup successfully, even including the external providers logins.
          If you have specific question or you are suspicious that something will not work when you try to build Android app and integrate with the API; then please let me know, always happy to help.

          Reply
          • Sandeep Karnik says

            December 3, 2014 at 7:00 am

            Thanks Taiseer for reply and much appreciate your help.

      • Phil Hadley says

        July 26, 2015 at 4:55 pm

        This is the best resource on securing Web APIs that I have found. Thanks for your efforts! A quick question to verify my understanding, if you please:

        When a resource server receives a request with a JWT from a non-confidential client (such as a mobile app), will the resource server need to communicate directly with the auth server which issued the JWT in order to validate the token? Or, can the resource server validate the JWT programmatically (by itself) by using the client secret that was issued to it by the auth server?

        Reply
        • Taiseer Joudeh says

          July 27, 2015 at 4:17 am

          Hi Phil, glad to hear that post is useful:)
          Basically the resource server will be able to validate the JWT based on the client secret issued by the AuthZ server, there is no need to communicate with the AuthZ server to validate a JWT token.
          Hope this answers your question.

          Reply
          • Phil Hadley says

            July 27, 2015 at 7:41 pm

            Thanks Taiseer. Yes, this answers my question perfectly.

            It occurs to me that the contents and validation of the JWT could be a proprietary (custom) implementation, provided that each supported resource server implemented the JWT validation algorithm in the same way. Am I characterizing this accurately?

  9. Robert E. Maurer says

    November 27, 2014 at 5:33 am

    Hello Taiseer,

    Again, excellent article. I am just a little bit confused. I followed your five part tutorial and I have have an authorization server and a resource server that are decoupled and using the same machine key. And, since I followed your tutorial, it supports a native login with refresh tokens as well as external facebook and google authentication.

    Unfortunately for me, this article started fresh instead of continuing from post number 4 or from post number 5. If I merge the changes you have outlined in this post into my existing authorization and resource servers, can I still support all of the features, native login with refresh tokens and external authoritzation?

    I have a few specific questions:
    1. From the first four posts I have a ClientId table that was being used to hold the external clients, which are the web and mobile applications. And, now I also have an audience table. Do those represent the same enttiy? Can they be combined?
    2. My SimpleRefreshTokenProvider is throwing an error since there is no as:client_id in the context.ticket.properties.dictionary. I think I should just return null in this situation?

    But, the more I think about this, it seems like I am no longer authenticating with an external id but with a client id.

    Bob

    Reply
    • Taiseer Joudeh says

      November 29, 2014 at 12:04 am

      Hi Bob,
      Apologies for the late reply, well the idea for this post was to find another way to decouple AuthZ server from resource server without unifying the machineKeys, so the use of JWT is suitable here, and yes you should be able to use refresh tokens along with external providers with JWT, we are only changing the format of the access token.
      Regarding your first question, the clients are piece of software used to to communicate with both your AuthZ server to get tokens from and Recourse server (Audience) to get data from, so the audience is different entity and usually it represents server side component (Web API) which relies on AuthZ server to protect it.
      For the second question I need to check it but with little re-factoring you can handle this, I do not have clear answer now.
      Hope this answers your questions and let me know if you need further help.

      Reply
  10. brettspurrier says

    December 1, 2014 at 6:16 am

    This is a great tutorial. I’m running into an issue when trying to expand it though.

    I would like to have multiple audiences be able to access the resource server. So in ConfigureOAuth() of startup.cs (of the resource server), I see that app.UseJwtBearerAuthentication() .AllowedAudiences property and .IssuerSecurityTokenProviders property are arrays, so I can easily pass in an array of my multiple audiences names[] and SymmetricKeyIssuerSecurityTokenProvider[].

    However, since ConfigureOAuth() is only run when the server starts, I’m not sure how to add/remove audiences from the allowed audiences of the app. Is there any way to do this? Are there any resources you could point me to?

    Many thanks, and again, this is a fantastic tutorial!

    Cheers,
    Brett

    Reply
    • Taiseer Joudeh says

      December 1, 2014 at 9:24 pm

      Brett, thanks for your comment, I do not have answer right now but I’ll check it the use for those arrays and get back to you if I have an answer.

      Reply
      • brettspurrier says

        December 1, 2014 at 9:41 pm

        Hi Taiseer,

        Just following up with a little code. This code is working and allows JWTs to be authenticated against multiple audiences:
        https://gist.github.com/brspurri/9dfeed196f5bf539189c

        But the question remains, is it possible to dynamically append audiences? Restarting the server after adding new audiences works of course – because ConfigureOAuth() is rerun, but I’d like to avoid a forced restart.

        Thanks again! Your tutorials are some of the best I’ve read!
        Brett

        Reply
      • Dave says

        December 16, 2014 at 10:07 pm

        Hi Taiseer,
        Excellent article! I’m actually having the same problem that Brett is having, regarding audiences being bound to a database and when it changes I’m having to restart the app pool. Any update on this?

        Thanks!
        Dave

        Reply
  11. David Phan says

    December 19, 2014 at 7:30 am

    Thanks Taiseer about this greate article!
    I wonder how can we extend TokenExpiration when client call/access to resource server, and should we do that, is it best practice?

    Reply
    • Taiseer Joudeh says

      December 19, 2014 at 8:31 pm

      Hi David, thanks for you comment.
      Sorry I din’t get your question, what do you mean by extending the TokenExpiration property? The only property you can use to set the token expiry time is “AccessTokenExpireTimeSpan” and this is set on the AuthZ server not on the resource server. If you are referring to something else please let me know.

      Reply
  12. Rod Runnheim says

    December 20, 2014 at 12:58 am

    Can you show an example of issuing a request with the acquired jwt? How do I structure the REST request to hit the Resource server (where does the JWT go?) Something like the POST examples you have above would be great!

    Reply
    • Taiseer Joudeh says

      December 20, 2014 at 5:49 pm

      Hi Rod,
      It is exactly like the default access token format, you need to send the JWT in the Authorization header of your request using Bearer scheme, the header will be something like this: [Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1bmlx…….]
      Hope this answers your question.

      Reply
  13. Rodrigo says

    January 3, 2015 at 6:14 pm

    Hello! Great arcticles! I’m following carefully all of them so I can understand better those mechanisms. There’s a lot of things here that I’ve never used (and some even heard) before.

    I would like to ask you onething: I’m trying to create an api to receive calls only from my application. They’ll be hosted on the same domain. Following your example, I didn’t enable CORS. And when sending the “Access-Control-Allow-Origin” header, I send only my application domain.

    But still, anyone would be able to issue a request against “oauth2/token” and check if a certain username and password matches (ie, brute-force), is that correct? Or by having CORS disabled that wouldn’t be a problem?

    I’m testing this with Postman sending “Origin” header with “http://foo.example/” and I’m still able to request the token generation endpoint. Sure, I’m testing this locally only so far. But should this work? Should I be checking “manually” the header “Access-Control-Allow-Origin” against a string with my domain?

    As I said, many things here are new to me, so, could you please point out how can I test this?

    And furthermore, would you say that the JWT way is the better approach on this case?

    Thanks in advance! I look forward more posts!

    Reply
    • Taiseer Joudeh says

      January 4, 2015 at 1:47 pm

      Hi Rodrigo, glad to hear that posts are useful.
      Well if your API is hosted withing your Front end application, I assume that it is an application will be running in a browser, then you do not need to enable CORS for sure. As well you shouldn’t send any extra headers such as “Access-Control-Allow-Origin” with your request.
      Keep in your mind that same origin policy and CORS are only applicable on browsers, if you are calling from PostMan, native application, or exe, then there is no CORS involved at all.
      JWT is more standard especially if your one of your resource servers is not built using .NET, maybe Node.js then tokens using JWT format can work between different server platforms.
      Hope this answers you questions.

      Reply
  14. vinnitsky says

    January 3, 2015 at 11:26 pm

    is it possible to use JWT in vNext project? For instance I can’t add references to Microsoft.Owin.Security.Jwt to ResourceProject

    Reply
    • Taiseer Joudeh says

      January 4, 2015 at 10:31 am

      As far as I know, currently you can’t because this middleware has not been ported to ASP.NET 5 yet, you can check this issue here

      Reply
    • Nguyễn Quý Hy says

      July 22, 2015 at 5:35 am

      I believe you can create a resource server that understands JWT with vnext. Just add the middleware app.UseOAuthBearerAuthentication(…). Not sure about Authentication server though.

      Reply
  15. Matt Demler says

    January 6, 2015 at 5:05 am

    Amazing set of tutorials Taiseer!
    I have a quick question:

    In your previous tutorial with separating the resource server and auth server you used the existing project from earlier tutorials. (refresh tokens, access tokens, etc) With this tutorial being stand alone, I’m not sure if the JWT, that is used to secure the APIs, also replaces the refresh token and access token formats? Or does all that still stay the same and the JWT is JUST used to secure the API infrastructure?

    Any clarification would be great! 🙂

    Reply
    • Taiseer Joudeh says

      January 6, 2015 at 9:52 am

      Hi Matt,
      Glad to hear that posts were useful for you. Well the JWT will be used as new format for the access token only, the refresh token identifier which you send to the user will remain the same, it will stay the as Guid.
      As well the ProtectedTicket stored in table RefreshTokens will not be affected too, so the only one changed is the access token format.
      Hope this answers your question.

      Reply
      • Matt Demler says

        January 6, 2015 at 10:38 pm

        Thanks Taiseer.
        Would you recommend using JSON Web Encryption then? Or is that overkill for this solution? (using your previous tutorials for reference)

        Reply
        • Taiseer Joudeh says

          January 8, 2015 at 10:27 am

          Hi Matt, are you going to encode any sensitive information in your JWT or just set of claims? If there is sensitive information then consider encryption, but you need to mange decryption on client too. Usually JWT should not contain sensitive information such as CC number or Social security numbers, etc…

          Reply
          • Matt Demler says

            January 8, 2015 at 2:10 pm

            It will just contain claims and a userid… any sensitive data will be retrieved from subsequent calls to the resource server. So encryption will probably be too much.
            The audience entity in this tutorial… does that replace much of the ‘client’ entity from your earlier tutorials?
            Sorry for all the questions! This is really great stuff! 🙂

          • Matt Demler says

            January 9, 2015 at 5:24 am

            To try and clarify my previous question a bit further…

            In your first set of tutorials the client_id that is passed to the Auth server is ‘ngAuthApp’ which is describing the angular.js application requesting the token. This is used to set AllowedOrigin and RefreshTokenLifeTime in the AuthorizationServerProvider component in the middleware.

            In this tutorial, the client_id is now the resource server client id. This comes from registering it as an ‘audience’.

            It seems the context of client_id is different in both cases… 1st being the javascript application requesting the token and 2nd being the service you want to make your request to. (resource server)

            Or have I not fully understood? 🙂

          • Taiseer Joudeh says

            January 9, 2015 at 4:22 pm

            Hi Matt, apologies for the late reply.
            You are correct, in the first posts the client id is an identification for the client (application/software) which attempt to get access to the user’s account, and in the first posts I’m not trying to get access to the user account, I’m using only the client id to get some settings from DB for this client (application) such as the (allowed origin for building redirect URIs, Refresh token life time, etc..).
            I this post the client id is little bit different, it is the Id for the Resource server which will rely on this authorization server to get tokens from, maybe we should consider calling it audience_id instead of client_id, but the default implementation for the context “OAuthValidateClientAuthenticationContext ” of “OAuthAuthorizationServerProvider” contains strongly types properties for reading the client_id from (audience_id in your case).
            Hope this answers your concerns.

  16. Matt Demler says

    January 11, 2015 at 12:26 pm

    Thanks Taiseer. Don’t apologise… thanks for taking the time to reply to every single question people ask!
    I think a common thing people are getting confused about (or have trouble with) is requesting a token from a client application (mobile / website / etc) AND then still having some way of coupling an auth server and a resource server.
    I have seen a lot of questions that is similar to that. Your first tutorial you solve the client app requesting an auth token flow and then in this tutorial you solve the RS and Auth Server coupling flow. Putting it together seems to be the harder part.

    I have seen a few posts about how to solve this (as the spec just says ‘the resource server should check with the auth server to make sure the token is valid… but how to do that is outside of purpose of the spec’) and they recommend implementing a custom grant type, one that would allow a resource server to send a bearer token, that it has received, to the auth server for validation.
    I am going to attempt at putting together a working scenario on github over the next couple of weeks when I can fit it in and see if I can implement such a thing. I will reply here if I am successful if you would like to have a look at it 🙂

    Reply
    • Taiseer Joudeh says

      January 14, 2015 at 1:36 am

      You are welcome, yes please if you find better solution please share it here. Good luck 🙂

      Reply
  17. Luis says

    January 19, 2015 at 6:36 pm

    Hello,
    I have problem access from rest client.

    {
    Message: “Authorization has been denied for this request.”
    }

    I dont understand, lep me please

    Reply
    • Taiseer Joudeh says

      January 19, 2015 at 8:05 pm

      This is means your access token is invalid, make sure your are sending the right access token as well using bearer scheme

      Reply
      • Bob says

        April 20, 2015 at 8:37 pm

        I have the problem of Luis as well. I followed all the steps in the tutorial and when access the resource server by putting the token in the header in bearer scheme, I got the error saying “Authorization has been denied for this request.”. Do I missing anything here, and need to provide the secret as well, but how?

        Also, when I stepped into the process of token generation, I got error saying that HmacSigningCredentials.cs not found, although I double checked the Thinktecure package was installed properly. Please help.

        Reply
      • Bob says

        April 29, 2015 at 10:27 pm

        Can I get help on this? I used the clientId statically configured in the tutorial to generate the token, but still got access denied error. Thanks.

        Reply
  18. Werner Swart says

    January 25, 2015 at 3:35 pm

    First of all, fantastic article. Then my question is, do you know how to add additional information to the jwt token response. The current format is { access_token : xxxx, token_type: “bearer”, expires_in: 1799}. Is there a way of including the issued date in the token or is this the standard way the token must be?

    Reply
    • Taiseer Joudeh says

      January 26, 2015 at 1:32 pm

      Hi Werner,

      I guess you need override the method “TokenEndpointResponse” in class “CustomOAuthProvider” and include the properties needed there, I didn’t try it but it should be like the below:

      Let me know if it works 🙂

      public override Task TokenEndpointResponse(OAuthTokenEndpointContext context)
      {
      foreach (KeyValuePair property in context.Properties.Dictionary)
      {
      context.AdditionalResponseParameters.Add(property.Key, property.Value);
      }

      return Task.FromResult(null);
      }

      Reply
  19. Chris says

    February 2, 2015 at 8:01 pm

    Looking at the OAuth 2 documentation, shouldn’t the grant_type be “urn:ietf:params:oauth:grant-type:jwt-bearer” instead of “password”? Then the the authorization header in requests for resources should just contain the JTW, right?

    See http://openid.net/specs/draft-jones-oauth-jwt-bearer-03.html section 2.1. Hopefully I’m understanding it correctly.

    Reply
  20. Ra says

    February 6, 2015 at 4:44 am

    Thanks Taiseer for the great article.

    I’ve read your series on Token Based Authentication with Angular and now this particular article has me asking questions:

    I would like to combined the RefreshToken logic with JWT. I want a user on a particular application(client) to claim access to a resource(audience).

    So I changed my OAthServerOptions to this:

    OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() {

    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString(“/token”),
    AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30),
    Provider = new JWTAuthorizationServerProvider(),
    AccessTokenFormat = new CustomJwtFormat(“http://dev-maui-04/SOCCSAuthService”)
    RefreshTokenProvider = new SimpleRefreshTokenProvider()
    };

    My trouble lies in the ValidateClientAuthentication and GrantResourceOwnerCredentials:
    Since both JWT and RefreshToken are each accessing the ClientId property for different values, how do I elegantly hack this?

    Perhaps you can show me an example of how these two methods may look for returning a RefreshToken with a JWT Token as its Ticket?

    How would the resource server’s conversation with the Auth server change with a RefreshToken paradigm?

    Also, would this idea be forgery proof, considering Access-Control-Allow-Origin is set to *?

    Reply
    • Taiseer Joudeh says

      February 7, 2015 at 12:47 am

      Hi and thanks for your comment, I guess you need to add new property named “audience_id” in once you request the token, this property will hold the value for the resource server and the validation will take place in method “ValidateClientAuthentication” as it is in step 1.5. To read the value of the new parameter in method “ValidateClientAuthentication” you can do the following:
      dynamic formCollection = (Microsoft.Owin.FormCollection)context.Parameters;
      audience_id = formCollection.Get(“audience_id”);
      I didn’t try it before, so in summary the client_id/client_secret will be used to validate the client(i.e mobile app) and the audience_id property will be used to validate the Resource server.
      Let me know if this works with you.

      Reply
      • Ra says

        February 7, 2015 at 4:28 am

        Thanks again Taiseer. Its working out just right.

        public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
        {

        string clientId = string.Empty;
        string audiencId = string.Empty;
        string clientSecret = string.Empty;
        string symmetricKeyAsBase64 = string.Empty;

        Client client = null;
        Audience audience = null;

        if (!context.TryGetBasicCredentials(out clientId, out clientSecret))
        {
        context.TryGetFormCredentials(out clientId, out clientSecret);
        }

        if (context.ClientId == null)
        {
        //Remove the comments from the below line context.SetError, and invalidate context
        //if you want to force sending clientId/secrects once obtain access tokens.
        context.Validated();
        context.SetError(“invalid_clientId”, “ClientId should be sent.”);
        return Task.FromResult(null);
        }

        // protected method below. Gets parameter from context.Parameters.
        if (!TryGetFormParameter(context, “audience_id”, out audiencId))
        {
        context.Validated();
        context.SetError(“invalid_audienceId”, “AudienceId should be sent.”);
        }

        using (var repo = TinyIoC.TinyIoCContainer.Current.Resolve())
        {
        client = repo.FindClient(context.ClientId);
        }

        if (client == null)
        {
        context.SetError(“invalid_clientId”, string.Format(“Client ‘{0}’ is not registered in the system.”,
        context.ClientId));
        return Task.FromResult(null);
        }

        if (client.ApplicationType == Models.ApplicationTypes.NativeConfidential)
        {
        if (string.IsNullOrWhiteSpace(clientSecret))
        {
        context.SetError(“invalid_clientId”, “Client secret should be sent.”);
        return Task.FromResult(null);
        }
        else
        {
        if (client.Secret != Helper.GetHash(clientSecret))
        {
        context.SetError(“invalid_clientId”, “Client secret is invalid.”);
        return Task.FromResult(null);
        }
        }
        }

        if (!client.Active)
        {
        context.SetError(“invalid_clientId”, “Client is inactive.”);
        return Task.FromResult(null);
        }

        using (var repo = TinyIoC.TinyIoCContainer.Current.Resolve())
        {
        audience = repo.FindAudience(audiencId);
        }

        if (audience == null)
        {
        context.SetError(“invalid_audienceId”, string.Format(“Invalid audience_id ‘{0}'”, audiencId));
        return Task.FromResult(null);
        }

        context.OwinContext.Set(“as:clientAllowedOrigin”, client.AllowedOrigin);
        context.OwinContext.Set(“as:clientRefreshTokenLifeTime”, client.RefreshTokenLifeTime.ToString());
        context.OwinContext.Set(“as:audienceId”, audiencId);

        context.Validated();
        return Task.FromResult(null);
        }

        Reply
        • sorsubscriptions says

          June 10, 2015 at 9:57 am

          Hi @Ra,

          Have you got working copy of an entire solution (JWT + Refresh token + multiple ClientIds + multiple AudienceIds)? If yes, please share here. It will greatly resolve 90% of an existing and future comments here.

          Thank you!
          Sudhir

          Reply
          • Ukjells says

            June 26, 2015 at 5:25 pm

            I’m also really interested in the multiple ClientIds + multiple AudienceIds

  21. Bilal Pakka Insafian says

    February 8, 2015 at 2:35 am

    Hello again, silly question – I am saving these tokens in SessionStorage but issue is if I open a subpage in new link I need to login again? is there any way out?

    Reply
    • Taiseer Joudeh says

      February 9, 2015 at 10:33 am

      Hi Bilal, session storage is per tab, right? Why you not use localStorage to store the token?

      Reply
      • Bilal™ (@akaMBS) says

        March 27, 2015 at 3:07 pm

        Thanks.

        Reply
  22. Chris says

    February 9, 2015 at 9:42 pm

    So I managed to combine what I learned in your post about refresh tokens with this post on using JWT’s. However, I’m not sure I’m clear on one thing. Right now, I have my code populating the “aud” claim in the JWT with the clientId. Is that correct? Or is the “aud” claim supposed to represent something other than the client?

    Reply
    • Taiseer Joudeh says

      February 10, 2015 at 3:53 pm

      If you would like share the code you implemented with me and I’ll take a look. Thanks

      Reply
  23. Chris says

    February 9, 2015 at 9:52 pm

    I’m also looking to implement external authentication like you did in your post about external logins with Facebook and Google. However, I’m trying to do it strictly via the Owin middleware. From what I have found, it looks like all I need to do differently is replace the AccountController.ObtainLocalAccessToken action by overriding the GrantCustomExtension method in my custom implementation of OAuthAuthorizationServerProvider. Then, in that method, check if the grant_type is “urn:ietf:params:oauth:grant-type:google” (I made up this new custom grant_type). If so, then follow the same verification process that the ObtainLocalAccessToken method followed and call context.Validate(ticket) where ticket is a new AuthenticationTicket object based on the authenticated ClaimsUser. Does this sound right? Or am I missing some steps?

    Reply
  24. James says

    February 10, 2015 at 1:29 pm

    Hi to all,
    when I fail the request token (login by username and password not correct) is right that the tool returns a 400 error ?
    Thank you very much
    greetings
    James

    Reply
    • Taiseer Joudeh says

      February 10, 2015 at 3:58 pm

      Hi James, yes it’s correct to revive bad request, because technically you are (user) is sending wrong password and username so there server validate it and it needs to indicate that there is something wrong with user input, it should not return 401 because you are not authenticated yet. Hope this answers your question.

      Reply
  25. Ra says

    February 11, 2015 at 10:53 pm

    Hi Taiseer,

    I think my question is similar to Chris’: I have three resource servers(MapLayers, RSSProxy and Reports). My roles are creator and viewer. A creator can access every server to build a map where on which messages will reside as icons. The viewer can see the resulting report data the the reports server handles.

    I want the creator to login one time and get a token that allows role based access to every server.

    How would the custom JWT look? Would I sent up three audience_ids (one for each server) or could I add claims to the token?

    Reply
  26. Kartik Sharma says

    March 26, 2015 at 9:43 pm

    Hi Taiseer,

    Thanks for this excellent article. But I have some questions in regards to mobile client for these api’s:

    1. After getting JWT everything’s fine. But how to make this process of fetching JWT from Authorization server secure? As we send credentials in this step and hence it seems to be very critical data, so should I just rely on SSL for that or try additional steps.Can you please throw some light here?

    2. In case of mobile clients, such as an Android app, once i authenticate and receive JWT I have to persist JWT somewhere inside the phone to make further calls, lets say sqllite or shared preferences in case of Android. Is it recommended to persist JWT’s inside the client machine. If not then, is there any alternative?

    Reply
    • Taiseer Joudeh says

      March 27, 2015 at 4:31 pm

      Hi Kartik,
      Glad to hear that this post is useful, please find my answers below:
      1- I’m implementing here an OAuth 2.0 flow named “Resource owner password credential flow” which should only be used with client application that you trust 100% or your have built, what I mean by this you need to make sure that this native login screen appears in your android App where the user provides his username/password to it is not storing it locally or invoking a malicious API where it logs those credentials. Those credentials should be sent the /token endpoint directly over HTTPS only and your receive the access token over HTTPS too, not if this is not the case you need to consider using another OAuth 2.0 flow named implicit grant.
      2- Yes you need to store the access token securely in your device so you present it with each call, usually what you can do is to issue short lived access token 1 hours and you keep refresh it using refresh token grant. Access token transmission should be done over HTTPs only.
      Hope this answers your question.

      Reply
  27. Victor says

    March 26, 2015 at 10:46 pm

    Hi Taiseer,

    Maybe a stupid question but how does the client (Angular app for example) know about the client_id (audience_id)?
    Is it “hard coded” in for example the app.js file just like the rest? So it is stored in 3 places namely in the web.config of the Resource Server, in the database of the Authentication Server and in the app.js file of the Angular app?

    If you want access to multiple Resource servers they are “stored” in the app.js file?

    Thanks!

    Reply
    • ashley208 says

      June 12, 2015 at 1:10 pm

      I see it working a little like this (if you can understand my terrible hand writing)

      https://www.dropbox.com/s/9shtau0dlpkep32/File-12-06-2015-11-02-24.jpg?dl=0

      Client -> Resource Server -> Auth Server

      So to login, your js passes the client name & user credentials, the resource server appends on its resource credentials (completely privately, nothing to do with the client) then the resource server just passes on the JWT it receives from the auth server back to the client

      (Taiseer if I’m wrong here please let me know!)

      Reply
  28. Andrew Safwat says

    April 1, 2015 at 4:52 pm

    i’m using fiddler for testing API’s. when i tried to test the token using http://localhost:18303/api/protected “Get”
    User-Agent: Fiddler
    authorization: bearer [ACCESS TOKEN]
    Host: localhost:18303

    the result always 401 Unauthorized.
    note: i can create new token and all of them Unauthorized
    please need help

    Reply
    • Taiseer Joudeh says

      April 2, 2015 at 11:10 am

      Make sure that you implementing step 2.3 correctly and the values for issuer, audience and secret are exactly the same as your AuthZ server.

      Reply
      • Andrew Safwat says

        April 2, 2015 at 2:18 pm

        i downloaded your source code and that what i’m working on it and i didn’t changed in it. it always gives me 401 Unauthorized.

        Reply
        • Taiseer Joudeh says

          April 3, 2015 at 7:18 pm

          That strange, many others used it without any issues, I can’t think of cause of this issue 🙁

          Reply
          • Victor says

            April 3, 2015 at 7:28 pm

            I think he did not change the JWT issuer to his local IP?

          • Priya Khisti says

            April 7, 2015 at 11:39 pm

            Taiseer: Really great article! I have followed all your blogs and especially this one very carefully. And I have the exactly same issue as the above comment. I am getting Authorization has been denied for this request.(401) whenever I try to call a resource server api method from angularjs client with a valid token. Token is valid, I checked it multiple times on http://jwt.io/. I am not sure if I am missing something very simple.

          • Taiseer Joudeh says

            April 8, 2015 at 11:51 am

            Hi Priya,
            Are you sure the same AudienceId and Secret are used to generate the token and the same to validate it in (app.UseJwtBearerAuthentication)?
            As well what is the the value you receive in the WWW-Authenticate header? Is it bearer or something else?

          • Priya Khisti says

            April 8, 2015 at 4:56 pm

            Thanks for the reply Taiseer. I finally figured out the for JWT issuer url needed a “/” in the end. 401 error makes you think that error is somewhere else. Again thanks for these great posts.

  29. Eben Bosman says

    April 15, 2015 at 12:37 pm

    Hi Taiseer,

    Thanks for a great article! I am a bit new to JWT’s and WebAPI after having used mostly WCF services up to now. However, I do have a little experience regarding using JWT’s working with Angular and Node.js.

    I mostly followed your tutorial to the T, except that in the Audience store I am using cache to persist the user data as the API am working on will only be used for an intermediary for other services.

    My front end uses Angular to do get/posts to the API and after logging in and getting the token form “oauth2/token”, I set it in sessionStorage and subsequently make sure the “Authetication” header is present equal to “Bearer xXxTokenxXx…”.

    At the moment when I am trying to access a endpoint protected by the [Authorize] decorator, I get a 401 reply. However, I have made sure on endpoints using [AllowAnonymous] that the “Authetication” header is present by inspecting System.Web.HttpContext.Current.Request.Headers[“Authorization”].

    Do you have any idea what I might be doing wrong or if you can point me in the right direction where to start debugging my issue? I currently have breakpoints all over the show in the code I got copied from your example, but not hitting any of them when trying to access the endpoint protected by [Authorize].

    As an example, I get the sure issue when trying to call the endpoint from Postman. You can see the example here: http://imgur.com/a/WoCeL#0

    Any help would be appreciated. Thanks!

    Reply
    • Taiseer Joudeh says

      April 18, 2015 at 2:15 am

      Hi Eben,
      Once you receive 401, and in the response header (www-authenticate) what is the value returned? I’m afraid that your resource API is not configured to be protected by bearer tokens and it is using cookies.
      As well double check that issuer value used are identical in your Authz and Resource API.

      Reply
  30. Eben Bosman says

    April 16, 2015 at 9:21 am

    Hi Taiseer

    Thanks for a great article again.

    I am just wondering if I have a project which is both the Authorization Server and the Resource Server, whether it is possible to get the AllowedAudiences in the JwtBearerAuthenticationOptions object to work on a more dynamic fashion? Realistically in a real world scenario one cannot have only one allowed audience and one cannot restart the server every time a new audience is added to the Audience Store.

    In my case I changed the Audience Store to be persisted and when recognized users logs in, I add them to the Audience Store. Then in JwtBearerAuthenticationOptions I would like AllowedAudiences to get it’s values from my Audience Store.

    However, if I do it this way and the Audience Store is empty when I start up the server for the first time an error is thrown because the AllowedAudiences in JwtBearerAuthenticationOptions needs to have at least one entry.

    If I hard code at least one entry into the Audience store as you did, then it works fine, obviously. However, after that point I can add as my users to the Audience Store as I want, they won’t be recognized until the AllowedAudiences in JwtBearerAuthenticationOptions gets refreshed – aka restarting the server.

    I was hoping you could help me get around this?

    Kind regards
    Eben

    Reply
  31. Robert says

    April 19, 2015 at 4:40 am

    I got the similar problem as above from Luis. I followed the steps in your tutorial to add audience, generate token, secret, then, as you mentioned, pasted the token to the jwt.io, it shows the signature is invalid with a red bar. I can put the base64secret in the field as indicated in jwt.io, but should I use only the token, or both token and secret in the header to get to protected area on the resource server, and how? Excuse me if this is a stupid question. I tried with token, and I got
    {
    Message: “Authorization has been denied for this request.”
    }

    but I tried again, I got 500 error.

    Also, when I was in debug mode to step-in the token generation process, I got an error that HmacSigningCredentials.cs is not found. I did installed Thinktecture Nuget package as the instruction in the tutorial.

    Thanks and really appreciate your help..

    Reply
    • Robert says

      April 19, 2015 at 5:33 am

      Never mind about the 500 error, it was something else, I already fixed that. The error is “Authorization has been denied for this request.”, please help. Thanks.

      Reply
  32. Koundinya says

    April 23, 2015 at 8:55 pm

    Hi Taiseer,

    Great Article!! I am having a scenario where the OAuth server and the resource server are the same. It would be really great if you can guide me what needs to be done in this scenario.

    Thanks,
    Koundinya

    Reply
    • Taiseer Joudeh says

      April 24, 2015 at 12:06 am

      Hi Koundinya,
      Glad that this post is useful, you can find the exact scenario you are looking for on my other post here where the Authz and Resource server are the same. Good luck 🙂

      Reply
  33. Sotheayuth says

    May 3, 2015 at 6:15 pm

    This is a great tutorial!
    Thank you very much Taiseer Joudeh…

    Reply
    • Taiseer Joudeh says

      May 3, 2015 at 8:43 pm

      You welcome, glad you liked it!

      Reply
      • Sotheayuth says

        May 4, 2015 at 2:08 pm

        Could you pls respond to my question left under the comment of Kent F.?

        Thanks in advance

        Reply
        • Taiseer Joudeh says

          May 4, 2015 at 2:22 pm

          I will hopefully by end of today, hopefully I will find answer.

          Reply
  34. Akinsanya Olanrewaju says

    May 5, 2015 at 9:37 am

    Hi, Taiseer Joudeh

    Am sorry to have ask for this question but i have search for resource with any help, I need to convert this part of the code to the pattern of Repository and Controller method but without any solution, please can you point me to resources or solution to help fixing this

    public static class AudiencesStore
    {
    public static ConcurrentDictionary AudiencesList = new ConcurrentDictionary();

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

    And this Controller

    [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(newAudience);

    }
    }

    Am new to web api, and your blog is my first resources in Web API,

    Thanks

    Reply
  35. Rich says

    May 12, 2015 at 1:27 am

    Do you have an example client or http request that gets a token and then requests from the protected resource? I can get the token but the call to the api/protected fails on authentication.

    Reply
    • woailibian says

      May 13, 2015 at 11:56 am

      I have the same question

      Reply
    • Taiseer Joudeh says

      May 15, 2015 at 11:59 pm

      Hi Rich, I’m using postman to call the resource server end points, any http clients can do the same as long you pass the correct token in the authorization header using bearer scheme. If it is not working then there is issue with configuring the resource server with the authorization server.

      Reply
  36. woailibian says

    May 13, 2015 at 11:55 am

    hi,Taiseer
    I can do this following you hlep
    but I have a question:
    when I get the access token from Authroization Server,why can’t I use the Authroization’s Protect API?

    I means,I add an WebAPI in Authroization Server name Protected3Controller below [Authorize].
    I get the access token as your sample and return the right token which can use all of the action in Resource Server,
    but I can’t use any action in Protected3Controller .
    why? and can you tell me how to do this?

    Reply
  37. Arthur W says

    May 20, 2015 at 7:44 pm

    I am sending a post with Fiddler to the Audience Controller. My audienceModel is always null. Am I missing a step?

    Reply
  38. Arthur W says

    May 20, 2015 at 7:52 pm

    I found the issue. It was USER ERROR! Boy I feel stupid. Thanks for this excellent post!

    Reply
    • Taiseer Joudeh says

      May 20, 2015 at 8:08 pm

      You are welcome, glad you find it useful.

      Reply
  39. Chris T. says

    June 2, 2015 at 7:04 pm

    I see that you are using the Authorize filter on you WebApi methods. As you know this filter has a Roles parameter so access to the api methods can be restricted to specific roles [Authorize(Roles = “Admin”)] for example. I also see you added roles to the JWT. My question is will the Authorize filter inspect the JWT for roles if they are provided in the filter on the api method? If not would I need to implement that in the custom provider?

    Thanks!

    Reply
    • Taiseer Joudeh says

      June 3, 2015 at 2:04 am

      Hi Chris,
      You are right, the Authorize filter will check for Roles provided in the token, so if you have a method which is attribute by [Authorize(Roles = “Admin”)] only access token which contains the role “Admin” will be authorized, so no need to create custom provider.

      Reply
      • Chris T. says

        June 3, 2015 at 3:04 pm

        Thanks! I can’t tell you how much this series of blog posts have helped me in understanding a fairly confusing process. Great job!

        Reply
  40. Cristian says

    June 4, 2015 at 1:29 am

    Good day, why?They use the line AccessTokenFormat = new CustomJwtFormat (“http://jwtauthzsrv.azurewebsites.net”) why must serguir that format? there is something more generic?

    Reply
  41. Brett Hargreaves says

    June 9, 2015 at 5:59 pm

    Great article – can I ask what tool you are using to test the endpoint? I’ve been using Fiddler but yours looks a bit friendlier!

    Reply
    • Taiseer Joudeh says

      June 13, 2015 at 2:50 am

      Hi Brett,

      It is called PostMan, Google Chrome Extension, just search for “PostMan Packaged App”

      Reply
  42. sorsubscriptions says

    June 10, 2015 at 8:29 am

    Hi Taiseer,

    Thanks a lot for explaining such a complicated thing with easiness, simple words and working examples. Thank you!

    What is the best way to incorporate 3rd party apps accessing multiple in-house APIs? Can you please guide?

    Any help here would be much appreciated.

    Thank you!
    Sudhir

    Reply
  43. Amani ghuneim says

    July 1, 2015 at 1:51 pm

    Great article, thanks a lot for these beneficial blogs, but I have a little confuse about the difference between client ID and resource server ID,
    1- should I add hard coded resource ID???
    2- Isn’t the client ID should be generated when register to application??
    3- when a requesting an access token, the client ID passed is that of client and not the resource server Id?

    Reply
  44. Amani ghuneim says

    July 1, 2015 at 2:48 pm

    Hi,
    Great! thanks a lot for all these beneficial blogs, but I have a little bit confused about the difference between Resource server ID and client ID,
    1- Should I hard coded Resource server ID?
    2- The Client ID is the one got upon app registration, isn’t it?
    3- when requesting an access token, using post, the client Id entered is that of the client or of the resource server?

    please advice ,

    Best Regards.

    Reply
  45. Fred Chateau says

    July 1, 2015 at 4:55 pm

    Thank you for the detailed instructions here. This is exactly what I was looking for.

    I’m have a little problem, however. The code compiles, but I’m getting a run-time error “ServiceLocationProvider must be set.” at the OAuthServerOptions. Any idea what that is about?

    Reply
  46. Fred Chateau says

    July 1, 2015 at 5:00 pm

    Oh, it just occurred to me, is this something to do with the CommonServiceLocator? If so, I’ll figure it out.

    Reply
  47. Leroy Jenkins says

    July 2, 2015 at 5:22 pm

    I’m trying this out step by step and I’m getting the following response when using the client_id, username, password, and grant_type = password:

    {
    “error”: “unsupported_grant_type”
    }

    Please help me figure this out. I haven’t the slightest idea as to why this is happening and no one has mentioned this yet.

    Reply
    • Taiseer Joudeh says

      July 4, 2015 at 2:59 am

      Your request should look as the below, i guess you missed setting the content-type header correctly

      POST /consumerappapi/oauth2/token HTTP/1.1
      Host: ws.sandbox.aramex.net
      Accept: application/json
      Content-Type: application/x-www-form-urlencoded
      Cache-Control: no-cache

      username=XXX&password=XXX&grant_type=password&client_Id=XXX&client_secret=XXX&device_id=XXXX

      Reply
      • Leroy Jenkins says

        July 6, 2015 at 6:58 am

        Thanks for the help. It turned out that I fat fingered the word “grant_type”. Would it be possible to update this tutorial? I noticed a few inaccuracies:

        Your tutorial says:
        Install-Package Thinktecture.IdentityModel.Core Version 1.2.0

        It should say:
        Install-Package Thinktecture.IdentityModel.Core -Version 1.2.0

        The missing hyphen on the version threw me off a little. Last, for the Resource Server’s startup.cs, there’s a difference between what you put in this tutorial and what’s on github. In this tutorial, you’re missing the following (within JwtBearerAuthenticationOptions) :

        ,
        Provider = new OAuthBearerAuthenticationProvider
        {
        OnValidateIdentity = context =>
        {
        context.Ticket.Identity.AddClaim(new System.Security.Claims.Claim(“newCustomClaim”, “newValue”));
        return Task.FromResult(null);
        }
        }

        Adding those two updates will make things a bit easier to follow when you’re not downloading the source. Without the Provider being set, you’ll get:

        {
        “Message”: “Authorization has been denied for this request.”
        }

        Reply
        • Taiseer Joudeh says

          July 9, 2015 at 4:47 am

          Good catch, I will check it and update. Thanks Leroy

          Reply
  48. mrivanlee says

    July 4, 2015 at 5:12 pm

    Great post!

    Just want to see what I should do if I want to keep the roles under the resource server instead of Authorization server.

    Because I thing that every systems should have the specific roles, right?

    Thanks!

    Reply
    • Nguyễn Quý Hy says

      July 22, 2015 at 5:41 am

      I have the same question. Really hope that you can help on this.

      Reply
  49. Derek Xiao says

    July 14, 2015 at 12:39 pm

    Hi Taiseer,

    Very wonderful article, I’m new in Web API, I just follow your steps. I can register the new audience and get the access_token, but when trying to get the protected api(Resources Server), it always return
    {
    “Message”: “Authorization has been denied for this request.”
    }

    I just download the source code from GitHub, and modify the issuer to localhost with port, and the behavior still the same.

    Thanks again for the great post.

    Reply
    • Taiseer Joudeh says

      July 15, 2015 at 1:07 am

      Hi Derek,
      Make sure that issues is the exact thing, its case sensitive and trailing slash will affect the validation of the token

      Reply
      • Derek Xiao says

        July 15, 2015 at 5:38 am

        Thanks for the reply Taiseer. It’s my careless, the issuer not exactly the same, the resource server miss a trailing slash.

        Reply
  50. Mitja Dragman says

    July 17, 2015 at 8:31 pm

    Realy great tutorial.
    Thanks for your time to explain it nice and clear.

    Reply
    • Taiseer Joudeh says

      July 21, 2015 at 10:23 am

      You are welcome Mitja.

      Reply
  51. tuananh says

    July 27, 2015 at 6:03 pm

    Excuse me, I downloaded your solution, I can generate JWT by AuthorizeServer, but when I request with this JWT, I received status code 401 unauthorized, I dont understand. I’m no change anything in your project, please help me, thank you.

    Reply
  52. wask says

    July 31, 2015 at 9:31 pm

    Realy great tutorial

    i have issue
    1. http://localhost:21972/oauth2/token
    2. http://localhost:21972/api/audience

    The first one works fine, so I can get token back. I have issues with the second one try to add new audience. It gives back 404, always. how to fix this issue
    Thanks for your help

    Reply
    • Taiseer Joudeh says

      August 8, 2015 at 7:04 am

      Make sure that you are setting the correct [RoutePrefix] attribute on this controller.

      Reply
  53. Atul says

    August 6, 2015 at 9:19 am

    Hi Taiseer,

    As usual you are doing a great job and contribution to community.
    Just one question Instead of using the custom json formatter class I am thinking of using the https://github.com/jwt-dotnet/jwt nuget. What are your thoughts on it?

    Regards,
    Atul(Big Fan)

    Reply
    • Taiseer Joudeh says

      August 8, 2015 at 7:28 am

      Hi Atul,
      Thanks for comment, the JWT is becoming standard for access token format, so I guess you can use this library, I read the source code of it but never tried it before. Let me know the outcome after you implement it.

      Reply
      • Kunal Bajpai says

        April 16, 2016 at 1:12 pm

        Taiseer,

        You posts have been a great help.

        I have followed you tutorial to configure the resource server. Jwt token is issued by Google (on Android). At the resource server side I get the following error,

        – System.IdentityModel.Tokens.SecurityTokenSignatureKeyNotFoundException was unhandled by user code
        – Message=IDX10500: Signature validation failed. Unable to resolve SecurityKeyIdentifier: ‘SecurityKeyIdentifier

        I’m unable to find a valid solution. I am on .NET version 4.5 (IdentityModel 4.0.0)

        Reply
        • SarSha says

          July 8, 2016 at 11:23 pm

          You can not decrypt the jwt created by google since you do not have the secret key it was encrypted with.

          Reply
          • Taiseer Joudeh says

            July 10, 2016 at 10:47 am

            That is correct, but you can decode it is content and see the claims inside it.

        • SarSha says

          July 8, 2016 at 11:47 pm

          Great post.

          How do you combine that with social logins ?
          How will the flow look like ?

          I’m guessing the resource server will be responsible to provide a social provider access token?
          But how will the authorization server validate it? should it be validates on the auth server ?

          What grant_type will be used on such flow ? not the ‘password’ since the user won’t provide any username \ password.

          Will appreciate your help figuring out the flow.

          Thanks !

          Reply
          • Taiseer Joudeh says

            July 10, 2016 at 10:46 am

            Hello,
            Did you have the chance to take a look at the following blog where I cover social logins? You might be able to take some hints as I do not have a dedicated blog post for this.

  54. Adolfo says

    August 8, 2015 at 7:18 pm

    Like tuananh above I also get 401 unauthorized.

    First off, great job, loved all your oauth/owin related articles, thanks a lot for sharing all this wonderful information with us.

    Here is my situation:

    i separated the two projects into two separate solutions running respectively in http://localhost:18292 and http://localhost:18303

    I am getting the token for that Auth Server [port 18292] fine:

    access_token : xxxx
    expires_in : 1799
    token_type : bearer

    But calling the protected [Authorize] method in the Resource Server with these headers gives me the 401:

    GET http://localhost:18303/api/protected
    Host: localhost:18303
    User-Agent: Mozilla/5.0 (Windows NT 6.3; rv:39.0) Gecko/20100101 Firefox/39.0
    Accept: application/json, text/plain, */*
    Accept-Language: en-US,en;q=0.5
    Accept-Encoding: gzip, deflate
    Authorization: Bearer xxxx
    Referer: http://localhost:18303/Login.html
    Connection: keep-alive

    1, Should the Resource Server by secure (https) ?
    2. Are the headers ok? any missing?
    3. I left the issuer to: http://jwtauthzsrv.azurewebsites.net, should this be changed to the real Authorize Server url? How do you do that with localhost?
    4. Is there any way to get more detailed errors at least during development? or a way to step through the validation code in the Resource Server?

    Really appreciate any help you could provide

    Reply
    • Taiseer Joudeh says

      August 15, 2015 at 1:33 am

      Hi,
      Just make sure that the issuer value in your resource api has the same value of the issuer (authorization server) which generated the JWT, no trailing slashes, case sensitive, same http protocol.

      Reply
      • Redshirt says

        June 30, 2016 at 12:31 am

        Would this include the port number and/or path used to retrieve the token?

        Reply
    • lennybaconDaniel Fisher(lennybacon) says

      November 22, 2015 at 10:21 pm

      >> Should the Resource Server by secure (https)

      YES. If not everybody could steal the token with ease…

      Reply
      • Taiseer Joudeh says

        November 24, 2015 at 1:34 pm

        Correct, with OAuth2, you should go TLS all the way.

        Reply
    • Jason says

      January 8, 2016 at 5:11 pm

      I get the exact same error. I followed your post to the letter, but still get a 401 error. When I run the project you posted on GitHub I also get this issue. Even though the issuer is still set to http://jwtauthzsrv.azurewebsites.net.

      Reply
      • Jason says

        January 8, 2016 at 5:27 pm

        Scratch that… What I am actually asking is how do I provide the JWT in my GET request to the /api/protected?

        Reply
        • Taiseer Joudeh says

          January 10, 2016 at 1:22 am

          Hi Jason,
          You need to set the token in the Authorization header using Bearer scheme, it will be like this “Authorization: Bearer Your_JWT_Token”

          Reply
          • Ganesh Kumaresan says

            May 11, 2016 at 2:23 pm

            Hai Taiseer,

            I have set the authorization header as you said. Should I send the issuer name with the request? If so how to set that ? Should I send it as json in the request body. I am getting the Unauthorized error.

            Thanks,
            Ganesh

          • Taiseer Joudeh says

            May 12, 2016 at 12:18 am

            Hi Ganesh,
            No you should not send the issuer in the request, but you need to make sure that you used the same issuer in resource server and Authz server.

  55. Carlos Boichuk says

    August 13, 2015 at 8:35 pm

    Hi Taiseer, this post is very helpfull indeed, but can i ask you after the test in postman with the auth server, how to test the resource server with postman too?
    Thanks a lot for sharing your knowledge.

    Reply
    • Taiseer Joudeh says

      August 15, 2015 at 1:09 am

      Hi Carlos,
      The authorization server will be hosted on different domain and the resource server will be on another domain, so once you obtain the token from the authorization server, you need to send a request to the resource server domain and use the token in the authorization header using Bearer scheme.
      Hope this answers your question.

      Reply
      • Carlos Boichuk says

        August 16, 2015 at 4:20 am

        Thanks a lot Taiseer! It worked now, im brand new with oauth and web api security aspects and your posts of oauth and web api 2 helped me a los =D

        Reply
      • David Cook says

        October 20, 2015 at 6:53 pm

        Can you furthur describe the bearer scheme. I’m new to this and trying to use postman. Thanks.

        Reply
        • Taiseer Joudeh says

          October 21, 2015 at 11:08 am

          Hi David, This is a very open question, I recommend to Google this as well I have covered this on the first post.

          Reply
  56. Guario says

    August 21, 2015 at 6:12 pm

    I followed your set up for section 2 but I’m getting an error when I try to go to the endpoint. It says it can’t find the resource. I followed your suggestion of creating an empty application and then using Nuget to add the proper references. But I can’t use PostMan to hit my protected endpoint. I’ve put a breakpoint inside the Startup class in the ConfigureOAuth method. I can reach that but I can’t seem to reach the controller action. Any suggestions?

    Reply
    • Taiseer Joudeh says

      August 24, 2015 at 11:16 pm

      Hi Guario,
      I guess your problem is with defining Routes in your Web Api controllers, that’s why you are receiving 404. Make sure you are enabling config.MapHttpAttributeRoutes(); if you are using attributes routing.

      Reply
  57. Syam P says

    August 28, 2015 at 12:18 pm

    Hi Taiseer, I would like to know how to configure a resource server that accept many client applications to access the secured resources.
    I have a scenario like my Authorization Server and Resource Server(Web API end points) are the same.
    Here I need to provide access or authorize many client applications means these resource url’s can be accessed by many other client applications. Please guide me how to authorize the clients using JWT tokens only.
    Thanks
    Syam

    Reply
    • Haraldur says

      December 15, 2015 at 4:43 pm

      Did you ever figure out a feasible way to do this?

      Reply
    • Nishanth says

      December 29, 2016 at 7:55 am

      Did you find the solution for this?

      Reply
  58. Stephen says

    September 4, 2015 at 6:06 pm

    I have followed this tutorial but am getting an “Access is denied for this request”, error when I try and get to the protected API.

    1. I am running this locally, must both projects be deployed to separate websites in order for the example to work?
    2. When I make a call to the protected controller, it never hits any breakpoints in the Authorization server.
    3. Should the issuer be just the base URL or should it also include /token at the end?

    Reply
    • Taiseer Joudeh says

      September 7, 2015 at 6:43 am

      The issuer should be only the Base URL not with the “token” end point, I guess this is your only issue.

      Reply
  59. Srishti Parakh says

    September 5, 2015 at 8:40 am

    Hey Taiseer,

    Thanks for the post!
    I’m facing a little issue here though. I am getting 401 unauthorized.
    The issuer, audience and secret are the same for both the AuthenticationServer and ResourceServer. I really can’t place where it’s going wrong. Where else can I look to solve this issue?

    Thanks in advance 🙂

    Reply
    • Taiseer Joudeh says

      September 7, 2015 at 6:35 am

      Hi Srishti,
      Usually the issuer will be different, are you sure there is no trailing slash, and you are using same http scheme? (http, https)> Decode the JWT token using http://Jwt.io and make sure that the claims you are looking for is as expected.

      Reply
  60. avmp2208 says

    September 6, 2015 at 7:56 pm

    This is great. Thanks.

    I hope you could help me with a little question,

    Right now I’m trying to protect my WCF Service, and my idea is, have a web api project as STS which gives me a token as your example, once I get the token, I pass it to my client (MVC website) and I set a cookie with the token inside,

    Is there any way to protect my WCF Service with this mechanism? I mean for example: once I get the token from the web api I like to pass it from my MVC website to my WCF service and validate it, …

    I’ll appreciate any example about it.

    Best regards.

    Reply
    • Taiseer Joudeh says

      September 7, 2015 at 6:23 am

      Is your WCF is exposed to the public (hosted on IIS with Ws-binding enabled) if yes then why not to use Web Api to serve your need? If it is acting like back-end service then it is already protected by your company windows authentication and your company firewall. I’m not sure if I understood the whole picture but I do not know if there is a way to protected the WCF service using JWT tokens.

      Reply
      • avmp2208 says

        September 7, 2015 at 2:06 pm

        Yes, my WCF is public, this my scenario

        1. WCF on IIS
        2. Class Library as Client (With Service Reference to my WCF)
        3. MVC Application (this one consumes my class library)
        4. Web api as STS

        the thing is I don’t want to use web api beacause I will have to change all my services and theres a lot work doing that

        Thanks

        Reply
  61. Corne says

    September 10, 2015 at 12:46 pm

    Thank you for this thorough tutorial Taiseer, worked first time following it. And also for all the others regarding OWIN Auth (only ones I’ve been through). Have a great day.

    Regards,
    Corne

    Reply
    • Taiseer Joudeh says

      September 10, 2015 at 6:47 pm

      You are welcome Corne, happy to hear that posts are working directly without any changes 🙂

      Reply
  62. Corne says

    September 10, 2015 at 6:21 pm

    Hi Taiseer, I have a question regarding the CustomOAuthProvider, I see it only support these 2 methods:
    TryGetBasicCredentials and TryGetFormCredentials. So how would one handle JSON coming in through request body then ?

    If I were to log in by sending through a JSON object rather than forms structured credentials (username=x&password=y&grant_type=password&client_id=bla)

    Thanks

    Reply
    • Taiseer Joudeh says

      September 10, 2015 at 6:43 pm

      Hi Corne,
      The standard way to send request to an OAuth 2.0 “token” end point is by setting the content-type to “application/x-www-form-urlencoded” not “application/json”. Please check the specs here.

      Reply
      • Corne says

        September 11, 2015 at 1:39 pm

        Got it, thanks Taiseer.

        Reply
  63. Tonchi says

    September 11, 2015 at 3:43 pm

    Hi Taisser,

    Perhaps my question its too silly, but you add functionality for the user to refresh his token. But in real world this need to be like this? Because i think that common user dont know what means refresh token, so i think i need to refresh on behind. Im correct?

    Reply
  64. Sharad Kumar Singh says

    September 12, 2015 at 7:16 pm

    Hi Taiseer,
    first of all thank you for share this wonderful article. I have one question why you are using http://jwtauthzsrv.azurewebsites.net in CustomejwtFormat class. Should I use something else.

    Reply
    • Taiseer Joudeh says

      September 18, 2015 at 2:57 pm

      Hi Sharad, sorry I didnt get your question, can you elaborate more?

      Reply
  65. gromao says

    September 14, 2015 at 11:29 pm

    Is there any difference from this and this package ? Microsoft.Owin.Security.Jwt ?

    Reply
    • Taiseer Joudeh says

      September 18, 2015 at 2:49 pm

      Which packages you are comparing?

      Reply
  66. Tid says

    September 25, 2015 at 3:43 pm

    Like Adolfo I also get 401 unauthorized.
    I downloaded your solution, changed the issuer with the localhost server in both webAPIs, it doesn’t change the 401.

    I ran a fiddler, the protected webAPI doesn’t even try to connect to the authorization api.
    Is there something missing here ? (like some sort of link to specify the oath url ?)

    Thanks in advance

    Reply
    • Adolfo says

      October 3, 2015 at 7:47 pm

      Tid, my 401 was due to an issuer inconsistency in my implementation which I realized when I visualized the token in jwt.io.

      Your description of your problem is a little vague.

      I am not clear what you mean when you say “the protected webAPI doesn’t even try to connect to the authorization api”, because when you are trying to access a protected method in your web.api, the web.api does not need to access the “authentication server”. Your request to access the protected method should come with a token and only if the token is invalid, expired or missing you will get a 401. But this validation does not need to access the authenticating server, it is done in the Startup module of your resource server.

      You would never get a 401 from access the authenticating server because the login method is not protected.

      So until you clarify your workflow I would say you are trying to access the protected web.api method without a token.

      Reply
      • treetopvt says

        December 21, 2015 at 5:28 am

        Adolfo, What was your inconsistency and how did jwt.io help you identify it? The first time I implemented this tutorial I got everything to work. The second time, it does not work . Tokens are generated just fine and look great in jwt.io, but I always get an invalid token response on any authorized api resource. Very frustrating! It is almost like the owincontext is not consuming the token.

        Reply
  67. Andrew Davis says

    October 1, 2015 at 8:11 pm

    Hi Taiseer,

    Thanks very much for posting this, it’s been very helpful. Do you have any advice on how to use this sort of model with an asymmetric key instead of a symmetric one?

    I’m looking at implementing something like this for a microservice-based system — one client (which we control/develop, but is implemented in browser javascript and is therefore untrustable) will log in to our auth server and get a JWT, but that token must be usable by several different resource servers. Obviously I could do this with a symmetric key if I share the key with all the resource servers, but of course that would mean that anyone who managed to hack into any one of our resource servers would be able to get it. So what I’d like to do is use an asymmetric key pair so that the auth server can issue and sign the token with the private key, and the resource servers can verify the token’s signature with only the public key.

    As I understand it so far, if I started with your example in this article, I’d need to make changes in two places: in the auth server’s code, alter the class implementing ISecureDataFormat (CustomJwtFormat in your example) to use a different SigningCredentials object which uses asymmetric encryption; and in the resource server’s Web API startup code, use a different implementation of IIssuerSecurityTokenProvider which can verify the signature.

    If that’s correct, can you suggest any existing classes or examples for this? For the token provider, Microsoft.Owin.Security.Jwt already offers an X509CertificateSecurityTokenProvider class, but from a quick reading of the MSDN documentation it looks like I would need a full X509 certificate to create an instance of that class — not just the public key from one. Since the whole point is to remove the need to share a private key with the resource servers, that seems like a non-starter.

    Thanks again,
    –Andrew

    Reply
    • Jawand Singh says

      October 22, 2016 at 2:04 pm

      Hi,

      Andrew, did you find any thing. Can you help me ? I do to use asymmetric key and have multiple resource Servers.
      Let me know if you can help me.

      Thanks,

      Jawand Singh

      Reply
  68. Nitin says

    November 3, 2015 at 3:10 pm

    Why symmetric key is associated with Client? What if we have more than one client who uses same resource server, how to configure resource server settings in this case?

    Reply
  69. Jordan Sinko says

    November 14, 2015 at 1:09 am

    Great post! I have just one question that I cannot seem to solve. Based on client id, I am setting a different ExpiresUtc datetime in AuthenticationProperties in GrantResourceOwnerCredentials like so:

    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
    {
    {
    “audience”, (context.ClientId == null) ? string.Empty : context.ClientId
    }
    });

    prop.ExpiredUtc = DateTime.UtcNow.AddMonths(1);
    //prop.ExpiredUtc = DateTime.UtcNow.AddMonths(3);

    var ticket = new AuthenticationTicket(identity, props);
    context.Validated(ticket);

    When it gets to my Protect method, it reverts back to the standard expiration from the OAuthAuthorizationServerOptions init. Any ideas why this is doing it and what I can do to do what I would like? Thanks!

    Reply
  70. renchan says

    November 25, 2015 at 3:44 pm

    Hello, I’m making a request with AngularJS to Web API passing client_id. If I’m understanding correctly it’s securely vulnerable. But I don’t know what should I do in this case… Could you please give me a hint.

    Reply
  71. zoranpro says

    December 18, 2015 at 11:50 am

    Hi Taiseer,

    Can you please explain me how can I dynamically add/remove secrets from IssuerSecurityTokenProviders? From how I understand UseJwtBearerAuthentication is fired once on startup.

    If I create/store new secret in database, how can I pass that into the IssuerSecurityTokenProviders?

    Best,
    Zoran

    Reply
    • Taiseer Joudeh says

      December 24, 2015 at 3:13 am

      Hi Zoran, good question, and to be honest I have no answer for it yet. If you found a solution please share it here.

      Reply
      • Matthew Flynn says

        April 1, 2016 at 1:50 pm

        Hi Taiseer,

        I’m not sure if its still of interest but I added the following to the unprotect mehtod (its not great but ti works)

        public AuthenticationTicket Unprotect(string protectedText)
        {
        if (protectedText == null) throw new ArgumentNullException(“jwt”);

        //requires the issuer to send across their audience id in the claim
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
        var jwt = tokenHandler.ReadToken(protectedText) as JwtSecurityToken;
        var audienceId = jwt.Claims.FirstOrDefault(x => x.Type == “aud”).Value;

        if (audienceId == null) throw new InvalidOperationException(“Error the audienceid is not included in the claims”);

        //find the client in the repo and validate
        Client client = null;

        using (AuthRepository _repo = new AuthRepository())
        {
        client = _repo.FindClient(audienceId);
        }

        if (client == null) throw new InvalidOperationException(“ClientId does not exist.”);

        string symmetricKeyAsBase64 = client.Secret;
        var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
        var signingKey = new HmacSigningCredentials(keyByteArray);

        SecurityToken token = null;

        var validationParameters = new TokenValidationParameters
        {
        IssuerSigningKey = signingKey.SigningKey,
        ValidAudience = client.Id,
        ValidIssuer = _issuer,
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateIssuerSigningKey = true,
        ValidateLifetime = true
        };

        //validate the jwt
        JwtFormat jwtFormat = new JwtFormat(validationParameters);

        var ticket = jwtFormat.Unprotect(protectedText);

        if(ticket == null) throw new ArgumentException(“Invalid token”);

        return ticket;
        }

        it works and if theres any improvements that can be done here let me know!

        Reply
        • Taiseer Joudeh says

          April 3, 2016 at 1:29 am

          Thanks Matthew for sharing this, I will review it soon and for sure it might be useful for a reader who is looking at the comments, sometimes the comments have more information compared to the original post 🙂

          Reply
  72. Muhammad Ali says

    January 4, 2016 at 6:29 am

    Hi Taiseer,

    This is a very useful article. I have a question around how can this be used to provide SSO between a number of Resource Servers?

    Thanks
    Ali

    Reply
  73. kapacoo says

    February 19, 2016 at 12:07 pm

    Hi Taiseer,
    Our AuthorizationServer using mutual ssl in DelegatingHandler.
    DelegatingHandler : checking client certificate.
    but ,, http://jwtauthzsrv.azurewebsites.net/oauth2/token calling time

    DelegatingHandler is not working.

    Reply
  74. Guru Pitka says

    March 17, 2016 at 7:04 pm

    Wow!! Great article. very detailed and helpful as always.

    I have AuthServer (web-api) and a ResourceServer (MVC).
    The JWT tokens, [Authorize] Attribute and Cookie are all works as expected.

    But – I have a Login endpoint (on MVC) which the users can pass his credentials and will be sent to the AuthServer. i’m getting the access_token. then i need to call:Request.GetOwinContext().Authentication.SignIn(identity),
    but i don’t know how to extract the Claims from the access_token in order to pass the identity to the SignIn method.

    any directions?

    Reply
  75. Arsénio Costa says

    April 8, 2016 at 1:24 pm

    Hi TAISEER,
    Great tutorial I have followed it and it serves my purposes just great, now i am implementing impersonation in my javascript client any toughts on how to do that ?
    I have added an header to the login request on my client saying if we’re impersonating or not someone and in my custom OAuthAuthorizationServerProvider i check for that so i can login without cheking the password, but now i need to check for the authentication of the caller on the GrantResourceOwnerCredentials method however the Owin.OwinContext.Authentication).User is null, as i suspect calls to GrantResourceOwnerCredentials are not authenticated (after all thats what we’re doing in the method) any tips ?

    Reply
  76. Frauke Nonnenmacher says

    April 12, 2016 at 6:18 pm

    Hi, Taiseer, first off, thanks for the excellent tutorial! I do have one (newbie) question, however. As I understand it, if I have a client app that wants to consume the Web Api of a resource server, I first go to the authorisation server to get a token, and then the client app takes the token and uses it within the request it sends to the resource server, right?

    However, as far as I can see from the ValidateClientAuthentication method, the client app would need to pass the resource server’s audience id to the authorisation server in order to get authorised and receive the correct token. How would the client app get that audience id? Simply adding a controller to the resource server that exposes an Api that allows just anybody to retrieve the id doesn’t seem a very secure way of going about it.

    Reply
  77. xqlun says

    April 13, 2016 at 1:41 pm

    How can I revoke a Json Web Token actively?

    Reply
    • Taiseer Joudeh says

      April 19, 2016 at 8:58 pm

      You can not revoke self-contained tokens, you should wait until they expire

      Reply
  78. starnb says

    April 14, 2016 at 11:46 pm

    A great article, detailed and very helpful as always. I have one clarification though.

    I see you are using client_id to pass identifier for the audience. This may work for AuthorizationCode Grant however for ResourceOwnerCredential Grant and ClientCredentials Grant there seem to a problem of how to pass “audience id” from the client as the client_id will contain the actual client identifier. Any thoughts?

    Reply
  79. Assad Faizi says

    April 20, 2016 at 12:41 pm

    Taiseer, great set of articles.

    I have a question with regards to signing the JWT. In practice, should we sign the token using a certificate rather than simply using HmacSigningCredentials? Is this more suited for development purposes or “Good Enough” for production?

    Reply
    • Taiseer Joudeh says

      April 27, 2016 at 2:10 am

      Hi Assad,
      Certificate is the way yo go with production apps, it is more secure way.

      Reply
  80. Diego Chapeton says

    April 21, 2016 at 5:29 am

    Hi Taiseer thank you for the post, it´s very good.

    I have two questions,
    How can i update the token? is necesary generate other token? is not?.
    How can I close session if the token is active?

    thank you for you time.

    Reply
    • Taiseer Joudeh says

      April 27, 2016 at 2:09 am

      Hi Diego, thanks for your comment,

      Self-contained tokens can’t be updated, any change on it is content will affect the token and it is a signature and invalidate it, so you need to generate a new one when you update the user profile.

      Reply
  81. Krishna says

    April 24, 2016 at 6:51 am

    Hi Taiseer,
    Just to clarify,at resource server (API), If i set these options for UseJwtBearerAuthentication
    options.Authority = “”;
    options.Audience = “”;
    options.AutomaticAuthenticate = true
    resource server will make a round trip to Authorization server and validate the access token?

    Reply
    • Taiseer Joudeh says

      April 27, 2016 at 1:50 am

      Hi Kirshna,
      There should be no direct communication between the resource server and the authorization server, the resource server will validate that the token received is issued by a trusted issuer (Authorization server) using the secret provided by AythZ server upfront when registering the resource server.

      Reply
  82. tom says

    May 2, 2016 at 12:56 am

    How would you envisage an onboarding/first issue scheme by the auth server? Would you be adding some kind of email or token/pin code auth on first request as a callback to then issue the token or how would you generally see that process working?

    Reply
    • Taiseer Joudeh says

      May 2, 2016 at 11:33 am

      Hi Tom,
      Could you elaborate more, I didn’t get your question.

      Reply
  83. GhaMe says

    May 2, 2016 at 9:49 am

    Hi, thank you for this article, as a beginner for oAuth2 it help me understand the flow of oAuth2 using OWIN and JWT. Quick questions for you, how come I am always getting an “Invalid Client Id” when I tried to request for token from http://jwtauthzsrv.azurewebsites.net/oauth2/token? I was able to register and received a valid client id from http://jwtauthzsrv.azurewebsites.net/api/audience but no success from requesting a token using the client Id that I received.

    Thanks,
    GhaMe

    Reply
    • Taiseer Joudeh says

      May 2, 2016 at 11:27 am

      Hi Grahame,
      I’m afraid that you are sending the client id and client secret incorrectly in the request, can you make sure you are using the correct content-type, it should not be JSON, it should be “x-www-form-urlencoded”

      Reply
  84. Rob Lapp says

    May 9, 2016 at 6:33 pm

    Hey Taiseer, I keep calling your end point (with Postman) http://jwtauthzsrv.azurewebsites.net/api/protected after adding an audience and successfully generating a token. I am getting a 404. Do you still have the site on Azure? great article!

    Reply
    • Taiseer Joudeh says

      May 12, 2016 at 12:37 am

      Hi Rob,
      I’m afraid not, the azure subscription I used to host apps on it is expired now, sorry about this.

      Reply
  85. Ganesh Kumaresan says

    May 11, 2016 at 1:25 pm

    Hai Taiseer,

    I have passed the data as,

    {“client_id”:”099153c2625149bc8ecb3e85e03f0022″,”username”:”myApp”,”password”:”myApp”,”grant_type”:”password”}

    to the url,

    http://localhost:18292/oauth2/token

    content-type: application/xxx-www-form-urlencoded

    For the above requests it is giving 403 response. It is not giving token. Am I doing right?? Can u help me, Pls.

    Regards,
    Ganesh. K

    Reply
    • Taiseer Joudeh says

      May 12, 2016 at 12:20 am

      Hi,
      You are receiving 403 when you invoke the Api from postman? If it is not working you should receive 401 not 403.

      Reply
  86. Arvind Agrahari says

    May 12, 2016 at 3:09 pm

    Hey Taiseer,

    After adding an audience and successfully generating a token. With token i’ve successfully accessed ‘api/protected’.

    Is token(ResourceServer A) is readable to another ResourceServer(B) server that authorized with same AuthorizationServer ?

    great article!

    Reply
    • Taiseer Joudeh says

      May 23, 2016 at 11:18 am

      Hi, it should not be accessible if they are using different Audience ID, each token will be issued for certain audience.

      Reply
  87. Joseph El Khoury says

    May 13, 2016 at 4:30 pm

    Hi Taiseer,

    Can you please describe why the client_id in the request is set to the audience id ?
    If i have only one Resource server should i include the audience id ?

    Thank you.
    Regards

    Reply
  88. Ebimie Abari says

    May 28, 2016 at 7:25 pm

    Hi Taiseer,

    Very insightful I must say. Everything works perfect when I followed your post. however, I need to make the authentication server read audiences from the database where they are stored instead one single constant audience. How do archive this. Thank you.

    Reply
  89. Maicon Matsubara says

    May 31, 2016 at 9:03 pm

    Hi Taiseer!

    I am developing a project that needs to use SSO (Single Sign-On) strategy, but, as I saw, I cant use your example (great, by the way) in my solution or, if I use it, I will need to define the same key to all audiances. So, in this case, nothing changes between this and the machine key solution. Am I right?

    Thank you!

    Reply
    • Taiseer Joudeh says

      May 31, 2016 at 11:02 pm

      Hi Maicon,

      You are right, if you need to enable SSO you need to unify the key, my post was about creating a very simple Authorization server where multiple resource servers can rely on. If you ae looking for SSO service, my recommendation is to take a look at the ThinkTecture Identity Server.

      Reply
  90. Tiago Louis Zontag says

    June 1, 2016 at 8:42 pm

    Hi Taiseer. This article is really useful.

    Pls, tell me. There is anyway to add more audience to resource server in run time?

    Thank you!

    Reply
  91. Rakesh says

    June 12, 2016 at 3:39 pm

    Hello,

    How I will get audience (Client id) in below mentioned code dynamically rather than hard-coded. Once I will audience client than i get secret-key from database and can dynamically pass it to below mentioned code. I observed that you are adding clientid in AuthenticationProperties of JWT but I dont know how to get this clientId.

    Your quick reply will highly appreciated

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

    }

    Reply
  92. David says

    June 28, 2016 at 6:30 pm

    Hi Taiseer,

    HmacSigningCredentials cannot convert to SigningCredentials, After upgrading System.IdentityModel.Tokens.Jwt to 5.0

    Please help.
    Regards

    Reply
  93. Tomy Dong says

    July 4, 2016 at 12:30 pm

    JwtSecurityToken use a microsoft.identityModel.token.signningcredentials not HmacSigningCredentials. please help me

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

    Reply
    • Taiseer Joudeh says

      July 10, 2016 at 11:02 am

      What is the exact error please?

      Reply
      • Oliver says

        August 7, 2016 at 4:07 pm

        When using the latest versions of

        Install-package System.IdentityModel.Tokens.Jwt
        Install-package Thinktecture.IdentityModel.Core

        Then you get the following error:
        Error BC30311 Value of type ‘HmacSigningCredentials’ cannot be converted to ‘SigningCredentials’

        Reply
        • Taiseer Joudeh says

          August 8, 2016 at 10:42 am

          Hello Oliver,

          Thanks for the update, to be honest I didn’t check them with latest version, but I will try them soon. meanwhile If you found a fix for the issue please share it here so others can benefit from it. Thank you.

          Reply
        • Nuno Leong says

          October 3, 2016 at 4:54 pm

          Hi Oliver,

          As Taiseer mentioned, if you use the versions he indicated in the article you’ll be fine. If you want to upgrade though, here’s what happened.

          Microsoft incorporated the Microsoft.IdentityModel.Tokens members into the .NET framework, effectively as System.IdentityModel.Tokens. See here:
          https://msdn.microsoft.com/en-us/library/microsoft.identitymodel.tokens.aspx

          So what’s happening is you’re caught in the middle of this change:
          – Thinktecture.IdentityModel.Core (1.2.0) extends class Microsoft.IdentityModel.Tokens.SigningCredentials
          – Thinktecture.IdentityModel.Core (1.3.0+) extends class System.IdentityModel.Tokens.SigningCredentials
          – System.IdentityModel.Tokens.Jwt (4.0.0) references Microsoft.IdentityModel.Tokens.SigningCredentials
          – System.IdentityModel.Tokens.Jwt (4.0.3) references System.IdentityModel.Tokens.SigningCredentials

          So basically you need to make sure you have versions that match the namespace. If you’re using Thinktecture 1.3.0, than update System.IdentityModel.Tokens.Jwt to 4.0.3 (do NOT update to 5.0.0)

          Best,

          Reply
  94. Manav says

    August 2, 2016 at 1:28 pm

    Hi Taiseer,
    very helpful article. Thanks. I have a question though. How do we refresh the token before it expires. It would be nice if you post an article in continuation to this article.

    Thanks
    Manav

    Reply
    • Taiseer Joudeh says

      August 2, 2016 at 11:53 pm

      Please check this post, I believe it will help answering your questions.

      Reply
  95. eeidfn says

    August 4, 2016 at 10:04 pm

    How do I convert the Thinktecture.IdentityModel.Tokens.HmacSigningCredentials to Microsoft.IdentityModel.Tokens.SigningCredentials?

    var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey); gives the below error:
    Error CS1503 Argument 6 signingKey: cannot convert from ‘Thinktecture.IdentityModel.Tokens.HmacSigningCredentials’ to ‘Microsoft.IdentityModel.Tokens.SigningCredentials’ in AuthorizationServer.Api

    Reply
    • Taiseer Joudeh says

      August 8, 2016 at 10:55 am

      I think you are using the latest version of the NuGet packages, somehow it is not compatible with the current post, I do not have an answer for this now but if you used the same packages version used in the post then it should work.

      Reply
  96. AOzD4v says

    August 13, 2016 at 3:39 pm

    Fix for latest nuget packages:

    var signingCredentials = new SigningCredentials(new SymmetricSecurityKey(keyByteArray), SecurityAlgorithms.Sha256Digest);

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

    Reply
    • bgs264 says

      August 19, 2016 at 3:55 pm

      Thanks man, this single comment made me stop tearing my hair out!

      FYI you can also remove the need for the Thinktecture package by doing this stuff.

      Send my best wishes to your family also.

      Reply
  97. Sanvid Maniyar says

    October 4, 2016 at 10:23 am

    Hi,

    When I try with URL http://jwtauthzsrv.azurewebsites.net/oauth2/token, it seems working fine and provided me with the correct result. But I am doing the same with my ADFS server (http://my_ADFS_server/oauth2/token ) and not able to pass the username and password.

    I search a bit and came to know that

    “AD FS 3.0 (2012 R2) DOES NOT support grant_type=password for OAuth 2.0 but it supports grant_type=authorization_code and grant_type=refresh_token only”

    “AD FS provides WS-Trust endpoints and you could use them instead of OAuth 2.0 endpoint for issuing and exchanging tokens”

    So, is there any way to make it work or how do I made above code working with “authorization_code”.

    If you can guide me for the same because I want to make SSO with multiple intranet applications based on JWT.

    Regards,
    Sanvid

    Reply
Newer Comments »

Trackbacks

  1. How to pass client_id and client_secret in http request header? | stackoverflow.com.pl says:
    September 2, 2015 at 6:53 pm

    […] am new to OAuth2 JWT based authentication and was trying to implement the same according to this article. This shows how to pass the client_id and client_secret in request body using […]

    Reply
  2. JWT Bearer Token Authentication & Authorization Front-End in ASP.NET MVC | 60-Second Tutorial {C#} says:
    December 13, 2015 at 9:40 am

    […] the blog of Taiseer Joudeh at https://bitoftech.net/2014/10/27/json-web-token-asp-net-web-api-2-jwt-owin-authorization-server/, I was able to build a JSON Web Token Authorization Server and Resource Server in ASP.NET API 2 […]

    Reply
  3. Combining social logins with the JWT flow from this blog post (link inside) - How to Code .NET says:
    July 9, 2016 at 12:01 am

    […] This blog post show how to implement an authorization server that is decoupled from the resource server and using JWT. […]

    Reply

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 ASP.Net 5 Authentication Autherization Server Azure Active Directory Azure Active Directory B2C Azure AD B2C basic authentication Code First Dependency Injection Documentation Entity Framework Entity Framework 7 Facebook Foursquare API Google Authenticator Identity jQuery JSON JSON Web Tokens JWT MVC 6 Ninject OAuth OData Resource Server REST RESTful RESTful. Web API Single Page Applications SPA Swagger-ui Swashbuckle TFA Token Authentication Tutorial Two Factor Authentication Web API Web API 2 Web API Security Web Service

Search

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