NML

Configuring JWT authentication for ASP.Net Core 3.1 web APIs

Posted on 24 April 2020
Francois Nel
  1. Learn more about JSON Web Tokens.

  2. Work through Jason Watmore's tutorial to configure your API project, and implement the sections that you require. Don't just copy and past the code. You will also need some form of user authentication, such as Identity. The tutorial uses username/password terminoly, but for a web API, you might want to use API key and API secret.

  3. Instead of storing the JWT secret key in appsettings.json as the tutorial suggests, store it in Azure Key Vault, or if that is not available, store it as an environment variable. For example, create a property called SecretKey in your AppSettings class, then add your secret key to your environment variables (in the Configuration section of an App Service) with the name/key of YourProject_AppSettings__SecretKey. Then update Program.cs to look similar to the following. Not the addition of the .ConfigureAppConfiguration() call. The prefix will be removed, and the double underscore will be substited with a ":" to indicate hierarchy.

     private static IHostBuilder CreateHostBuilder(string[] args)
     {
         return Host.CreateDefaultBuilder(args)
             .UseServiceProviderFactory(new AutofacServiceProviderFactory())
             .ConfigureAppConfiguration(
                 (hostingContext, config) =>
                 {
                     config.AddEnvironmentVariables("YourProject_");
                 })
             .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
     }
    
  4. You can generate any secret keys and API keys that you require programmatically using something similar to the following snippet, either in your project, or with a service like .Net Fiddle. Note that JWT secret keys should be at least 128 bit / 16 byte strings. 32 or 64 bytes should be sufficient. If you store your secret key as a base 64 encoded string, remember to update your code to account for that with Convert.FromBase64String(appSettings.SecretKey).

     using System;
     using System.Security.Cryptography;
    
     public class Program
     {
         public static void Main()
         {
             byte[] bytes = new byte[32];
             var rng = new RNGCryptoServiceProvider();
             rng.GetBytes(bytes);
             Console.WriteLine(Convert.ToBase64String(bytes));
         }
     }
    
  5. If you're using Swashbuckle and Swagger UI, update your config to add authentication and ensure that Swagger UI passes the bearer token along with requests. In services.AddSwaggerGen() add:

     opts.AddSecurityDefinition(
         "jwt_auth",
         new OpenApiSecurityScheme
         {
             Name = "Bearer",
             BearerFormat = "JWT",
             Scheme = "bearer",
             Description = "Specify the authorization token.",
             In = ParameterLocation.Header,
             Type = SecuritySchemeType.Http
         });
    
     opts.AddSecurityRequirement(
         new OpenApiSecurityRequirement
         {
             {
                 new OpenApiSecurityScheme
                 {
                     Reference = new OpenApiReference
                     {
                         Id = "jwt_auth",
                         Type = ReferenceType.SecurityScheme
                     }
                 },
                 new string[] { }
             }
         });
    
  6. Try it out! If you're using Swagger, you'll need to call your authentication method first to get a bearer token, then click Authorise on Swagger UI and enter the token. Now all other request should be authorised.

  7. A few caveats to remember. The JWT secret key should be kept secure and private, since it's your encryption key. On the other hand, API keys are not secrets, so don't rely on keeping it private for security. It is essentially just a unique username for your integrating client/customer. For that reason, you can also use an API secret to pair with your API key, not unlike a username/password pair. Your client/customer should keep their API secret private.

An error has occurred. This application may no longer respond until reloaded. Reload