Common features in ASP.NET Core 2.1 WebApi: Authentication with a JWT

 

Introduction

Authentication and authorization are required to restrict access to custom and / or sensitive data.
A safer technique than cookie protection is to use tokens, provided by a tier provider.
In this article we will talk about JWT with OpenID Connect.

OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner. OpenID Connect allows clients of all types, including Web-based, mobile, and JavaScript clients, to request and receive information about authenticated sessions and end-users. The specification suite is extensible, allowing participants to use optional features such as encryption of identity data, discovery of OpenID Providers, and session management, when it makes sense for them.

For more information about how to configure an Open Id Connect provider you can check this sample with Azure AD here.

Configuring Startup.cs for authentication

Step 1: Download Microsoft.AspNetCore.Authentication.JwtBearer Nuget package

PM> Install-Package Microsoft.AspNetCore.Authentication.JwtBearer -Version 2.1.2

Step 2: Set authentication scheme for JWT

public void ConfigureServices(IServiceCollection services)
{
   // Authentication
   services.AddAuthentication(options =>
   {
      options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
      options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
   });
}

Step 3: Set JWT provider configuration

public void ConfigureServices(IServiceCollection services)
{
   // Authentication
   services.AddAuthentication(options =>
   {
      options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
      options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
   }).AddJwtBearer(options =>
   {
      options.Authority = "provider end point";
      options.Audience = "application id or uri as identifier";
      options.TokenValidationParameters.ValidateLifetime = true;
      options.TokenValidationParameters.ClockSkew = TimeSpan.FromMinutes(5);
   });
}

Audience represents the intended recipient of the incoming token or the resource that the token grants access to. If the value specified in this parameter doesn’t match the aud parameter in the token, the token will be rejected because it was meant to be used for accessing a different resource. Note that different security token providers have different behaviors regarding what is used as the ‘aud’ claim (some use the URI of a resource a user wants to access, others use scope names). Be sure to use an audience that makes sense given the tokens you plan to accept.

Authority is the address of the token-issuing authentication server. The JWT bearer authentication middleware will use this URI to find and retrieve the public key that can be used to validate the token’s signature. It will also confirm that the iss parameter in the token matches this URI.

ValidateLifetime validates the token expiracy.

ClockSkew allows a certain amount of clock drift. I recommend 5 minutes or less.

Step 4: Set autorization policies

services.AddAuthorization(opts =>
{
   opts.AddPolicy("SurveyCreator", p =>
   {
      // Using value text for demo show, else use enum : ClaimTypes.Role
      p.RequireClaim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", "SurveyCreator");
   });
});

This policy require a role claim type with value “SurveyCreator”

Step 5: Protect your actions with Authorize Attribute

[Authorize(Policy = "SurveyCreator")]
[HttpPost]
public void Post([FromBody] string value)
{
}

Remember that if you don’t provide a toekn to your Api or you provide a wrong or expired token the answer will be Http Unauthorized.

If your token doesn’t satisfy the policy, you will get Http Forbidden.

Conclusion

this was an example of implementing security in a web API 🙂

The complete source code can be found here.