GuideAnts Auth Flow
June 6, 2026 ยท View on GitHub
This document describes the final authentication and authorization flow shipped in Phases 2-6, including bootstrap-admin behavior on a fresh install.
Role model
GuideAnts uses one application-wide role per user:
PendingReaderContributorAdmin
Pending is a pre-approval state, not a capability tier. Authorization policies
map to roles as follows:
RequireApprovedUser:Reader,Contributor,AdminRequireContributor:Contributor,AdminRequireAdmin:Admin
Bootstrap-admin procedure (fresh install)
- Start with an empty database (no rows in
Users/UserRoles). - First user registers at
POST /api/auth/register. - Registration transaction grants that first account:
- role
Admin ApprovedAtset (active account)
- role
- Every later registration is created as:
- role
Pending ApprovedAt = null
- role
- An Admin approves pending users through
POST /api/admin/users/{id}/approveand assignsReader,Contributor, orAdmin.
User journey
- User registers (
/register) or logs in (/login). - API issues an app JWT in an HttpOnly cookie (
GuideAnts.Auth); the client never stores the token in JavaScript. - Authenticated API calls use
fetch(..., { credentials: 'include' })so the browser sends the cookie;GET /api/auth/mehydrates auth state on load. The session is sliding: the server re-issues the cookie on authenticated requests once the token is older thanSlidingSessionRenewal.RenewalInterval(1 day), so an active user is never logged out mid-session. With the default 30-day (Jwt:LifetimeMinutes = 43200) lifetime, only a genuinely idle session (no requests for ~30 days) lapses. There is no absolute session cap. - Route behavior:
- anonymous ->
/login - authenticated
Pending->/pending - authenticated with
MustChangePassword->/change-password - approved user -> app routes
- anonymous ->
- Logout calls
POST /api/auth/logoutto clear the cookie, then clears client state. - Admin-managed recovery:
- Admin sets password via
POST /api/admin/users/{id}/set-password - user receives
MustChangePassword = trueand rotates password at next sign-in
- Admin sets password via
Token signing configuration
Jwt:* settings live in src/server/GuideAntsApi/appsettings*.json for
issuer/audience/lifetime, with a non-secret SigningKey placeholder only.
Real signing keys must be supplied outside source control:
- local development:
dotnet user-secretsor environment variableJwt__SigningKey - production: secret manager (for example Azure Key Vault) exposed as
Jwt__SigningKey
No real signing key should be committed to git.