Intro

This is the second blog from three blogs about JWT (JSON Web Token). In the first blog I explained how you can create a JWT. This blog we secure the REST service and tackle these topics:

  • Setup and configure JWT
  • Secure by default
  • Setup Swagger for JWT
  • HTTP client with JWT
  • Claim based access
  • Claim based content

General JWT solution Overview

Before we dive into the details first a refresher on part one. The JWT issuer is now up and running. It delivers a JWT based on user credentials.

Setup and configure JWT

The next step is securing the REST service and starts with adding the Microsoft.AspNetCore.Authentication.JwtBearer package. The JWT package needs configuring in startup.cs First we set the parameters in ‘appsettings.json’

The SecretKey value must match the key in the JWT issuer server otherwise the user will remain unauthenticated and access will be denied. DI (Dependency Injection) delivers access to the configuration:

JwtTokenValidationSettingsFactory implements the interfaces and has the function TokenValidationParameters.

The function TokenValidationParameters returns (as the name suggest) JWT validation parameters. These parameters are used during startup.cs

That’s it! Now you can secure controllers or their action with the [Authorize] attribute.

Secure by default

With MVC framework you can set custom filters. Securing all controllers by default is just setting a custom filter during startup.

Setup Swagger for JWT

The Swagger setup needs a little tweak for JWT support. The tweak allows you to add an JWT during testing. Swagger adds the JWT to the request header and the REST service receives the token and sets the security.

The rest of the Swagger setup is normal.

Time to Test

All is now set to test with swagger. With the small LoginStatus function you can easy if the security works.

I started Swagger and try the loginstatus

The response code is 401 meaning ‘Unauthorized‘. I did not add a JWT so this is the correct result! Let’s check what happens if we provide swagger with a JWT.

First get a JWT from the JWT issuer with ’employee@xyz.com’ and ‘password’ as credentials.

The swagger value is  ‘Bearer ‘ and the response code combined.

The JWT is now added to Swagger and we try again:

The response code is 200 (Ok) and the response body shows the authentication is set and the controller can read the claims. Yes!

HTTP Client with JWT

I added a small console application that clearly demonstrates how JWT and a http client can work together.

The first step is retrieving a JWT from the issuer:

With the JWT we can make calls to the rest service:

Please mind the different URL’s for login and GetEmployees and watch line 10 carefully. The JWT is added to the request header in the same style as with Swagger,  ‘Bearer <token>’

Running the console app:

results in:

CBAC (Claim Based Access)

The security model supports CBAC and differs from the more traditional RBAC (Role Based Access).  I am not starting a discussion is if RBAC or CBAC is better. In think Claim based is more generic and better suited to integrate with different systems. For the RBAC diehards there is good news, you can perfectly fit a Role based system in a Claim based environment and the Role based support is also added for backward compatibility.

Policy require claim(s)

The security model introduces the Policy concept. A Policy is made of one or more claims and in registered during startup.

A Policy can be fulfilled be either a Role or a Claim. Complex combinations are also possible but they are not used in this demo. You can authorize by role or policy

However you cannot use a claim as authorize attribute, you must use a Policy with your Claim.

Claim Based Content

Some times the content of a resource depends on the client. For example everyone can view employees but only the human resource department is allowed to view the salary. You can implement this feature by checking the user claims or role if you prefer.

Key elements in RemoveSensitiveFields are in line 11 and 18. The function depends on package ‘System.Linq.Dynamic.Core‘. This package offers a Select(params) extension method on IQueryable items. The property names are extracted with reflection, if the client is not a member of the HR department the field ‘Salary’ is removed.

The console application demonstrates the claim based content.

Output:

As the screen dump shows only HR members can view the salary.

Conclusion

JWT  (JSON Web Tokens) is a solid way for securing REST services.  JWT is easy to setup and integrates well with .Net Core. Due to the self contained design keeps JWT the REST service stateless and drops the need for an authentication server. JWT supports both the traditional Role based and the more modern Claim based approach.

Visual Studio Startup Projects

Sometimes the Visual Studio startup Project is lost and prevent running the application. Right click on the solution and choose ‘Set Startup Projects…’

And repair the startup setting:

Choose either WebApp or Jwt.ConsoleDemo deppending on what you want.

Further Reading

Next post: JWT Security Part 3, Secure MVC application

Previous post: JWT Security Part 1, Create Token

REST status codes

System.Linq.Dynamic Documentation