Policy-based Authorization Using Asp.Net Core 2 And Json Web Token (JWT)

I’ve been tinkering with different options to secure the API endpoint of one of my Asp.Net Core apps. What I end up using was IdentityServer4, primarily because my app needed Single sign-on too. But for straightforward scenarios, I think IdentityServer4 is an overkill. That’s where JWT comes in, so in this post, I’m going to share what I’ve learned using JWT in Asp.Net Core 3.1. In my next post I’m going to do the same thing with IdentityServer4.

So let’s say I have an Insecure API like this.

Our goal is to implement policy-based authorization that uses the built in Asp.Net Core Identity claim. By doing so only people who fit a particular policy can use this API.  In this example, only people who has the claim “Employee” with the value “Mosalla” should be able to access our API. I’m going to explain what I did step by step, and give you the sample code in the end.

Adding JwtBearer To Startup.cs

The first step we need to take is to add the JwtBearer in ConfigureServices part of our Asp.Net Core app. There is no need for additional package, JWT is now part of Asp.Net Core authentication and lives in AspNetCore.Authentication.JwtBearer namespace. We do this by using the AddJwtBearer extension method, here the complete code for Startup.cs.

The AddJwtBearer has some options which I’ve used. The first option is RequireHttpsMetadata which determines if HTTPS is required. This should always be true for production environments, I only turned it off because I wanted to make things easier during development. The reason this is important is the nature of Bearer tokens. Which means whoever carry this token, can have access to our resources. Any system that implement JWT grants access to whoever has the token. It doesn’t care who owns this token, that is the identity of the owner, only the token’s validity. So it’s imperative to use SSL to make sure our tokens are not stolen while travel across the wire.

The TokenValidationParameters property can help us substantiate the validity of the incoming token. By setting this property the issuer, audience and sign in key are added to the every token that our system is going to generate.

Also on line 53 I’ve declared a policy called Trusted which which I’m going to use to secure our API. Now we can secure our API by adding authorize attribute and our policy to it. Also note that we should instruct Asp.Net Core to use AuthenticationSchemes of JwtBearerDefaults.AuthenticationScheme. You could either set your DefaultAuthenticateScheme in AddAuthentication options in startup, or set it explicitly on our action method. The reason I didn’t set it in startup is that I wanted to use JWT alongside cookie authentication. By doing so I have to explicitly set the AuthenticationSchemes whenever I want to use the JwtBearer to secure my API action methods.

The next step is creating a class to generate access tokens.

Generating JWT Access Token

Now what we need is some kind of endpoint to create access token if the provided credentials where valid.

We first check to see if the incoming credentials are valid, if they are, we read the user claims. After that we add the JWT related tokens to the list of user’s claim. Next we create an instance of SymmetricSecurityKey and SigningCredentials and pass them along with user’s claims to JwtSecurityToken constructor to create a JWT access token. Now people who want to access our API needs to make a request to Token/Generate. If their credential were valid they receive an access token. They should use that access token to set the HTTP Authorization header of their request. Finally they can send their request to the secured API. As far as securing our API goes, we’re done. Next step is to make a request to that API with the Username and Password of the user that we’ve created to see if it works correctly.

Create User And Add Claim For it

Now we need to register a user and add the necessary claim to it. Once user registered and logged in, I’ve added a link which navigates us to the action that adds the claim.


Normally we shouldn’t use a trivial get method to change state in our system, but for this example it suffice.

Call The API With Our Credentials

Now we need to make a request to the API, we do this with HttpClient, consider the following code.

First we need to get an access token, we do this by calling GetAccessToken and this method in turn create an HttpContent that PostAsync needs by creating an instance of StringContent class. We pass our Username and Password along with encoding and media type for our post request. We make the request and return the access token. Now that we have a access token we can set the DefaultRequestHeaders.Authorization property of our HttpClient. Here we pass Bearer for our Authentication Scheme, and our access token. Here’s what we’ll get if the call to our API was successful.

Now let’s enter the wrong password to see what we’ll get.

Note that not only our Username and Password should be correct, but also our user should fit the Trusted policy that we set earlier. So it means if your delete the user’s claim from AspNetUserClaims table, our request is not authorized.

Summary

In this post, I’ve explained how we can use JWT with Asp.Net Core 3.1 to implement policy-based authorization for our API. You can find the sample project for this post here. This post was part of a series of posts which I intend to write, in my next post I’ll show you how to do the same thing using IdentityServer4.

Share...
 

Hamid Mosalla

Hi, I'm Hamid Mosalla, I'm a software developer, indie cinema fan and a classical music aficionado. Here I write about my experiences mostly related to web development and .Net.

 

3 thoughts on “Policy-based Authorization Using Asp.Net Core 2 And Json Web Token (JWT)

  1. Isn’t this supposed to apply as default? and skip specifying the schema in the Authorize attribute?
    (this is what i’ve supposeed that it does but i didn’t get it working either)

    /*o =>

    {

    o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;

    o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;

    o.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;

    }*/ /*Uncomment this if you don’t want to use JWT for all of your api*/

    1. As far as I can remember you can either set the schema in startup and this will be used across the project, or you can set it via attribute on action by action cases.

Leave a Reply

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