dotkit 1.1.0

dotnet tool install --global dotkit --version 1.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local dotkit --version 1.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=dotkit&version=1.1.0
                    
nuke :add-package dotkit --version 1.1.0
                    

dotkit

A .NET CLI tool that installs and configures JWT Authentication in ASP.NET Core Web API projects with a single command.

License Repository CI NuGet

Features

  • Supports .NET 6 and later: multi-targeted tool (net6.0, net8.0, net10.0) that installs and runs on any .NET 6+ runtime
  • Detects the target project's target framework and rejects frameworks older than .NET 6
  • Installs Microsoft.AspNetCore.Authentication.JwtBearer NuGet package with the version matched to the project's target framework (resolved from NuGet, e.g. 6.0.x for net6.0)
  • Adds Jwt section to appsettings.json with auto-generated secret key
  • Creates JwtSettings and JwtService ready-to-use classes (C# 10 compatible, so they compile on net6.0)
  • Injects JWT authentication, DI registration, and middleware into Program.cs
  • Configures User Secrets for SecretKey, Issuer, and Audience (or writes them to appsettings.json via --no-user-secrets)
  • Logs progress to console and rolling files via Serilog

Installation

dotnet tool install --global dotkit

Usage

dotkit install [options]

Options

Option Description Default
--project Path to the Web API project directory Current directory
--secret-key JWT secret key (32+ chars) Auto-generated (64 chars base64)
--issuer Token issuer Project name
--audience Token audience Project name
--no-user-secrets Write values to appsettings.json instead of User Secrets false
--verbose Enable debug-level logging false

Examples

# Default: stores values in User Secrets
dotkit install

# Custom values
dotkit install --project ./MyApi --issuer "MyApp" --audience "MyApp"

# Write values directly to appsettings.json (skip User Secrets)
dotkit install --no-user-secrets --secret-key "your-32-char-min-key-here..."

What it does

  1. Detects the ASP.NET Core Web API project (must target Microsoft.NET.Sdk.Web and .NET 6.0 or later)
  2. Installs Microsoft.AspNetCore.Authentication.JwtBearer NuGet package (version matched to the project's target framework)
  3. Merges Jwt section into appsettings.json
  4. Creates Configuration/JwtSettings.cs and Services/JwtService.cs
  5. Injects into Program.cs:
    • Required using directives
    • builder.Services.AddAuthentication().AddJwtBearer() with TokenValidationParameters
    • builder.Services.Configure<JwtSettings>(...)
    • builder.Services.AddScoped<JwtService>()
    • app.UseAuthentication() and app.UseAuthorization()
  6. Configures SecretKey, Issuer, and Audience via User Secrets (or appsettings.json)

After running, inject JwtService in any controller and call GenerateAccessToken() to issue JWTs.

Secret storage modes

Mode appsettings.json User Secrets
User Secrets (default) Placeholder (CHANGE_ME...) Real key, issuer, audience
--no-user-secrets Real key, issuer, audience Not configured

Lifecycle

dotkit install [options]
             │
             ▼
    ┌─────────────────────┐
    │  Initialize Serilog   │  → %TEMP%\dotkit\logs\dotkit-YYYYMMDD.log
    └─────────┬───────────┘
              ▼
    ┌─────────────────────┐
    │  ProjectDetector    │  ← Reads .csproj from directory
    │  .Detect()          │
    └─────────┬───────────┘
              ▼
    ┌─────────────────────┐
    │  JwtInstaller       │  ← dotnet add package
    │  .InstallAsync()    │     Microsoft.AspNetCore.Authentication.JwtBearer
    └─────────┬───────────┘
              ▼
    ┌─────────────────────┐
    │  JsonEditor         │  ← Merges Jwt section from template
    │  .UpdateAppSettings │     into existing appsettings.json
    │  (key?,iss?,aud?)  │     (real values if --no-user-secrets,
    └─────────┬───────────┘      placeholder if User Secrets)
              ▼
    ┌─────────────────────┐
    │  TemplateInstaller  │  ← Creates:
    │  .InstallTemplates  │     Configuration/JwtSettings.cs
    │                     │     Services/JwtService.cs
    └─────────┬───────────┘
              ▼
    ┌─────────────────────┐
    │  ProgramEditor      │  ← Injects into Program.cs:
    │  .UpdateProgramAsync│     - usings for .Configuration and .Services
    │                     │     - AddAuthentication + AddJwtBearer
    │                     │     - Configure<JwtSettings>
    │                     │     - AddScoped<JwtService>
    │                     │     - app.UseAuthentication/Authorization
    └─────────┬───────────┘
              ▼
    ┌─────────────────────┐
    │  UserSecretsManager  │  ← (only if NOT --no-user-secrets)
    │  .ConfigureAsync    │     dotnet user-secrets init
    │                     │     set Jwt:SecretKey
    │                     │     set Jwt:Issuer
    │                     │     set Jwt:Audience
    └─────────┬───────────┘
              ▼
    ✓ Installation completed successfully

Possible errors

ProjectDetector

Error Cause
Directory '{path}' not found. --project points to a non-existent directory
No .csproj file was found. Directory contains no .csproj file
Program.cs was not found. Project has no Program.cs
The selected project is not an ASP.NET Core Web API. .csproj doesn't use Microsoft.NET.Sdk.Web

JsonEditor

Error Cause
Template not found: {path} appsettings.json template missing from Templates/
Template JSON is invalid. Template is not valid JSON
Template does not contain 'Jwt' section. Template has no Jwt property
Existing appsettings.json contains invalid JSON. Target project's appsettings.json has malformed JSON

JwtInstaller

Error Cause
Failed to install Microsoft.AspNetCore.Authentication.JwtBearer: ... dotnet add package failed (no connection, incompatible version, etc.)

UserSecretsManager

Error Cause
Error: dotnet user-secrets init --project ... Could not initialize User Secrets (permissions, SDK)
Error: dotnet user-secrets set --project ... Could not set a secret

Runtime errors (in the generated project, NOT in the tool)

Error (project runtime) Cause
JWT settings not configured. Jwt section in appsettings.json was not loaded correctly
IDX10720: key size must be greater than '256' bits SecretKey < 32 characters (only if someone modified the placeholder)
SecretKey not found. / Issuer not found. / Audience not found. JwtService instantiated without configured values

Exit code

  • 0 → success
  • 1 → any error (message and exception are logged)

Requirements

  • A .NET runtime 6.0 or later to install and run the dotkit tool
  • An ASP.NET Core Web API project targeting net6.0 or later (net6.0, net8.0, net10.0, ...)

The tool is multi-targeted (net6.0, net8.0, net10.0) and the installer picks the binary that matches the runtime available on your machine.

Supported target projects

  • Target framework: net6.0 or later. Older frameworks (net5.0, netcoreapp3.1, netstandard2.0) are rejected.
  • The Microsoft.AspNetCore.Authentication.JwtBearer version is resolved automatically from the target project's framework (e.g. 6.0.x for net6.0, 8.0.x for net8.0), using the latest stable version for that line.
  • Generated templates (JwtSettings.cs, JwtService.cs) are compatible with C# 10, so they compile in net6.0 projects.

CI/CD & Releases

The repository uses GitHub Actions with a supply-chain hardened setup:

  • .github/workflows/ci.yml — runs on push to main/dev and on PRs: build (all 3 TFMs), unit tests, NuGet vulnerability audit (dotnet list package --vulnerable), pack, and an end-to-end smoke test (scripts/e2e.sh) that installs the packed tool and verifies /token and /protected behavior on net6.0, net8.0, and net10.0 samples.
  • .github/workflows/release.yml — publishes to NuGet.org using Trusted Publishing (OIDC): no long-lived API keys. It requests a short-lived API key at push time via NuGet/login@v1 and uses --skip-duplicate.
  • Actions are pinned to commit SHAs and kept updated by Dependabot (.github/dependabot.yml).
  • global.json pins the .NET SDK (10.0.302) for reproducible builds; ContinuousIntegrationBuild enables deterministic packaging in CI.
  • Permissions are least-privilege (contents: read, id-token: write only on the publish job) and persist-credentials: false.

How to publish a release

  1. One-time setup:
    • nuget.org → your account → Trusted Publishing → add a policy for owner Gianss19, repository dotkit, workflow file release.yml.
    • GitHub repo → Settings → Secrets and variables → Actions → add NUGET_USER = your nuget.org username (profile name, not email).
  2. Trigger a publish:
    • Manually: Actions → ReleaseRun workflow → enter version (e.g. 1.1.0).
    • Or push a tag: git tag v1.2.0 && git push origin v1.2.0. The version is validated against a SemVer regex before packaging.

Development

Clone the repository and build, test, and pack locally:

git clone https://github.com/Gianss19/dotkit.git
cd dotkit

# Build all target frameworks (net6.0, net8.0, net10.0)
dotnet build

# Run the unit tests
dotnet test tests/dotkit.Tests.csproj

# Audit NuGet packages for known vulnerabilities
dotnet list dotkit.csproj package --vulnerable --include-transitive

# Pack the NuGet tool package
dotnet pack -c Release -o artifacts

# End-to-end smoke test (needs a bash shell; uses the packed nupkg in artifacts/)
bash scripts/e2e.sh

Contributing

Contributions are welcome! To report a bug, request a feature, or open a pull request, use the repository's issue tracker:

License

This project is licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
1.1.0 129 8/2/2026
1.0.0 112 7/28/2026