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
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.
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
JwtBearerDefaults.AuthenticationScheme. You could either set your
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
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
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.
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.