Authentication
Sessions, refresh-token rotation, password sign-in, forgot password, and plug-and-play Google OAuth.
Sessions
Section titled “Sessions”HttpOnly cookie + CSRF double-submit. The session cookie is pulse_session, max-age 30 days. CSRF token is exposed via pulse_csrf (readable cookie) and must echo back in the X-CSRF-Token header for state-changing requests.
Refresh-token rotation
Section titled “Refresh-token rotation”Long-lived refresh tokens rotate on every use. Refresh-token families are revoked on detected reuse (a classic compromised-token signal). If a user is suddenly bounced to /login, the family was revoked — they re-authenticate.
Password sign-in
Section titled “Password sign-in”Standard email + password. Passwords are stored as bcrypt hashes with cost 12.
Forgot password
Section titled “Forgot password”/forgot → email link → /reset?token=.... Links are valid for 1 hour, one-time use. Falls back to dev-log mode if SMTP isn’t configured.
Google OAuth (optional)
Section titled “Google OAuth (optional)”Plug-and-play. Set:
GOOGLE_OAUTH_CLIENT_ID=your-client-idGOOGLE_OAUTH_CLIENT_SECRET=your-secret# optional, defaults to ${PUBLIC_BASE_URL}/api/v1/auth/google/callbackGOOGLE_OAUTH_REDIRECT_URL=https://pulse.example.com/api/v1/auth/google/callback…and restart the API. A Continue with Google button appears on the login page automatically.
Behaviour:
- New Google user — provisioned with the verified email and display name, no password, gets a personal organization automatically.
- Returning Google user — looked up by
oauth_provider + oauth_subject, logged in. - Existing password user signing in with Google for the first time (email matches) — the Google identity is linked to the existing account; their existing org membership is preserved.
When either env var is missing, the feature is invisible: no button, callback endpoint returns 404. No DB toggle to maintain — env presence is the switch.
Register the redirect URL in Google Cloud Console → APIs & Services → Credentials. It must match exactly.