Swevo.AutoAuth
1.5.0
Prefix Reserved
dotnet add package Swevo.AutoAuth --version 1.5.0
NuGet\Install-Package Swevo.AutoAuth -Version 1.5.0
<PackageReference Include="Swevo.AutoAuth" Version="1.5.0" />
<PackageVersion Include="Swevo.AutoAuth" Version="1.5.0" />
<PackageReference Include="Swevo.AutoAuth" />
paket add Swevo.AutoAuth --version 1.5.0
#r "nuget: Swevo.AutoAuth, 1.5.0"
#:package Swevo.AutoAuth@1.5.0
#addin nuget:?package=Swevo.AutoAuth&version=1.5.0
#tool nuget:?package=Swevo.AutoAuth&version=1.5.0
Swevo.AutoAuth
A free, MIT-licensed fluent configuration wrapper around OpenIddict (Apache 2.0) for building OAuth2/OIDC token servers in ASP.NET Core.
AutoAuth exists because Duende IdentityServer v6+ requires a paid commercial license for production use once your organization crosses Duende's revenue/usage thresholds (see duendesoftware.com/license). OpenIddict is a fully free, Apache 2.0-licensed alternative — but it is a low-level protocol toolkit, not a turnkey product: you must wire up its server/validation options and write your own token/authorization endpoint controllers by hand. AutoAuth removes the boilerplate from that wiring and ships one ready-to-use endpoint, while being explicit about what it does and does not do.
What AutoAuth actually is
AutoAuth is a thin, fluent configuration and client-seeding layer. It contains no cryptography and no custom protocol logic — every token is issued, signed, validated, and checked by OpenIddict itself. AutoAuth only:
- Translates a small, fluent options object into the equivalent
AddOpenIddict().AddCore()/.AddServer()/.AddValidation()calls, with sane, secure-by-default settings (PKCE required by default, explicit opt-in for development certificates). - Provides an idempotent client-seeding helper (
AutoAuthClientSeeder) so you can declare your OAuth2 clients in code and have them created/updated safely on every startup. - Ships one pre-built, production-usable endpoint: the
client_credentialsgrant token endpoint — the simplest and safest OAuth2 flow, since it never involves a user session, login form, or consent screen. Its implementation mirrors OpenIddict's own official sample (openiddict/openiddict-samples,Aridka.Server/Controllers/AuthorizationController.cs) line-for-line in logic, translated to a minimal API endpoint.
What AutoAuth explicitly does NOT do
Interactive flows (authorization_code with real user login/consent) are not implemented by AutoAuth. Building a safe, tested login and consent UI is a substantial undertaking involving session management, CSRF protection, and consent-persistence — exactly the part of the puzzle where mistakes are most dangerous. Rather than shipping unproven login/consent code, AutoAuth configures the server correctly for authorization_code (including endpoint URIs and PKCE enforcement) and lets you bring your own controller, following OpenIddict's own official, security-reviewed samples:
If you need a complete, ready-made interactive login/consent experience out of the box, OpenIddict's samples repo or Duende IdentityServer's commercial UI remain your best options. AutoAuth's job is to remove the configuration boilerplate, not to replace security-critical UI code you haven't reviewed yourself.
Advanced extensibility hooks (1.4.0)
AutoAuth now includes first-class extension points for higher-level auth capabilities while keeping protocol/crypto responsibility in OpenIddict:
- Passkeys/WebAuthn feature flag:
EnablePasskeys() - Multi-tenant isolation hook:
EnableMultiTenantIsolation()+IAutoAuthTenantResolver - Risk-based token policy hook:
EnableRiskBasedAuthentication()+IAutoAuthRiskEvaluator - Session lifecycle hook:
EnableSessionManagement()+IAutoAuthSessionManager - Compliance/audit hook:
EnableComplianceAudit()+IAutoAuthAuditSink - Operational telemetry:
EnableTelemetry()emitsActivitySource("Swevo.AutoAuth")and counters:autoauth.token.requestsautoauth.token.issuedautoauth.token.rejected
These hooks let you layer SaaS multi-tenancy, adaptive risk controls, compliance logging, and session management without AutoAuth taking ownership of your identity UX.
Example:
builder.Services.AddAutoAuthServer<AppDbContext>(server => server
.SetIssuer("https://auth.example.com/")
.AllowClientCredentialsFlow()
.EnableMultiTenantIsolation()
.UseTenantHeader("X-Tenant-Id")
.EnableRiskBasedAuthentication()
.DenyIpAddresses("203.0.113.15")
.LimitTokenRequestsPerMinute(60)
.LimitTokenRequestsPerMinutePerIp(120)
.EnableComplianceAudit()
.AddRedactedAuditFields("api_key", "authorization")
.EnableSessionManagement()
.EnableTelemetry()
.EnableKeyRotation(TimeSpan.FromHours(12))
.RunKeyRotationOnStartup()
.SetKeyRotationFailureThreshold(5)
.UseDevelopmentCertificates());
When key rotation is enabled, AutoAuth registers a hosted scheduler (AutoAuthKeyRotationBackgroundService).
Implement and register IAutoAuthKeyRotationHandler to perform your real key rollover operation.
By default, rotation runs once at startup and then on each interval; set a failure threshold to stop noisy retry loops.
For Azure Key Vault-backed key rotation, use:
builder.Services.AddAutoAuthAzureKeyVaultKeyRotation(options =>
{
options.VaultUri = new Uri(builder.Configuration["AutoAuth:KeyVault:VaultUri"]!);
options.KeyNames.Add(builder.Configuration["AutoAuth:KeyVault:SigningKeyName"] ?? "autoauth-signing");
options.KeyNames.Add(builder.Configuration["AutoAuth:KeyVault:EncryptionKeyName"] ?? "autoauth-encryption");
});
Suggested production settings:
{
"AutoAuth": {
"KeyVault": {
"VaultUri": "https://kv-autoauth-17815.vault.azure.net/",
"SigningKeyName": "autoauth-signing",
"EncryptionKeyName": "autoauth-encryption"
}
}
}
Session revocation helper:
await app.Services.RevokeAutoAuthSessionAsync(subject: "service-a", clientId: "service-a");
When session management is enabled, subsequent token requests for revoked subject/client pairs are rejected.
Session inventory and targeted revocation helpers:
var sessions = await app.Services.ListAutoAuthSessionsAsync(subject: "service-a", clientId: "service-a");
var latestSessionId = sessions.FirstOrDefault()?.SessionId;
if (!string.IsNullOrWhiteSpace(latestSessionId))
{
await app.Services.RevokeAutoAuthSessionByIdAsync(latestSessionId);
}
var activeSessionsPage = await app.Services.QueryAutoAuthSessionsAsync(
subject: "service-a",
clientId: "service-a",
includeRevoked: false,
skip: 0,
take: 100);
Session records include optional operational metadata (TenantId, RemoteIpAddress, UserAgent) for device/session diagnostics.
Advanced reference sample
See examples\\AutoAuth.AdvancedConfiguration\\Program.cs for an end-to-end composition sample combining:
- multi-tenant resolution,
- risk controls (IP deny + throttling),
- compliance audit with redaction,
- session inventory/revocation helpers with paging/filtering,
- resilient key-rotation scheduling options.
Production rollout runbook checklist
- Certificates/keys: Implement
IAutoAuthKeyRotationHandleragainst your KMS/HSM/Key Vault and verify rollover in a non-prod environment. - Rotation safety: Set
EnableKeyRotation(...),RunKeyRotationOnStartup(...), andSetKeyRotationFailureThreshold(...)to your operational SLOs. - Session ops security: Protect operational session endpoints with strict authorization policies and audit all read/revoke actions.
- Risk controls: Enable rate limiting and IP deny controls when risk-based auth is enabled.
- Compliance: Enable compliance audit and configure redacted fields for sensitive payload attributes.
- Deployment verification: Validate token issuance/revocation, rotation ticks, and telemetry counters in staging before production rollout.
- Runtime identity access: grant your runtime managed identity key-management permissions on the vault (minimum required for your rotation flow).
Install
dotnet add package Swevo.AutoAuth
For compile-time security guardrails:
dotnet add package Swevo.AutoAuth.Analyzers
Quick start: client_credentials (machine-to-machine)
using AutoAuth;
using AutoAuth.Endpoints;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(builder.Configuration.GetConnectionString("Default"));
options.UseOpenIddict(); // registers OpenIddict's entities in your EF Core model
});
builder.Services.AddAuthorization();
builder.Services.AddAutoAuthServer<AppDbContext>(server => server
.SetIssuer("https://auth.example.com/")
.AllowClientCredentialsFlow()
.AddSigningCertificate(myCertificate) // or .UseDevelopmentCertificates() for local dev only
.EnableRevocationEndpoint()
.SetAccessTokenLifetime(TimeSpan.FromMinutes(60)));
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapAutoAuthClientCredentialsEndpoint(); // maps POST /connect/token
app.Run();
Seed a client on startup:
using AutoAuth.Clients;
using var scope = app.Services.CreateScope();
var seeder = new AutoAuthClientSeeder(scope.ServiceProvider.GetRequiredService<IOpenIddictApplicationManager>());
await seeder.SeedAsync(new AutoAuthClientOptions("service-a")
.WithSecret("a-strong-generated-secret")
.WithDisplayName("Service A")
.AllowClientCredentialsFlow()
.WithScopes("api1"));
SeedAsync is idempotent — call it on every startup; existing clients (matched by ClientId) are updated in place, never duplicated.
Validating tokens in a resource server (API)
builder.Services.AddAutoAuthValidation(validation => validation
.SetIssuer("https://auth.example.com/")
.UseLocalValidation()); // or .UseIntrospection(clientId, clientSecret)
Enabling token revocation endpoint
builder.Services.AddAutoAuthServer<AppDbContext>(server => server
.SetIssuer("https://auth.example.com/")
.AllowClientCredentialsFlow()
.EnableRevocationEndpoint()
.AddSigningCertificate(myCertificate));
When enabled, AutoAuth configures OpenIddict's revocation endpoint at POST /connect/revocation.
Define authorization policies with a fluent DSL:
using AutoAuth.Authorization;
builder.Services.AddAutoAuthPolicies(policies => policies
.RequireScope("api.read", "api.read")
.RequireAnyScope("api.read-or-write", "api.read", "api.write")
.RequireRole("admins", "admin")
.RequireClaim("region.eu", "region", "eu"));
Enabling authorization_code (bring your own login/consent controller)
builder.Services.AddAutoAuthServer<AppDbContext>(server => server
.SetIssuer("https://auth.example.com/")
.AllowAuthorizationCodeFlow() // requires PKCE by default
.RequirePushedAuthorizationRequests()
.AllowRefreshTokenFlow()
.AddSigningCertificate(myCertificate));
AutoAuth will map the /connect/authorize and /connect/logout endpoint URIs and enable ASP.NET Core passthrough for them, but you must implement your own controller/endpoint handling login, consent, and building the ClaimsPrincipal — see OpenIddict's Velusia/Zirku samples for a complete, working reference implementation of interactive flows.
Requiring PAR (Pushed Authorization Requests)
builder.Services.AddAutoAuthServer<AppDbContext>(server => server
.SetIssuer("https://auth.example.com/")
.AllowAuthorizationCodeFlow()
.RequirePushedAuthorizationRequests()
.AddSigningCertificate(myCertificate));
For Duende IdentityServer users, this is the AutoAuth/OpenIddict equivalent of enabling PAR as an enterprise hardening feature for interactive clients. AutoAuth simply switches on OpenIddict's built-in PAR enforcement and exposes the pushed authorization endpoint at /connect/par; it does not implement any custom PAR protocol logic itself.
Current limitation: PAR is only exposed through AutoAuth for interactive authorization_code setups, which matches the flows AutoAuth already configures. You still bring your own login/consent endpoint for /connect/authorize.
Security notes
- PKCE (
RequireProofKeyForCodeExchange) is required by default for authorization_code requests. RequirePushedAuthorizationRequests()forces interactive clients to send authorization requests through/connect/par, reducing sensitive request data in the browser front channel.UseDevelopmentCertificates()uses OpenIddict's ephemeral signing/encryption certificates, regenerated on every restart. Do not use in production — tokens issued before a restart become unverifiable. UseAddSigningCertificate(...)with a real, persisted certificate instead.- AutoAuth throws at startup if no issuer, no flow, or no signing certificate (and no explicit development opt-in) is configured — misconfiguration fails fast rather than silently running insecurely.
Related Swevo packages
- AutoBus — free MassTransit alternative
- FluentPdf — free QuestPDF alternative
- FluentExcel — free EPPlus alternative
- AutoImage — free ImageSharp alternative
Related Packages
| Package | Downloads | Description |
|---|---|---|
| Swevo.AutoBus | Free, MIT-licensed in-process message bus for | |
| Swevo.AutoBus.RabbitMQ | RabbitMQ transport for AutoBus | |
| Swevo.AutoAssert | Free, MIT-licensed fluent assertions for | |
| Swevo.AutoAudit | Compile-time audit field generation for EF Core entities using Roslyn source generators | |
| Swevo.AutoResult | Compile-time Result<T> monad for | |
| Swevo.AutoGuard | Compile-time guard clauses for | |
| Swevo.AutoImage | A free, MIT-licensed fluent image processing wrapper around SkiaSharp for | |
| Swevo.AutoFeatureFlag | Compile-time feature flag stubs for | |
| Swevo.AutoTestData | Compile-time test data builders for |
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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. |
-
net10.0
- Azure.Identity (>= 1.13.2)
- Azure.Security.KeyVault.Keys (>= 4.7.0)
- OpenIddict.AspNetCore (>= 7.5.0)
- OpenIddict.EntityFrameworkCore (>= 7.5.0)
-
net8.0
- Azure.Identity (>= 1.13.2)
- Azure.Security.KeyVault.Keys (>= 4.7.0)
- OpenIddict.AspNetCore (>= 7.5.0)
- OpenIddict.EntityFrameworkCore (>= 7.5.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
1.5.0: Adds first-class Azure Key Vault-backed `IAutoAuthKeyRotationHandler` implementation and DI registration extension (`AddAutoAuthAzureKeyVaultKeyRotation`), plus production configuration wiring and validation tests. 1.4.0: Adds production-ops hardening with queryable session operations (paging/filtering), optional session metadata capture hooks for tenant/IP/user-agent, resilient key-rotation startup/failure-threshold tuning, and an advanced end-to-end operations sample. 1.3.0: Adds operational hardening features including session inventory/targeted revocation APIs, session metadata capture (tenant/IP/user-agent), resilient key-rotation scheduling controls (startup execution + failure threshold), and stricter lifetime validation. 1.2.0: Add advanced feature hooks: passkeys flag, multi-tenant resolver, risk-based token evaluation hook, session/compliance sinks, and built-in telemetry counters/activities around token endpoint execution. 1.1.0: Add fluent RequirePushedAuthorizationRequests() support for OpenIddict PAR enforcement, exposing /connect/par for authorization_code deployments. 1.0.1: Add missing package icon. 1.0.0: Initial release. Fluent AddAutoAuthServer/AddAutoAuthValidation configuration wrappers over OpenIddict, an idempotent client seeder (AutoAuthClientSeeder), and a ready-made client_credentials token endpoint (MapAutoAuthClientCredentialsEndpoint). Interactive flows (authorization_code with user login) require your own login/consent endpoint — see README.