Local Auth Setup
In production, the API is secured using Auth0. For local development, you can use dotnet user-jwts to generate signed JWT tokens without needing an Auth0 account or internet access.
This guide walks you through getting auth working on your machine from scratch.
- .NET 7+ SDK installed
- The API project cloned and running locally
How it works locally
The API supports two JWT authentication schemes simultaneously:
| Scheme | Used in | Issuer |
|---|---|---|
| Auth0 | Production / Staging | https://your-tenant.auth0.com/ |
| UserJwts | Development only | dotnet-user-jwts |
When a request arrives, the API inspects the iss (issuer) claim in the Bearer token and forwards it to the correct validation handler automatically. You don't need to change any API code — just generate a local token and use it.
Step 1 — Verify your project has a UserSecretsId
Open the .csproj file and confirm there is a <UserSecretsId> entry:
<PropertyGroup>
<UserSecretsId>your-project-guid-here</UserSecretsId>
</PropertyGroup>
If it's missing, add one:
dotnet user-secrets init
Step 2 — Generate a local JWT
From the directory containing the .csproj file, run:
dotnet user-jwts create \
--name "Auth0|Auth0-User-Id-here" \
--claim "org_id=Add-Org-Id-Here" \
--claim "permissions=admin:platform" \
--name "local-platform-admin" \
--scheme UserJwts
dotnet user-jwts scopes keys to the project based on your current directory. Running it from the wrong folder will write the signing key to the wrong project's user secrets, and the API won't be able to validate your token.
This command will:
- Generate a signing key and store it in your user secrets (not in source control)
- Print a Bearer token you can use immediately
Example output:
New JWT saved with ID 'd2b8240f'.
Name: your-name
Scheme: UserJwts
Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Save the token — you'll use it in Step 4. If you lose it, generate a new one.
Step 3 — Verify the signing key was stored
dotnet user-secrets list
You should see entries like:
Authentication:Schemes:UserJwts:SigningKeys:0:Value = wiqeQl...
Authentication:Schemes:UserJwts:SigningKeys:0:Length = 32
Authentication:Schemes:UserJwts:SigningKeys:0:Issuer = dotnet-user-jwts
Authentication:Schemes:UserJwts:SigningKeys:0:Id = d2b8240f
Authentication:Schemes:UserJwts:ValidAudiences:0 = https://localhost:7251
If SigningKeys is empty or missing, the token was created for a different project. Go back to Step 2 and ensure you're in the right directory.
Step 4 — Use the token
Swagger UI
- Run the API (
dotnet run) - Open Swagger at
https://localhost:7251/swagger - Click Authorize (the padlock icon)
- Enter your token as:
Bearer eyJhbGciOi... - Click Authorize
curl
curl -H "Authorization: Bearer eyJhbGciOi..." https://localhost:7251/your-endpoint
HTTP file (Visual Studio / Rider)
GET https://localhost:7251/your-endpoint
Authorization: Bearer eyJhbGciOi...
Managing tokens
List all your local tokens
dotnet user-jwts list
Inspect a token
dotnet user-jwts print <token-id>
Create a token with custom claims
dotnet user-jwts create --name "your-name" --scheme UserJwts --claim "role=admin" --claim "email=you@example.com"
Delete a token
dotnet user-jwts remove <token-id>
Troubleshooting
invalid_token — The signature key was not found
The signing key in your user secrets doesn't match the token. This usually means:
- The token was created for a different project (wrong directory)
- Your user secrets were cleared
Fix: Regenerate the token from the correct project directory:
dotnet user-jwts create --name "your-name" --scheme UserJwts
invalid_token — The issuer is invalid
Your token's iss claim doesn't match what the API expects. Ensure you used --scheme UserJwts when creating the token.
Token routes to Auth0 handler instead of UserJwts
The API routes based on the iss claim. Check your token at jwt.io and verify the iss field is dotnet-user-jwts.
Token expired
Local tokens default to a 6-month expiry. If yours has expired:
dotnet user-jwts create --name "your-name" --scheme UserJwts