I'm trying to support JWT bearer token (JSON Web Token) in my web API application and I'm getting lost.
I see support for .NET Core and for OWIN applications.
I'm currently hosting my application in IIS.
How can I achieve this authentication module in my application? Is there any way I can use the <authentication>
configuration similar to the way I use forms/Windows authentication?
Best Answer
I answered this question: How to secure an ASP.NET Web API 4 years ago using HMAC.
Now, lots of things changed in security, especially that JWT is getting popular. In this answer, I will try to explain how to use JWT in the simplest and basic way that I can, so we won't get lost from jungle of OWIN, Oauth2, ASP.NET Identity... :)
If you don't know about JWT tokens, you need to take a look at:
https://www.rfc-editor.org/rfc/rfc7519
Basically, a JWT token looks like this:
Example:
A JWT token has three sections:
If you use the website jwt.io with the token above, you can decode the token and see it like below:
Technically, JWT uses a signature which is signed from headers and claims with security algorithm specified in the headers (example: HMACSHA256). Therefore, JWT must be transferred over HTTPs if you store any sensitive information in its claims.
Now, in order to use JWT authentication, you don't really need an OWIN middleware if you have a legacy Web Api system. The simple concept is how to provide JWT token and how to validate the token when the request comes. That's it.
In the demo I've created (github), to keep the JWT token lightweight, I only store
username
andexpiration time
. But this way, you have to re-build new local identity (principal) to add more information like roles, if you want to do role authorization, etc. But, if you want to add more information into JWT, it's up to you: it's very flexible.Instead of using OWIN middleware, you can simply provide a JWT token endpoint by using a controller action:
This is a naive action; in production you should use a POST request or a Basic Authentication endpoint to provide the JWT token.
How to generate the token based on
username
?You can use the NuGet package called
System.IdentityModel.Tokens.Jwt
from Microsoft to generate the token, or even another package if you like. In the demo, I useHMACSHA256
withSymmetricKey
:The endpoint to provide the JWT token is done.
How to validate the JWT when the request comes?
In the demo, I have built
JwtAuthenticationAttribute
which inherits fromIAuthenticationFilter
(more detail about authentication filter in here).With this attribute, you can authenticate any action: you just have to put this attribute on that action.
You can also use OWIN middleware or DelegateHander if you want to validate all incoming requests for your WebAPI (not specific to Controller or action)
Below is the core method from authentication filter:
The workflow is to use the JWT library (NuGet package above) to validate the JWT token and then return back
ClaimsPrincipal
. You can perform more validation, like check whether user exists on your system, and add other custom validations if you want.The code to validate JWT token and get principal back:
If the JWT token is validated and the principal is returned, you should build a new local identity and put more information into it to check role authorization.
Remember to add
config.Filters.Add(new AuthorizeAttribute());
(default authorization) at global scope in order to prevent any anonymous request to your resources.You can use Postman to test the demo:
Request token (naive as I mentioned above, just for demo):
Put JWT token in the header for authorized request, example:
The demo can be found here: https://github.com/cuongle/WebApi.Jwt