Stock Identity vs AuthEndpoints
Both stacks sit on ASP.NET Core Identity and your EF user store. Stock here means Microsoft's Identity API endpoints (AddIdentityApiEndpoints / MapIdentityApi) or the same routes written by hand. AuthEndpoints means the cookie facade: AddAuthEndpoints / UseAuthEndpoints / MapAuthEndpoints.
Request bodies stay Identity-shaped (RegisterRequest, LoginRequest, ForgotPasswordRequest, ResetPasswordRequest, TwoFactorRequest). AuthEndpoints maps the routes and adds cookie login, CSRF where required, rate limits, and ReAuth. It does not invent alternate DTOs.
AuthEndpoints tables use the facade default prefix /identity (IdentityPath). Stock MapIdentityApi has no built-in prefix unless the host wraps it in MapGroup.
AuthEndpoints-only on this surface: GET /identity/csrfToken, cookie POST /identity/logout, and ReAuth (/manage/authMethods, /confirmIdentity). Stock MapIdentityApi does not map logout.
Client steps for these flows: Examples. Product positioning against OpenIddict: Compare.
Host setup
Stock (MapIdentityApi)
builder.Services
.AddIdentityApiEndpoints<AppUser>()
.AddEntityFrameworkStores<AppDbContext>();
var app = builder.Build();
// Optional prefix — without MapGroup, routes are at the app root (/register, /login, …).
app.MapGroup("/identity").MapIdentityApi<AppUser>();
You still wire authentication, authorization, antiforgery, CORS, and rate limiting yourself. Login is bearer-first unless the client passes cookie query flags.
AuthEndpoints (cookie facade)
builder.Services.AddAuthEndpoints<AppUser, AppDbContext>(o =>
{
o.Passkeys.Enabled = false; // thin cookie path; omit or set ServerDomain when passkeys stay on
o.Jwt.Enabled = false;
});
builder.Services.AddTransient<IEmailSender<AppUser>, MyEmailSender>();
var app = builder.Build();
app.UseAuthEndpoints(); // authentication, authorization, rate limiting, antiforgery
app.MapAuthEndpoints<AppUser>();
Passkeys and JWT are off. When you leave passkeys enabled (facade default), set Passkeys.ServerDomain in Production. See Quick start.
CSRF on the AuthEndpoints cookie stack applies to cookie logout, manage POSTs, ReAuth, and authenticated resendConfirmationEmail. It does not apply to register, login, forgotPassword, or resetPassword.
Register
| Stock Identity API | AuthEndpoints facade | |
|---|---|---|
| Route | POST /register (or POST /identity/register with MapGroup) | POST /identity/register |
| Body | Identity register (email, password) | Same Identity body |
| CSRF | Host policy (endpoint does not require antiforgery by default) | Not required (RequireAntiforgery is not on register) |
| Duplicate email | 200 (no enumeration) | 200 (no enumeration) |
| Confirmed-account policy | Host Identity options | RequireConfirmedAccount default true |
After 200 | Not signed in | Not signed in (200 ≠ session) |
| Confirm | GET …/confirmEmail?userId&code | GET /identity/confirmEmail?userId&code, then login. Optional ConfirmEmailRedirectUri → 302 with status / flow |
| Rate limit | Host-owned | Built-in account rate limits |
Client flow: register → check email → confirm → login. Steps: Register a confirmed account.
Login
| Stock Identity API | AuthEndpoints facade | |
|---|---|---|
| Route | POST /login (or under your MapGroup) | POST /identity/login |
| Handler | Identity Login | LoginCookie |
| Body | Identity LoginRequest | Same (email, password, optional 2FA fields) |
| Default success | Identity bearer tokens (AccessTokenResponse) | Application cookie only (no bearer): empty body + Set-Cookie (TypedResults.Empty). Session when the flag is omitted |
| Cookie query flags | useCookies / useSessionCookies select cookie vs bearer | Only useSessionCookies (useCookies ignored). Persistent: ?useSessionCookies=false |
| CSRF on login | Not required | Not required |
| Logout | Not in MapIdentityApi | POST /identity/logout (auth + CSRF) |
| CSRF helper | Host-owned | GET /identity/csrfToken for logout, manage, ReAuth, resend |
| Lockout | Identity lockout | Lockout + login rate limit |
Full flag tables: Cookie auth. Bearer-style Identity login stays available via compose (MapBearerAuthEndpoints) or SignIn = IdentityBearer. It is not the cookie-facade default.
Password reset
| Stock Identity API | AuthEndpoints facade | |
|---|---|---|
| Forgot | POST …/forgotPassword { email } → always 200 | POST /identity/forgotPassword → always 200 |
| CSRF / session on forgot | Not required | Not required |
Your IEmailSender<TUser> | Same (Production rejects Identity's no-op sender) | |
| Reset code | From mail | Base64Url token from the sender; send that value as resetCode |
| Reset | POST …/resetPassword { email, resetCode, newPassword } | Same Identity body on /identity/resetPassword |
| CSRF / session on reset | Not required | Not required |
| Then | POST …/login | POST /identity/login (LoginCookie) |
Client steps: Reset a forgotten password.
Two-factor authentication
| Stock Identity API | AuthEndpoints facade | |
|---|---|---|
| Status | No GET — use POST /identity/manage/2fa (response includes sharedKey / flags) | GET /identity/manage/2fa → isTwoFactorEnabled only |
| Shared key | On stock POST response (TwoFactorResponse.sharedKey) | Mint/read via POST /identity/manage/2fa + {} (not GET); CSRF + ReAuth |
| Enable / disable | Auth’d POST /manage/2fa (TwoFactorRequest) | Auth’d POST /identity/manage/2fa (same Identity body); CSRF + ReAuth |
CSRF on POST | Not required by MapIdentityApi | Required (RequestVerificationToken) |
| Step-up | Not built in | ReAuth required (confirmIdentity, then cookie or X-AuthEndpoints-Reauth) |
enable + resetSharedKey | Avoid together | Do not send together (validation problem) |
| Login with 2FA | twoFactorCode / twoFactorRecoveryCode on Login | Same fields on LoginCookie |
Client steps: Enable and disable two-factor authentication and Complete step-up (ReAuth).
After these four flows
AuthEndpoints also maps manage info, ReAuth routes, and optional passkeys/JWT. Stock MapIdentityApi does not include passkeys, ReAuth, cookie logout, or csrfToken. Compose only the modules you need when the facade is too much. See Composable endpoints and Modules.