Rants and Raves

Thanks for visiting my blog!

More on .NET 7 user-jwts Tool
More on .NET 7 user-jwts Tool
January 10, 2023

I recently released a Coding Short video and a blog post about the new JWT Tooling in .NET 7. It was received well, but I didn’t dig into some of the real details of what is happening. If you need to catch up, here is the blog post:

Changes in JWT Bearer Tokens in .NET 7

What I didn’t have a chance to explain is everything that the user-jwts tool actually does. It makes several changes:

  • Adds a section to the appsettings.developer.json file to add user-jwts as a valid issuer of JWTs.
  • Adds secret key related properties to the user-secrets for the project.

What it doesn’t do is wire up your startup to include JwtBearer authentication, it only sets up the tool as an issuer of the JWT. Let’s walk through this.

AppSettings.Developer.json

The first step is it adds a new Authentication section to the developer settings:

  "Authentication": {
    "Schemes": {
      "Bearer": {
        "ValidAudiences": [
          "http://localhost:38015",
          "https://localhost:44384",
          "http://localhost:5241",
          "https://localhost:7254"
        ],
        "ValidIssuer": "dotnet-user-jwts"
      }
    }
  }

It gets the valid audiences by looking at the launchsettings.json (in the Properties folder) of your project. The ValidIssuer is there to match the issuer of the JWT as configured in user settings (see next section for what I mean).

User Secrets

In order to allow the JWT to be signed, it needs to have some security information. This information is in the user-secrets file. If your project didn’t have support user-secrets yet, the tool adds the user-secret GUID to the project and then stores some information there. To see what they added, just list the secrets in this project:

> dotnet user-secrets list

In my case, this returns the secret and valid issuer information (this is a throw-away project, so leaking this secret doesn’t matter):

Authentication:Schemes:Bearer:SigningKeys:0:Value = R98yic+EGjR0asjN8eHe2nSLlhBB8tWcebIxHmcOSko=
Authentication:Schemes:Bearer:SigningKeys:0:Length = 32
Authentication:Schemes:Bearer:SigningKeys:0:Issuer = dotnet-user-jwts
Authentication:Schemes:Bearer:SigningKeys:0:Id = e1b964aa

What’s interesting here, is that some of these defaults are configurable. By default, when the tool issues a JWT, it uses your machine name identification. If you don’t want that, you can simply override it:

> dotnet user-jwts create -n shawn@aol.com

You can even change the name of the Issuer with:

> dotnet user-jwts create -n shawn@wildermuth.com --scheme YourIssuerName

I was able to use this information to just prototype issuing JWTs (via API) to just re-use the tools’ information. You can see here the GetSection matches the information in user-secrets:

var bearer = _config.GetSection("Authentication:Schemes:Bearer");
if (bearer is not null)
{
  var uniqueKey = bearer.GetSection("SigningKeys")
    .Get<SymmetricSecurityKey[]>()?
    .First()
    .Key;
  var issuer = bearer["ValidIssuer"];
  var audiences = bearer.GetSection("ValidAudiences")
    .Get<string[]>();
  var key = new SymmetricSecurityKey(uniqueKey);
  var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);

Hope this answers some questions. Ping me below if you have questions!