ASP.NET; ASP.NET Core; Learn. Learn About ASP.NET Web API. ASP.NET Web API is a framework that. This tutorial shows how to use ASP.NET Web API in an ASP.NET Web. When ASP.NET Core was released, Microsoft and the.NET community decided to merge the functionality of MVC and Web API. This makes sense since the two have always been very similar. We went through the process of making an ASP.NET Core Web API with various scenarios and came up with these tips for.
There are a few resources that you can find that teach how to secure an ASP.NET Core web application. I’ve written a few, for example ASP.NET Core Identity From Scratch, External Login Providers in ASP.NET Core and Facebook Authentiation with ASP.NET Core.
For web apis using ASP.NET Core it’s a little bit harder to find information. That’s what this blog post is about.
In this blog post I’ll explain how you can use Json Web Tokens (JWT) to secure a Web Api in ASP.NET Core. There’s a demo project in github that you can use to follow along.
Using a token instead of a cookie
The most common way to keep track of a signed in user in a web application is to use cookies.
The normal flow is: the user clicks login, goes to a login page and after entering valid credentials the response that is sent to the user’s browser contains a
Set-Cookie
header that contains encrypted information.Every time a cookie is set for a domain, e.g. blinkingcaret.com, on every subsequent request for that domain the browser will include the cookie automatically.
On the server that cookie is decrypted and its contents are used to create the user’s identity.
This process works very well if the client is a browser, it’s a different story when we the client is a mobile app.
JWT
What we can use instead of a cookie is a token. A token also represents the user, but when we use it we don’t rely on the browser’s built-in mechanism to deal with cookies.
We have to explicitly ask for a token, store it ourselves somewhere, and then manually send it with every request. There are some ways to make this as painless as possible and I’ll discuss some of them later in this the post.
The token format I’ll be talking about here is JWT. JWT stands for Json Web Token.
A JWT token has the following format:
base64-encoded-header.base64-encoded-payload.signature
.An example of a header is
{
“alg”: “HS265”,
“typ”: “JWT”
}
{
“alg”: “HS265”,
“typ”: “JWT”
}
The payload contains a list of claims, for example:
Finally the signature is created by taking: “base64(header).base64(payload)” and cryptographically signing it using the algorithm specified in the header. For example HMAC-SHA256. The signing part involves using a secret that is only known at the server.
Here’s how a real JWT looks like:
It is important to be aware that the information contained in the JWT is not encrypted. To get the payload you just need to base64-decode it. You can even do that from your developer tools console (for example in chrome). Use the
atob
method and pass the payload as an argument. You’ll see that you’ll get JSON back.The signature guarantees that if someone tries to replace the payload, the token becomes invalid. For someone to be successful in replacing the payload and producing a valid token they would need to know the secret used in the signature, and that secret never goes to the client.
This is something to have in mind when you decide what to put in the payload.
Using JWT in ASP.NET Core
To use JWT in ASP.NET Core we need to know how to manually create JWT tokens, how to validate them and how to create an endpoint so that the client app can request them.
How to create a JWT token
First you need to install the package System.IdentityModel.Tokens.Jwt:
Now we need to create a secret key. We are going to use a symmetric key, here’s how we can do that:
Our token will contain a set of claims. So lets create them:
I’ve used both
ClaimTypes
(from System.Security.Claims) and JwtRegisteredClaimNames
(from System.IdentityModel.Tokens.Jwt) to highlight that JwtRegisteredClaimNames
contains the claims that are listed in the JWT RFC. You should use those as much as possible if you are planning to use the produced tokens with different frameworks for compatibility reasons. However, there are some claim types that enable certain functionalities in ASP.NET. For example ClaimTypes.Name
is the default claim type for the user’s name (User.Identity.Name
). Another example is ClaimTypes.Role
that will be checked if you use the Roles property in an Authorize attribute (e.g. [Authorize(Roles='Administrator')]
).After creating the list of claims we want to encode in the token we can create the token itself, here’s how we can do it:
There are a few concepts here that I didn’t mention before, namely the issuer, audience and expiration dates.
The issuer represents the entity that generates the tokens, in this case it will be the ASP.NET Core web application. The audience is who the tokens are intended to, i.e. the client application. This issuer and the audience are important if your are relying on a third party to create the tokens (not the case here). You can validate both the issuer and the audience when you validate the token.
The
notBefore
and expires
define after what point in time the token can be used and until when it is valid, respectively.Finally in the
signingCredentials
you specify which security key and what algorithm to use to create the signature. In the example we used HMAC-SHA256.If you don’t care about the
issuer
and audience
(which are optional in the JWT specification), you can use the simpler constructor overload of JwtSecurityToken
that expects a JwtSecurityHeader
and JwtSecurityPayload
. You’ll have to manually add the expires
and notBefore
claims yourself to the payload, for example:Note that the
Exp
(expires) and Nbf
(notBefore) claims’ value is a string with Unix time. The easiest way to convert a DateTime
to that format is using DateTimeOffset
.After creating an instance of
JwtSecurityToken
, the way to actually generate the token is to call the WriteToken
method of an instance of JwtSecurityTokenHandler
and pass the JwtSecurityToken
as a parameter:Creating an endpoint to get the token
Now that we know how to create our JWT tokens we need a way to enable the client to get them. The easiest way to do that is to create a web api controller action that expects a post request, for example, this would work:
Where in
IsValidUserAndPasswordCombination
you can use, for example ASP.NET Identity to validate the user’s credentials (if you need a resource for how to setup ASP.NET Identity check ASP.NET Identity Core From Scratch).GenerateToken
is the process we just described in the previous section.Validating the token and “signing in” the user
Now that we have a way to issue tokens we need a way to validate them. We’ll be using ASP.NET Core’s authentication middleware and configure it to accept JWT tokens.
Add the
Microsoft.AspNetCore.Authentication.JwtBearer
NuGet package to your project.Next open Startup.cs and update the
ConfigureServices
method:If you are not familiar with ASP.NET Core’s authentication middleware I recommend reading External Login Providers in ASP.NET Core. Even though it’s about enabling signing in through Google, Facebook, etc it provides a detailed explanation of how authentication middleware works.
Also, be aware that this is the new ASP.NET Core 2.0 syntax where authentication is fully configured via the
ConfigureServices
method, however the concepts are the same.More importantly in this example is the
TokenValidationParameters
class. It’s the class you have to instantiate to configure how the token should be validated.In
Startup.cs
you need to update the Configure
method and add the authentication middleware:Client
The web api client can be a desktop app, mobile or even a browser. The example I’ll be describing is that of a web application that signs in, saves the token and then uses it to perform authenticated requests. You can find a working example here.
First, to sign in you need to send a POST request to “/token” (or wherever you’ve setup the web api endpoint to generate the token) with a username and password. You can easily do that with jQuery:
If all goes well with the POST you get the JWT back and you can save it somewhere, usually in local storage in the case of a web application. On mobile it depends on the platform you are using but they all have facilities that allow you to save the token (e.g. Android’s
SharedPreferences
).For the authentication middleware in the previous section to accept a JWT token and transform it in a
User
that you can then access in your controller action the request must have an Authorization header. The value of the header should be “Bearer ” followed by the JWT token, for example:Although you can “manually” add the
Authorization
header to every request, there’s usually ways to do that automatically. For example in jQuery there’s an event that you can use that runs before every request where you can check if you have a saved token, and if that’s the case, add the Authorization
header to the request:There are similar mechanisms if you are using other frameworks, for example Angular has HttpInterceptors.
Finally, to logout you just need to remove the token from local storage:
One thing to be aware of is that if the client performs an action that requires the user to be authenticated and there’s no (valid)
Authorization
header in the request, the server will respond to that request with a response with status code 401. The response will also have a WWW-Authenticate:Bearer header. If you receive a response like this you can notify the user that authentication is required.