Originally posted on https://samueleresca.net
Developing token authentication using ASP.NET Core
Introduction
The following article shows how to developing token authentication using ASP.NET Core.
I have already written about ASP.NET Core here:
- Future of ASP.NET is open source and cross platform;
- Introducing ASP.NET 5 on Ubuntu;
- Querying MongoDB using .NET Core;
Token based authentication overview
Nowadays, Token based authentication is very common on the web and any major API or web applications use tokens.
Token authentication is stateless, secure and designed to be scalable. In fact, it is quickly becoming a de facto standard for modern single-page applications and mobile apps.
The problems with server based authentication
Authentication is the process by which an application confirms user identity. Applications have traditionally persisted identity through session cookies, relying on session IDs stored server-side. A few major problems caused by this technique:
- Scalability: if sessions are stored in memory, this provides problems with scalability;
- CORS: as we want to expand our application to let our data be used across multiple mobile devices, we have to worry about cross-origin resource sharing (CORS);
- CSRF: we will also have protection against cross-site request forgery(CSRF);
- Sessions: Every time a user is authenticated, the server will need to create a record on our server;
How token based authentication works
Token based authentication is stateless. It don't store any information about our user on the server or in a session.
Here's the common steps of the token based authentication:
- user requests access by using username / password;
- application provides a signed token to the client;
- client stores that token and sends it along with every request;
- server verifies token and responds with data;
Every single request will require the token. The token should be sent in the HTTP header to keep the idea of stateless HTTP requests.
Implementing Token based authentication using ASP.Net Core
This example shows how to developing token authentication using ASP.NET Core, the following  UML schema shows the architecture of project:
Setup the project
First of all, is necessary create new ASP.NET Core project. I suggest to use ASP.NET Yeoman Generator to generate project using Web application template and Visual Studio Code to edit the code.
Once the project is successfully created, add the following configurations to your appsettings.json
:
https://gist.github.com/978e16a046424d00e933eca778702d93
The TokenAuthentication
section configures some common information about token generation, for example the SectionKey
used by token.
Tokens transmission / validation
There are two ways to transmit the authorization tokens:
- using  HTTP Authorization headers (aka  Bearer authentication);
- using browser cookies to save the authentication token;
Bearer token validation
The  Microsoft.AspNetCore.Authentication.JwtBearer
package enables you to protect routes by using a JWT Token.
To enable Bearer token authentication, import the following Nuget package Microsoft.AspNetCore.Authentication.JwtBearer
 in the project.json:
