Getting Started
Quick start
Wire the opinionated AuthEndpoints facade for cookie Identity and passkeys.
Your frontend is a separate SPA that calls these routes on the ASP.NET Core API.
Minimal host
// Program.cs
builder.Services.AddDbContext<AppDbContext>(/* your provider */);
builder.Services.AddAuthEndpoints<AppUser, AppDbContext>(o =>
{
o.Passkeys.ServerDomain = "example.com"; // required in Production
});
// Required in Production (Identity's no-op sender is rejected).
builder.Services.AddTransient<IEmailSender<AppUser>, MyEmailSender>();
var app = builder.Build();
app.UseAuthEndpoints(); // authentication, authorization, rate limiting, antiforgery
app.MapAuthEndpoints<AppUser>(); // /identity (management + cookie) + /account (passkeys)
app.Run();
AddAuthEndpoints returns an IdentityBuilder for optional Identity chaining.
Roles
Use the three-type overload so EF registers IRoleStore correctly (AddRoles must run before AddEntityFrameworkStores):
builder.Services.AddAuthEndpoints<AppUser, AppRole, AppDbContext>(o =>
{
o.Passkeys.ServerDomain = "example.com";
});
Your DbContext should be IdentityDbContext<AppUser, AppRole, TKey> (or equivalent). Do not chain bare .AddRoles<TRole>() after the two-type overload — that leaves IRoleStore unregistered.
Default routes (facade)
| Area | Path prefix | Main routes |
|---|---|---|
| Management + cookie | /identity | register, login, logout, csrfToken, confirm/forgot/reset, manage/*, confirmIdentity |
| Passkeys | /account | passkeys register/login options + complete, credential CRUD |
| JWT (if enabled) | /auth | create, refresh, verify, logout, csrfToken |
SPA usage notes
Cookie stack
- Send cookies with credentials (
credentials: "include"/ AxioswithCredentials). - Call
GET /identity/csrfToken, then send the token asRequestVerificationTokenon unsafe methods (POST/PUT/PATCH/DELETE).
JWT stack (when enabled)
POST /auth/createreturns an access token; send it asAuthorization: Bearer ….- Refresh token is an HttpOnly cookie;
POST /auth/refreshandPOST /auth/logoutneed CSRF (GET /auth/csrfToken+RequestVerificationToken).
Enable JWT (facade opt-in)
Map the refresh-token entity on your DbContext:
// AppDbContext.cs
using AuthEndpoints.Jwt;
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.UseRefreshToken(); // AuthEndpointsRefreshTokens table
}
Then enable JWT on the facade:
builder.Services.AddAuthEndpoints<AppUser, AppDbContext>(o =>
{
o.Passkeys.ServerDomain = "example.com";
o.Jwt.Enabled = true;
o.Jwt.Path = "/auth";
o.Jwt.Configure = jwt =>
{
jwt.Issuer = "https://example.com";
jwt.Audience = "https://example.com";
jwt.SigningOptions.SymmetricKey = builder.Configuration["Jwt:SymmetricKey"];
};
});
Add a migration (or recreate the database) so AuthEndpoints.AuthEndpointsRefreshTokens exists. Tokens are stored hashed; recreate that table if upgrading from plaintext refresh-token storage.
Next steps
- Tune Configuration
- Follow the Production checklist
- Or compose modules yourself for bearer/JWT-only stacks