Building Web Apps with

Building Web Apps with
Photo by Markus Spiske / Unsplash

Building Web Apps with .Net 7: Learn Role-Based Authorisation using JWT & dotnet user-jwts CLI

DotNet 7 JSON Web Token
Recently, my colleague Michel and I embarked on a journey to construct a web application using C# with .Net 7. What initially seemed like a routine task became an exciting adventure, as .Net 7 presented a new landscape compared to .Net 3.5.

In our previous post .Net 7 & JWT, we explained how to create a JSON Web Token. This article explores authorization via web tokens in .Net 7.

Understanding .Net 7 Authorisation

Using Authorize Tag

Simple authorization is straightforward. Simply add [Authorize] tag atop your Controller class.

[Authorize]
public class AuthController : Controller{}

You need to be authenticated to access this Controller. For anonymous endpoints, use [AllowAnonymous] tag.

[HttpPost("login"), AllowAnonymous]
public ActionResult<User> Login(UserRequest userRequest){}

[Authorize(Roles = "Administrator")] indicates the roles that can access the endpoint. Remember to configure JWT Bearer authentication in your program.cs file.

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer();

User-jwts Tool

The user-jwts tool, akin to user-secrets tool, manages values valid for a local developer. It hides implementation details, with values stored in a JSON file on local machine’s user profile folder. Use dotnet user-jwts create to create a local JWT.

New JWT saved with ID '18e8560e'.
Name: alex
Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

This also generates the following in your appsettings.Development.json file.

"Authentication": {
    "Schemes": {
      "Bearer": {
        "ValidAudiences": [...],
        "ValidIssuer": "dotnet-user-jwts"
      }
    }
  }

Use dotnet user-jwts print {ID} --show-all to receive security info. To fetch the Signing issuer key, use dotnet user-jwts key.

Swagger & Security

Swagger currently has no option to manage security. For this, provide options to Swagger.

builder.Services.AddSwaggerGen(options =>
{
    options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
    {
        In = ParameterLocation.Header,
        Name = "Authorization",
        Type = SecuritySchemeType.ApiKey
    });
    options.OperationFilter<SecurityRequirementsOperationFilter>();
});

Swagger will require a bearer to test our endpoint, which can be generated using dotnet user-jwts role "admin".

Validating the Issuer Signing Key

Validation requires adding the following options inside Program.cs, where AddJwtBearer is set.

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = false,
            ValidateAudience = false,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration.GetSection("AppSettings:Token").Value!))
        };
    });

Upon executing the weatherForecast endpoint again, you will encounter a 401 error. The error message that displays is www-authenticate: Bearer error="invalid_token", error_description="The signature key was not found". This indicates that our API Key does not contain any signature key.

However, you can generate a new token through Swagger. Simply initiate a Request from the end-point using username joe and password ellie, and it should produce a new token.

To confirm that the registration process was successful, use the login end-point. Subsequently, add the generated bearer token to the lock pad in Swagger.

If everything is set up correctly, you will now receive a message indicating a 403 Forbidden error instead of the previous 401 error. This shift in error messages confirms that the signature issuer key has been validated, but the user does not possess the necessary roles for access.

However, this can be rectified by adding claims options inside your AuthController::CreateToken Method.

    new Claim(ClaimTypes.Role, "Admin")

And there you have it! A step-by-step guide to handling authorisation with JSON Web Tokens in .Net 7.

Alexandre Cuva

Alexandre Cuva

Nyon, Switzerland