Changelog
Composable Endpoints

Recipes

Common composition patterns for cookie SPA, Identity bearer, JWT-only, and custom paths.

Recipe matrix

RecipeManagement groupSign-in groupPasskeys
Cookie SPA (default facade)/identitycookie /identity/account
Identity bearer/identitybearer /identityoptional
JWT-onlye.g. /accountJWT /authoptional
Custom pathsany prefixmatching DIany prefix

Advanced composition

Compose modules yourself when you need bearer Identity, custom paths, or JWT-only. Map management once in production hosts.

builder.Services
    .AddIdentityApiEndpoints<AppUser>(o =>
    {
        o.Stores.SchemaVersion = IdentitySchemaVersions.Version3;
    })
    .AddEntityFrameworkStores<AppDbContext>()
    .AddDefaultTokenProviders();

builder.Services.AddAntiforgery();
builder.Services.AddCookieAuthEndpoints(); // rate limits + ReAuth schemes
builder.Services.AddPasskeyEndpoints();
builder.Services.AddJwtEndpoints<AppUser, AppDbContext>(o =>
{
    o.Issuer = "https://example.com";
    o.Audience = "https://example.com";
    o.SigningOptions.SymmetricKey = builder.Configuration["Jwt:SymmetricKey"];
});

// In AppDbContext.OnModelCreating:
//   builder.UseRefreshToken();

var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.UseRateLimiter();
app.UseAntiforgery();

// Cookie SPA
app.MapGroup("/identity").MapIdentityManagementApi<AppUser>();
app.MapGroup("/identity").MapCookieAuthEndpoints<AppUser>();

// Or Identity bearer
// app.MapGroup("/identity").MapIdentityManagementApi<AppUser>();
// app.MapGroup("/identity").MapBearerAuthEndpoints<AppUser>();

// Or JWT-only (no cookie login)
// app.MapGroup("/account").MapIdentityManagementApi<AppUser>();
// app.MapGroup("/auth").MapJwtAuthEndpoints<AppUser>();

app.MapGroup("/account").MapPasskeyEndpoints<AppUser>();

Best default for a first-party SPA on the same site (or carefully configured CORS + credentials).

  • Management + cookie on /identity
  • Passkeys on /account
  • Client uses credentials + CSRF token

Identity bearer

Use when the SPA stores Identity bearer tokens (ASP.NET Core Identity API token format) instead of cookies.

  • Map MapBearerAuthEndpoints instead of cookie
  • CSRF is skipped for bearer-authenticated unsafe methods (see Requirements)

JWT-only

Use JWT for access tokens and an HttpOnly refresh cookie.

  • Management on one prefix (e.g. /account)
  • MapJwtAuthEndpoints on /auth (or your choice)
  • Still call UseRefreshToken() and migrate
  • Passkeys do not issue JWT — after passkey login, call /auth/create if you need a JWT

Custom paths

Prefixes are arbitrary as long as DI and middleware match. The Demo host uses paths such as /auth/cookie, /auth/passkey, and /auth/jwt via facade options.