https://gist.github.com/samueleresca/c4dd98829e7b8d3e830255cf958c6333
To initialize the Bearer authentication you need to split your Startup.cs
file and use another partial class, for example Startup.Auth.cs
:
https://gist.github.com/samueleresca/66256d739cb20c0a848f8c43240f12b4
The Startup.Auth.cs
file initialize the Bearer Authentication using  configurations defined in the appsettings.json
file. The tokenValidationParamaters
object will be used also by Cookie validation.
Cookies validation
Cookies validation enables the Token transport over browser cookies, to enable the Cookie token authentication you need to add the following package inside the project.json
:
"Microsoft.AspNetCore.Authentication.Cookies": "1.0.0"
and  create a custom validator for the input token.
To create the new validator add the following CustomJwtDataFormat.cs
file:
https://gist.github.com/samueleresca/ec310b096a8543eb170d2fdebcbef8b7
Unprotect
method decript and validate information provided by the input token. Call the following method in the Startup.Auth.cs
file, to use the Cookie authentication:
https://gist.github.com/samueleresca/424b2062a9cee7daa58672e5fdec0d1d
Token generation
There isn't native support to Token generation in ASP.NET Core, but it is possible write a custom token generator middleware from scratch.
Firstly, you need to create a class which implement token options :
https://gist.github.com/samueleresca/c475abd4a6831a23981a55d76223757b
The middleware class will use TokenProviderOptions.cs
to generate tokens:
https://gist.github.com/samueleresca/e4e7f1f06c6af12fb1b126a0479e0054
The TokenProviderMiddleware
class implement the Invoke
method to generate tokens by using the TokenProviderOptions
. In order to initialize the middleware, it is necessary modify the Startup.Auth.cs
file and add in the ConfigureAuth
method:
https://gist.github.com/samueleresca/4c8a8844a944005a4086fa20b0ebbfad
The tokenProviderOptions
defines the options of the token generator. The IdentityResolver
is the Task method which will check the identity of users. For demo purposes, the IdentityResolver
is implemented by a simple method called GetIdentity.
Final steps
Now is possible call the ConfigureAuth
method inside the Startup.cs
file:
https://gist.github.com/samueleresca/765a08c9681f8478074014f2c910a0f3
Getting token
You can obtain the JWT token by calling the following route /api/token/
using POST
and passing the username and password data:
POST api/token
Content-Type: application/x-www-form-urlencoded
username=TEST&password=TEST123
Authorize controllers
All controllers decorated by the attribute [Authorize]
are protected by the JWT authentication.
In each http call you need to pass the access_token
parmeter:
http://hostname/controller/route?access_token=MY_TOKEN
The demo code is available on Github.
Cheers :)
Top comments (26)
Very Nice. Thank you!!
The implementation since ok however when trying to access the api using the acquired token I get:
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET localhost:2709/api/values
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (null).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Warning: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware:Information: AuthenticationScheme: Cookie was challenged.
Seems that some part of the puzzle is missing.
Anyone have an idea why?
"In each http call you need to pass the access_token parmeter:
hostname/controller/route?access_t..."
Can i pass the token in the headers section (like, a cookie, for example)? or i need to pass the token in the url?
Edit: Nevermind, didn't saw your "Errata corrige:"
Great article! \o
Also ran the api/token with the username and password all worked well I got the toekn in return which I appened to a HTTP get call to the server but the authorization fails
Errata corrige:
You need to pass the token in the HEADER of the request:
When i pass the Authorization Bearer in header, it gives me this error:
The header name format is invalid.
This is how i'm passing it:
client.DefaultRequestHeaders.Add("Authorization:Bearer", json.accessToken);
where client is a HttpClient variable and json.accessToken is the value of the token.
Another approach..
If you download the tool Postman you can easily check how this works.
After you revieced your token, you just have to put into Header:
Key: Authorization
Value: Bearer YOUR_TOKEN
including the whitespace between Baerer and your token!
I get nothing but 401s using this very approach in Postman.
I get the following error when trying to build: 'TokenProviderOptions' does not contain a definition for 'NonceGenerator' and no extension method 'NonceGenerator' accepting a first argument of type 'TokenProviderOptions' could be found (are you missing a using directive or an assembly reference?)
I see in your TokenProviderOptions you do not have a property for NonceGenerator()?
Couldn't find it either, so I googled Blog.TokenAuthGettingStarted and navigated to the same file, for some reason I could find it in there.
/// <summary>
/// Generates a random value (nonce) for each generated token.
/// </summary>
/// <remarks>The default nonce is a random GUID.</remarks>
public Func<Task<string>> NonceGenerator { get; set; }
= () => Task.FromResult(Guid.NewGuid().ToString());
First of all, I thank you for this tutorial.. very useful..
I have a couple of questions (I'm new to JWT).
Let's say that I have a login page.
From this page I get the token.
I wonder to know how to pass it to the next controller (I use a redirect action when the credentials are correct) and globally how to add the famous header (Authorization:Bearer myToken) to all the controllers I use
My second question is how to manage the token refresh?
Thanks once again
First of all let me say this is an excellent post.
I have one question though.
I have implemented this with an WEB API project. If the user is not authorized (e.g. token expired) a 404 Not found is returned.
How can you return an unauthorized status instead of "404 Not found"
With cookies I had implemented it as such
Thanks
Shaheem
When I try to implement with a .Net Core 2.0 project I get the following error in the Startup.Auth.cs file:
"JwtBearBearerAppBuilderExtensions.UseJwtBearerAuthentication(IapplicationBuilder,JwtBearerOptions) is obsolete"
Any idea how to resolve?
Hi,
I think is solved here: github.com/aspnet/Home/issues/2007
Sam
Thanks for a great article! my question is how to refresh the token when it expires? or what's the mechanism I should adapt in order not to prompt my user for credentials when they're in the middle of doing something considering my token lifetime would only be 10 minutes.
Thank you for the article, it helped me a lot understanding Token generation/validation as I am new to all this asp.net/asp.net core universe.
I have a question though related with the middleware necessity. As you provided a route for the token generation (/api/token), I ask myself if another approach wouldn't be the implementation of the TokenProviderOption class as a Configuration/Option object as explained in this Microsoft doc (docs.microsoft.com/en-us/aspnet/co...) letting the TokenController manage token generation instead of creating a Middleware, apparently, just to hold the customized options for the token generation process.
I would be grateful for any insights on this matter!
When a request arrives with a valid token in the header, how should the end point determine which user the token is associated with?
The token contains all the necessary informations. For example, you can see token infos here: (jwt.io/)[https://jwt.io/]
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJURVNUIiwianRpIjoiZTI2NGQ3NzktZTg2Ni00NGVlLThjOTUtZmI5YTA3NjNhM2ViIiwiaWF0IjoxNTI0NTIzNjY2LCJuYmYiOjE1MjQ1MjM2NjYsImV4cCI6MTUyNDUyMzk2NiwiaXNzIjoiRGVtb0lzc3VlciIsImF1ZCI6IkRlbW9BdWRpZW5jZSJ9.SORiDZO7kohrJ-Ew_hsTtJ5r9Zqn1RN9sjSTJni7MDo
I am not able to install any packages for dotnet core, including the ones here.
Package Microsoft.AspNetCore.Identity 2.0.0 is not compatible with netcoreapp1.1 (.NETCoreApp,Version=v1.1). Package Microsoft.AspNetCore.Identity 2.0.0 supports: netstandard2.0 (.NETStandard,Version=v2.0)
One or more packages are incompatible with .NETCoreApp,Version=v1.1.
Package restore failed. Rolling back package changes for
this is the error I get when installing Microsoft.AspNetCore.Identity. Same for Microsoft.AspNetCore.Authentication.JwtBearer or any AspNetCore package. I have made sure that the project type is correct.
Thanks a lot for the Net.Core v2.0 UPDATE!!!
Token based authentication is great... until you need to revoke a token.
Amazing article, helped me a lot since I'm a beginner in token based auth. thank you!
Hey Samuele Is it possible to use token based authentication in simple asp.net project ,mean (without MVC ,wihtout Asp.net core) please tell me ,If yes then How ?