Authentication
Authentication
This page covers how you sign in, how your session stays alive, and the rules around passwords and email verification. It applies to every user; admins should read the Force password change and Password policy sections.
Logging in
Sign in with your email and password.
POST /api/auth/login
{ "email": "you@example.com", "password": "••••••••", "rememberMe": true }
| Field | Required | Notes |
|---|---|---|
email | Yes | Your work email. |
password | Yes | Your account password. |
rememberMe | No | Defaults to true. Controls how long the session lasts (see below). |
Account enumeration is prevented by design
A wrong password and a non-existent or deactivated account both return the same generic error: Invalid email or password. We intentionally return identical responses regardless of which case applies, so a sign-in attempt never reveals whether an email address is in use.
What happens on a successful login
- A seat-limit check runs. If the organization is over its plan's user cap, login is blocked with 403 — except for Executive accounts, which are exempt so an owner can always get in to fix billing.
- You receive an access token and a refresh token (on web, the refresh token is also set as an HttpOnly cookie).
- The submitted password is checked against known breached-password lists in the background. If it appears in a known breach, you get a security alert (sent occasionally, not on every login).
Every login attempt, success or failure, is recorded (see Audit & Monitoring). Repeated failures feed a failed-login-burst tripwire.
JWT tokens & rotation
| Token | Lifetime | Stored where |
|---|---|---|
| Access token | Short-lived | Held by the client; sent as Authorization: Bearer. |
| Refresh token (remember me) | Longer-lived | Database + HttpOnly cookie (web). |
| Refresh token (session only) | Shorter-lived | Database + HttpOnly cookie (web). |
The access token's payload includes: userId, organizationId, role, email, emailVerified, onboardingCompleted, forcePasswordChange, and requiresTwoFactorSetup.
Refresh rotates everything
POST /api/auth/refresh
{ "refreshToken": "..." }
On every refresh, both tokens are rotated atomically — the old pair is deleted and a fresh pair issued in one transaction.
| Situation | Response | Meaning |
|---|---|---|
| Normal refresh | New access + refresh token | Old pair is now invalid. |
| Reusing an already-rotated refresh token | Token already rotated - use the new token | Treated as token theft — use the latest token your client received. |
| Two refreshes racing | 409 Token refresh in progress - please retry | Another refresh is mid-flight; retry shortly. |
Force password change
Users created by an administrator are created with forcePasswordChange = true. Until they set their own password, they are blocked (403) on everything except auth, profile, settings, and security pages, and are redirected to set a password. Setting the new password clears the flag and issues fresh tokens.
Password policy
The policy is org-configurable. The defaults are:
| Rule | Default |
|---|---|
| Minimum length | 8 characters (clamped to the 8–32 range) |
| Uppercase letter | Required |
| Lowercase letter | Required |
| Number | Required |
| Special character | Not required |
| Breached-password check | New passwords found in known breached-password lists are rejected |
New passwords are checked against known breached-password lists; the password itself never leaves our systems.
Changing your password logs you out everywhere
When you change your password, all of your refresh tokens are deleted (signing you out on every device), then a fresh pair is issued for your current session. The new password must be different from your current one.
Forgot & reset password
POST /api/auth/forgot-password
{ "email": "you@example.com" }
This always returns the same generic message — it never reveals whether the email exists. Behind the scenes it issues two credentials, both hashed in the database and valid for a limited time:
- a 6-digit code (handy for mobile entry), and
- a long URL token (embedded in the email link).
POST /api/auth/reset-password
{ "token": "<long token>", "password": "NewPass1", "email": "you@example.com" }
You may supply either the 6-digit code (in which case email is required) or the long token. On success:
- the password is updated,
- your email is marked verified (the reset link doubles as proof you control the inbox — useful for first-time setup),
- all refresh tokens are deleted, and
- a confirmation email is sent.
Email verification
POST /api/auth/verify-email
{ "token": "..." }
Verification is idempotent — clicking the link twice is harmless. Until you verify, you're blocked (403) on most endpoints and sent to the verification screen. A new verification email can be requested again after a short wait.
Troubleshooting
| Error | Cause | Fix |
|---|---|---|
401 Invalid email or password | Wrong credentials or a deactivated account (deliberately indistinguishable). | Re-check your password; if it's correct, contact your administrator — the account may be deactivated. |
403 Email verification required | Your email isn't verified yet. | Click the link in your verification email; resend after a short wait if needed. |
403 Password change required | You were created with a forced password change. | Set a new password when prompted. |
403 over the seat limit (non-executive) | The org has more users than its plan allows. | An admin/executive must reduce users or upgrade the plan. See Plans. |
Token already rotated | An old refresh token was reused. | Use the most recent token your client received; sign in again if unsure. |
409 Token refresh in progress | Two refreshes ran at once. | Retry the request. |
429 with retryAfter | Rate limit hit (e.g. too many logins). | Wait the indicated time, then retry. |
The forgot/reset credentials are valid for a limited time — request a fresh one if it has expired.
Security Overview
How BookYourPTO protects your account and your organization's data — authentication, encryption, rate limiting, security headers, audit logging, and account guards.
Two-Factor & Devices
Set up TOTP two-factor authentication, save backup codes, verify at login, and manage trusted devices in BookYourPTO.