Nedo.AspNet.Authentication.Local
2.0.2
See the version list below for details.
dotnet add package Nedo.AspNet.Authentication.Local --version 2.0.2
NuGet\Install-Package Nedo.AspNet.Authentication.Local -Version 2.0.2
<PackageReference Include="Nedo.AspNet.Authentication.Local" Version="2.0.2" />
<PackageVersion Include="Nedo.AspNet.Authentication.Local" Version="2.0.2" />
<PackageReference Include="Nedo.AspNet.Authentication.Local" />
paket add Nedo.AspNet.Authentication.Local --version 2.0.2
#r "nuget: Nedo.AspNet.Authentication.Local, 2.0.2"
#:package Nedo.AspNet.Authentication.Local@2.0.2
#addin nuget:?package=Nedo.AspNet.Authentication.Local&version=2.0.2
#tool nuget:?package=Nedo.AspNet.Authentication.Local&version=2.0.2
Nedo.AspNet.Authentication.Local
Username/password authentication with refresh-token families (with reuse detection), EF Core persistence, email verification, password reset, magic-link sign-in, account management endpoints, and the user store all social providers (Google, Microsoft, Apple, GitHub, Facebook, Keycloak) plug into.
Optional layers: TOTP 2FA (auto-gates every sign-in path), Passkeys / WebAuthn (passwordless or step-up), Dev impersonation (no-password endpoint for local dev + integration tests).
Install
dotnet add package Nedo.AspNet.Authentication.Local
dotnet add package Microsoft.EntityFrameworkCore.Sqlite # or Npgsql / SqlServer / MySql
Quickstart
using Microsoft.EntityFrameworkCore;
using Nedo.AspNet.Authentication;
using Nedo.AspNet.Authentication.Local;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddLocalAuthentication(opts =>
{
opts.SigningKey = builder.Configuration["Jwt:Secret"]!; // ≥ 32 bytes
opts.Issuer = "my-app";
opts.Audience = "my-app";
opts.AccessTokenLifetime = TimeSpan.FromMinutes(15);
opts.RefreshTokenLifetime = TimeSpan.FromDays(7);
opts.MaxFailedAttempts = 5;
opts.LockoutDuration = TimeSpan.FromMinutes(15);
});
builder.Services.AddLocalAuthStore(
db => db.UseSqlite("Data Source=auth.db"), // or UseNpgsql / UseSqlServer
autoMigrate: true);
builder.Services.AddPasswordHasher<BcryptPasswordHasher>(); // your impl
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<IAuthContext, AuthContext>();
builder.Services.AddAuthorization();
var app = builder.Build();
app.UseAuthentication();
app.UseNedoAuthContext();
app.UseAuthorization();
app.MapLocalAuth(); // /auth/login, /register, /refresh, /logout, /change-password,
// /verify-email, /forgot-password, /reset-password,
// /magic-link/{request,redeem}, /complete-external-signup
app.MapLocalAccount(); // /account/external-logins, /account/sessions
app.Run();
Endpoints
| Method | Path | Body |
|---|---|---|
| POST | /auth/login |
{ username, password, deviceInfo?, captchaToken? } |
| POST | /auth/register |
{ username, password, email?, displayName?, captchaToken? } |
| POST | /auth/refresh |
{ refreshToken } |
| POST | /auth/logout |
{ refreshToken } |
| POST | /auth/change-password (bearer) |
{ currentPassword, newPassword } |
| POST | /auth/verify-email |
{ token } |
| POST | /auth/forgot-password |
{ email, captchaToken? } |
| POST | /auth/reset-password |
{ token, newPassword } |
| POST | /auth/magic-link/request |
{ email, captchaToken? } |
| POST | /auth/magic-link/redeem |
{ token, deviceInfo? } |
| POST | /auth/complete-external-signup |
{ pendingToken, username, displayName? } |
| GET | /auth/username-available?username=… |
— |
| GET | /account/sessions (bearer) |
— |
| DELETE | /account/sessions/{id} (bearer) |
— |
| POST | /account/sessions/revoke-all (bearer) |
— |
| GET | /account/external-logins (bearer) |
— |
| DELETE | /account/external-logins/{provider} (bearer) |
— |
Full reference: docs/local/api-reference.md.
Extensibility hooks
| Interface | Use to |
|---|---|
IAccessTokenClaimsEnricher |
Add roles / tenant / user-types / feature-flags to every JWT mint. |
IPostLoginCheck |
Refuse a sign-in after auth passes (TOS, tenant suspension, trial expiry). |
ILockoutPolicy |
Replace fixed-window lockout with exponential backoff / IP-aware / soft-lock. |
ICaptchaVerifier |
Plug reCAPTCHA v3 / hCaptcha / Turnstile to gate login / register / forgot-password. |
IUserStore, IRefreshTokenStore, IUserTokenStore, IExternalLoginStore, IPasskeyStore |
Swap the EF defaults for any persistence layer. |
IAuthEventSink |
Audit log + side-channel for password-reset / email-verify / magic-link delivery. |
Walkthroughs: docs/local/extensibility.md.
Why use this
- Refresh-token families — every refresh belongs to a family; reuse of a revoked token revokes the entire chain (other sessions unaffected). Catches the standard refresh-token theft pattern.
- Auto-link CVE-safe — social sign-ins only auto-link to existing local users when both sides have a verified email, blocking the "register the victim's email but never confirm it, then wait for them to social-sign-in" attack.
- Five focused services —
LocalAuthService,RegistrationService,ExternalSignInService,PasswordResetService,EmailVerificationService(+MagicLinkService), all sharing oneSessionTokenIssuer. Easy to test or replace in isolation. - Discriminated outcomes — every flow returns
AuthOutcome(Tokens/PendingSignup/RequiresMfa/InfoMessage/Failure), so endpointsswitchon the concrete subtype rather than reading an "everything optional" struct.
Architecture deep-dive: docs/local/internals.md.
Custom schema mapping
Every table + column name is configurable via LocalAuthSchemaOptions:
builder.Services.AddLocalAuthStore(
db => db.UseNpgsql(connectionString),
schema =>
{
schema.Schema = "identity";
schema.UsersTable.TableName = "users";
schema.UsersTable.Columns.Username = "login_name";
schema.RefreshTokensTable.TableName = "tokens";
schema.PasskeysTable.TableName = "credentials";
});
Related packages
| Goal | Package |
|---|---|
| Add passkeys / WebAuthn | Nedo.AspNet.Authentication.Local.Passkeys |
| Add 2FA (TOTP) | Nedo.AspNet.Authentication.Totp |
| Add social sign-in | Nedo.AspNet.Authentication.{Google,Microsoft,Apple,GitHub,Facebook,Keycloak} |
| Dev-only impersonation | Nedo.AspNet.Authentication.Dev |
License
MIT — see LICENSE.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net9.0 is compatible. 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 was computed. 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. |
-
net9.0
- Microsoft.EntityFrameworkCore.Relational (>= 9.0.0)
- Nedo.AspNet.Authentication (>= 2.0.2)
- Nedo.AspNet.Authentication.Claims (>= 2.0.2)
NuGet packages (10)
Showing the top 5 NuGet packages that depend on Nedo.AspNet.Authentication.Local:
| Package | Downloads |
|---|---|
|
Nedo.AspNet.Authentication.Local.Passkeys
Passkeys (FIDO2 / WebAuthn) sign-in for Nedo.AspNet.Authentication.Local. Wraps Fido2NetLib and emits standard local sessions. |
|
|
Nedo.AspNet.Authentication.Totp
TOTP (RFC 6238) two-factor authentication for Nedo.AspNet.Authentication.Local. Compatible with Google Authenticator, Microsoft Authenticator, 1Password, Authy, etc. |
|
|
Nedo.AspNet.Authentication.Google
Google sign-in (ID-token exchange) for Nedo.AspNet.Authentication. |
|
|
Nedo.AspNet.Authentication.Dev
Dev-only impersonation endpoint — sign in as any user without a password. Refuses to start outside the Development environment unless explicitly forced. |
|
|
Nedo.AspNet.Authentication.Microsoft
Microsoft sign-in (ID-token exchange) for Nedo.AspNet.Authentication. |
GitHub repositories
This package is not used by any popular GitHub repositories.