Security update: Make sure you read this security advisory if you handle JWTs in your code. The examples and sample code in this article have been updated to use the fixed version of the affected packages.

Token authentication is quickly becoming a de facto standard for modern single-page applications and mobile apps. Even traditional server-rendered applications and web APIs can take advantage of token authentication. The benefits are great: less server state to manage, better scalability, and a consistent identity and authentication mechanism across web and mobile clients.

If you need a refresher on how tokens work, read our overview of token authentication and JWTs. All clear? Great!

Token authentication in ASP.NET Core is a mixed bag. The ability to protect routes with Bearer header JWTs is included, but the ability to generate the tokens themselves has been removed and requires the use of custom middleware or external packages. Despite this, both MVC and Web API applications can benefit from using tokens for authentication, and it turns out it’s not very hard to set up.

How do you implement both sides of token authentication – token verification and token generation – on the new ASP.NET Core stack? I’ll break down the process step by step. All of the code in this post can be found on Github.

Cookies or Headers for Authentication?

First, some background. Authentication tokens (such as JWTs) are typically transmitted in the HTTP Authorization header, like this:

Tokens can also be transmitted via browser cookies. Which transport method you choose (headers or cookies) depends on your application and use case. For mobile applications, headers are the way to go.

For web applications, we recommend using HttpOnly cookies instead of HTML5 storage/headers, for better security against XSS attacks. It’s important to note that using cookies means that you need to protect your forms against CSRF attacks (by using ASP.NET Core’s AntiForgery features, for example).

Validating Tokens in ASP.NET Core

First, you’ll need to create a SecurityKey from your secret key. For this example, I’m creating a symmetrical key to sign and validate JWTs with HMAC-SHA256. You can do this in your Startup.cs file:

Validating JWTs in Headers

In your Startup class, you can use the UseJwtBearerAuthentication method in the Microsoft.AspNetCore.Authentication.JwtBearer package to require a valid JWT for your protected MVC or Web API routes:

With this middleware added to your application pipeline, any routes protected with [Authorize] will require a JWT that passes the following validation requirements:

  • The signature matches your server’s secret key
  • The expiration date (exp claim) has not passed
  • The not-before date (nbf claim) has passed
  • The Issuer (iss) claim matches “ExampleIssuer”
  • The Audience (aud) claim matches “ExampleAudience”
  • If there is not a valid JWT in the Authorization header, or it fails these validation steps, the request will be rejected. If you’re not familiar with the JWT spec, the Issuer and Audience claims are optional. They are being used here to identify the application (issuer) and the client (audience).

    Validating JWTs in Cookies

    Out of the box, the ASP.NET Core cookie authentication middleware doesn’t support validating JWTs passed via cookies. You’ll need to create a custom ISecureDataFormat implementation that validates a JWT string.

    Since you’re only validating tokens, not creating them, you only need to implement the Unprotect method. The heavy lifting can be handled by the JwtSecurityTokenHandler class in the System.IdentityModel.Tokens.Jwt namespace. The full custom formatter class looks like this:

    Wire this class up with UseCookieAuthentication in your Startup.cs file:

    That’s it!

    If an incoming cookie named access_token contains a valid JWT, your protected MVC or Web API routes will be authorized. If you want, you can do additional validation of the JWT claims (or copy the JWT claims into the ClaimsPrincipal object) inside of CustomJwtDataFormat.Unprotect.

    If you’re using cookies to transport your JWTs between the browser and the server, we recommend the following best practices for security:

  • Set the HttpOnly flag
  • Set the Secure flag as well, if your site is hosted on HTTPS (and it should be!)
  • Use the [ValidateAntiForgeryToken] attribute on any forms that accept a POST
  • That takes care of the validation side of token authentication, but what about generating the tokens themselves?

    Generating Tokens in ASP.NET Core

    Back in the ASP.NET 4.5 days, the UseOAuthAuthorizationServer middleware provided an endpoint that could easily generate tokens for your application. However, the ASP.NET Core team decided not to port it to ASP.NET Core.

    Never fear! I’ll demonstrate how to write a simple token-generating middleware from scratch, and then conclude with a few links to pre-built solutions that could save you some time.

    Writing a Simple Token Endpoint

    First, you’ll need a simple POCO (plain ol’ CLR object) to hold a few options for the middleware class you’ll write. Create a new class called TokenProviderOptions.cs:

    Now you can build the middleware class itself. The basic pattern for ASP.NET Core middleware is this:

    This scaffolding creates a middleware class that can be added to the ASP.NET Core application pipeline and accepts a TokenProviderOptions instance as a parameter. When a request enters the pipeline, the Invoke method checks the request path and skips if it doesn’t match the exact path the middleware should be handling (such as /token or /api/token). The token endpoint also shouldn’t respond to anything but a POST with a form-urlencoded body, so the request method and Content-Type are checked as well.

    The heavy lifting happens in GenerateToken. This method needs to validate a user identity (given a username and password), and generate a signed token (JWT) to pass back to the client if that identity exists:

    Most of this method is just plumbing code. It uses the JwtSecurityToken class to build up a JWT payload, and then JwtSecurityTokenHandler writes it to an encoded string. You can store any custom claim you want in the payload by simply adding it to the claims array.

    The task of validating a user’s identity given their username and password is further abstracted away to the GetIdentity method. In a real application, you’d plug this into your user database or an identity framework like ASP.NET Core Identity. For the purposes of this example, you can hardcode the lookup:

    All done! You can wire the new middleware class up in Startup.cs by adding the middleware to your application pipeline:

    Once you’ve added it, fire up the application and use a tool like Fiddler or Postman to send a POST request to the new endpoint:

    If the username and password are valid, you’ll get a token response:

    You can use a tool like jsonwebtoken.io to decode the JWT and see the payload.

    That’s it! You now have a endpoint that issues JWTs for valid users. If you’re writing a mobile or single-page application or web API, you can store the JWT and send it in the Authorization header on subsequent requests. If you want to store the JWT in a browser cookie, you’ll need to make a small modification to the endpoint so that it adds a cookie to the response.

    Other ASP.NET Core Authentication Solutions

    This example works, but it’s simple. It doesn’t support refresh tokens or other methods of exchanging user credentials for an access token. There are some community-led efforts to build rich ASP.NET Core token authentication functionality:

  • AspNet.Security.OpenIdConnect.Server – Similar to the OAuth Authorization Server middleware for ASP.NET 4.x.
  • OpenIddict – Wraps OpenIdConnect.Server up into an easier-to-use package that plugs into ASP.NET Identity.
  • IdentityServer4 – A port of Thinktecture IdentityServer3 to .NET Core (currently in beta).
  • These solutions are much more powerful, but are also more complex to install and configure. If you want a powerful and simple solution, check out the Stormpath ASP.NET Core integration. This package will add all of Stormpath’s token management features to an ASP.NET Core project with two lines of code. You can learn more about Stormpath’s approach to token management with these resources:

  • Overview of Token Authentication Features
  • How Token Authentication Works in Stormpath
  • Use JWTs the Right Way!
  • Thanks for reading! Feel free to dig into the full code on Github. If you have any questions about token authentication, leave me a comment below.

    By the way, I’ll be speaking on ASP.NET Core Token Authentication at KCDC in Kansas City in June 2016. If you’re in the area, come say hi!