09 — User Behaviour (Auth Module)
- 1. Expected behaviour (server-contract-driven)
- 2. Common mistakes & countermeasures
- 3. Power & new users
- 4. Mobile & a11y users
- 5. Password managers
- 6. Interrupted sessions & retries
- 7. Abandonment
- 8. Frustration points → UX treatments (summary table)
- 9. Cross-device & conflict
- 10. Adoption path (holistic)
Expected behaviour (derived from server semantics + shared interaction rules), the common mistakes users make with these screens, and the UX countermeasures. Purpose: hand the UI designer a playbook of what the user does so the flow never surprises.
1. Expected behaviour (server-contract-driven)
- Login failure never distinguishes unknown email vs wrong password → UI must keep the
message generic to avoid teaching users "accounts exist" (
auth.service.ts 125/131/141). - Refresh is seamless: within the 15 min access TTL the app refreshes quietly; a 401 on
any request triggers single-flight
POST /auth/refresh; a second failure →SessionExpired. - After password reset all sessions die → user is logged out everywhere; from the client the only state is "session invalid"; UI: reason banner "Password was changed on another device" (so it reads as intentional).
- After logout, client clears local tokens, so the refresh never succeeds → login screen.
2. Common mistakes & countermeasures
| Mistake | Related | UX countermeasure |
|---|---|---|
| Typing wrong/` casecaps-lock for password | Login | show error; ensure a visible hint "Caps Lock is on" would help (proposed); reveal toggle; keep team away from password manager-fighting |
| Forgetting which tenant/school id | Register | placeholder + example; hint autofilled from invite |
| Losing / reusing the verify-email token (email link fired twice / link lost) | verify | server returns "already verified" → benign; resend link (rate-limited) |
| Resend obnoxious spam | resend-verification | rate 5/120s, cap UX "Wait 1 min" |
| Tapping "log out all" then leaving the device | logout-all | confirm dialog; after action show "logged out everywhere" result |
| Losing 2FA device & can't get in | 2fa | recovery codes (planned) + clear warning at setup: "save these recovery codes" |
| Revoking a device you're currently on → locked out of that session | sessions | identify current row (badge "This device"); warn on revoke of current |
3. Power & new users
- Power user: global shortcuts
Ctrl+Lfocus login field; fast tabbing; API key creation with pasted name; batch revoke pattern; saves assert favs. - New user (register): walk first-run task list ("Verify email", "Set up 2FA", "Invite staff") after token auto-login.
4. Mobile & a11y users
- One-thumb phone: resty single required CTA, min 48 target.
- TalkBack/VoiceOver: login flow fully walkable; errors announced on focus; TOTP sheet single-field semantics; copy buttons labeled.
- Dynamic type 200%: pre-auth forms reflow (no fixed widths).
- Reduced motion: no shake/animation; error = color+icon+text.
5. Password managers
- Correct
autofillHintseverywhere; serverside: password min 8 BUT login min 6 → managers may propose 8-char passwords that pass register but then get 6-char validation... Actually login is a verifier; managers generate ≥12; UI should accept managers' output. - In-app
Autofill: on web,<input autocomplete>; FlutterTextInputAction.
6. Interrupted sessions & retries
- Suspend/resume: app killed mid-session: secure-storage tokens intact → quiet refresh → home.
- Mid-login interruption (app kill): form state lost; return → fresh.
- Retry after rate limit: countdown; auto-resubmit only when the user re-taps.
- Server 5xx after login: show generic error +
requestId, keep form, suggest retry; tokens not committed.
7. Abandonment
- Where people quit and what to do:
registermid-way → email capture for invite context; UX: one-tap "resume".resettoken not clicked within 1 h → expired banner, one tap re-send.2fa enableafter obtaining secret → incomplete → show "Finish 2FA setup" reminder row on Security hub (client memoized).
8. Frustration points → UX treatments (summary table)
| Frustration | Treatment |
|---|---|
| "Account locked. Try again later." | Show remaining seconds from server lockedUntil (client can't compute; show "after MM:SS" only if known) — else generic + retry timer |
| 429 on login | countdown chip + "no auto-retry" |
| Device access after revoke | confirm; state icon change |
| Unknown key prefix | no "secret" leaks in UI; only prefix shown |
9. Cross-device & conflict
- Concurrent login on two devices → two sessions (
user_sessionsper device). Conflicting change (e.g., reset on one) → other device receives "session expired" on next action. - Revocation of the wallet's current session → immediate force logout of the app
(
sessionExpired).
10. Adoption path (holistic)
P0 release: register→login→verify→password reset→logout. P1: sessions/devices, 2FA,
api-keys. P2 (planned): recovery codes, impersonation, unlock, revoke-others, 2FA challenge
step (IMPLEMENTATION_PLAN.md).