Feature Owner: scorevi (Sean Patrick Caintic)
Module: Auth & Security
Priority: P0
Sprint #12: Fully Implemented
Date: 2026-06-29
EXECUTIVE SUMMARY
What is this feature?
A time-bounded, single-use re-authentication system that requires admins to verify their identity (password or email confirmation) before performing destructive actions like deleting users, changing roles, transferring agency ownership, or modifying Gemini AI configuration.
Why does it matter?
Even an authenticated admin session can be hijacked (XSS, unattended computer). Without re-auth, a malicious actor with access to an active session could delete all users or transfer agency ownership without any additional verification.
What's the MVP scope?issueReAuthToken() generates a UUID token with 5-minute TTL stored in admin_reauth_tokens. consumeReAuthToken() validates and marks as used (single-use). Token passed via request body (reauthToken field). ReAuthModal component (240 lines) auto-detects auth method. Protected endpoints: delete-user, change-role, agency delete/PATCH, gemini-config.
1. USER PAIN POINT & SOLUTION
Current State (Without Feature)
An admin signs in, leaves their computer unlocked, and someone else can access the admin panel and perform destructive actions without any additional verification.
Pain Point
Emotional: Anxiety about session hijacking — especially for admins with full platform access.
Functional: No secondary verification barrier for destructive actions.
Business Impact: Catastrophic data loss risk. GDPR/compliance violation risk from unauthorized data modification.
Future State (With Feature)
Before any destructive action, the admin must re-verify their identity. A 5-minute token is issued and consumed. After use, the token is invalidated. Audit logs track all re-auth attempts.
Marketing Hook
"Double-check before you wreck. Re-authentication protects what matters."
2. 4D FRAMEWORK MAPPINGDiagnose
N/A — security infrastructure.
Design
N/A — security infrastructure.
Develop
N/A — security infrastructure.
Deliver
N/A — security infrastructure.
3. USER FLOWS
Entry Point
Admin clicks a destructive action button (e.g., "Delete User", "Change Role", "Delete Agency", "Transfer Ownership", or saves Gemini config).
Success Criteria
Admin successfully re-authenticates, receives a 5-minute token, and the protected action executes. Token is consumed (single-use) and cannot be reused.
Main Flow (Happy Path)
Admin initiates a protected action (e.g., delete user).
Frontend calls
GET /api/admin/reauthto detect available auth methods.ReAuthModal opens, displaying password or email confirmation prompt.
Admin enters password (or confirms email).
Frontend calls
POST /api/admin/reauthwith credentials.Server validates: non-admin → 403, wrong password → 401, email mismatch → 401.
On success:
issueReAuthToken()generates UUID token, stored inadmin_reauth_tokenswith 5-minute TTL.Response returns
{ token, expiresInSeconds: 300 }.Frontend includes token as
reauthTokenin the destructive action's request body.Server calls
consumeReAuthToken(): validates token exists, belongs to requesting admin, not expired, not used.Server marks token as
used = true.Destructive action executes. Audit log entry written.
Edge Cases
Token expired:
consumeReAuthTokenreturns 403 "Re-authentication token has expired. Please re-authenticate."Token already used: Returns 403 "Re-authentication token has already been used."
Wrong admin: Token belongs to Admin A, but Admin B tries to use it → 403.
DB error persisting token:
issueReAuthTokenthrows"Could not issue re-authentication token".DB error consuming token:
consumeReAuthTokenfails to mark as used → 403 "Failed to validate re-authentication token".
Decision Points
IF user is not an admin → 403
ApiResponseHelper.forbidden().IF password is wrong → 401
ApiResponseHelper.unauthorized().IF email doesn't match → 401
ApiResponseHelper.unauthorized().IF token expired (now >
expires_at) → 403AuthorizationError.IF token already used (
used === true) → 403AuthorizationError.
4. INFORMATION ARCHITECTURE
Primary Information (Always visible)
ReAuthModal with password field or email confirmation prompt.
Auth method indicator (auto-detected via
GET /api/admin/reauth).
Secondary Information
"Action requires re-authentication" explanatory text.
Token TTL countdown (if shown in future UI).
Actions
Primary CTA: "Confirm" button to submit credentials.
Secondary Actions: "Cancel" button to abort the destructive action.
5. WIREFRAMES
[Excluded — existing UI: components/admin/ReAuthModal.tsx (240 lines)]
6. WIREFLOWS
Excluded.
7. PROTOTYPE
[Excluded — existing implementation]
8. BACKEND SCHEMA
Database Tables
admin_reauth_tokens:
Column | Type | Description |
|---|---|---|
| (auto) | Primary key |
| TEXT NOT NULL UNIQUE | UUID v4 token (not UUID DB type) |
| TEXT | Clerk ID of the admin |
| TIMESTAMPTZ | Token expiry (issued_at + 5 min) |
| BOOLEAN | Whether token has been consumed (single-use) |
| TEXT (nullable) | Client IP for audit trail |
| TIMESTAMPTZ | Token creation time |
audit_logs:
Column | Type | Description |
|---|---|---|
| (auto) | Primary key |
| UUID | References |
| VARCHAR(100) | Action performed |
| VARCHAR(50) | Type of entity affected |
| UUID | ID of entity affected |
| TEXT | Client user agent string |
9. API ENDPOINTS
Method | Endpoint | Auth | File | Description |
|---|---|---|---|---|
GET |
| Admin |
| Auto-detects available auth methods (password or email confirmation) |
POST |
| Admin |
| Validates credentials, returns |
Protected endpoints requiring reauthToken in request body:
POST /api/admin/delete-user— user deletionPOST /api/admin/change-role— role changeDELETE /api/admin/agencies/[id]— agency deletionPATCH /api/admin/agencies/[id]— ownership transferPOST(gemini-config server action) — AI configuration changes
Response shapes:
Success (POST reauth):
{ token: string, expiresInSeconds: 300 }Non-admin access: 403
ApiResponseHelper.forbidden()Wrong password: 401
ApiResponseHelper.unauthorized()Email mismatch: 401
ApiResponseHelper.unauthorized()
10. DATA REQUIREMENTS
Frontend Needs
ReAuthModalcomponent (components/admin/ReAuthModal.tsx, 240 lines) for credential input.Token storage in component state (passed to subsequent API call).
Auto-detection of auth method via
GET /api/admin/reauth.
API Calls Frontend Will Make
GET /api/admin/reauth→ determine auth method (password or email confirmation).POST /api/admin/reauthwith credentials → receive token.Protected action API call with
{ reauthToken, ...actionPayload }→ action executes.
Caching Strategy
Token is stored in memory (React state) and consumed immediately. No caching — single-use by design.
11. PERFORMANCE CONSIDERATIONS
Database Optimization
admin_reauth_tokens.tokenhas UNIQUE constraint — indexed for fast lookup.Token consumption is a single UPDATE by primary key.
API Response Time
issueReAuthToken: <50ms (single INSERT).consumeReAuthToken: <100ms (SELECT + UPDATE).Reauth API: <200ms (credential validation + token issue).
Who can access this feature?
Only admin users. Non-admin requests return 403.
Reauth endpoint: non-admin → 403
ApiResponseHelper.forbidden().Token validation:
adminClerkIdmust match the requesting admin → otherwise 403.Token is single-use: marked
used = trueon first consumption.Token TTL:
REAUTH_TTL_MINUTES = 5(300 seconds).Token generated via
randomUUID()(cryptographically secure).Token passed via request body (
reauthTokenfield), NOT header.
Data Validation
Password/email validation against Clerk (server-side, never exposed to client).
Token UUID format validation via database UNIQUE constraint + exact match query.
13. ERROR HANDLING
Error | Response |
|---|---|
Non-admin accesses reauth endpoint | 403 |
Wrong password | 401 |
Email mismatch | 401 |
Token not found | 403 |
Token belongs to different admin | 403 |
Token already used | 403 |
Token expired | 403 |
Failed to persist token |
|
Failed to mark token used | 403 |
14. TESTING CHECKLIST
Happy Path
□ Admin re-authenticates with correct password → token issued → protected action uses token → action succeeds → token marked used.
□ Admin re-authenticates via email confirmation → token issued → action succeeds.
Edge Cases
□ Non-admin accesses reauth endpoint → 403.
□ Wrong password → 401.
□ Attempt to reuse consumed token → 403 "already been used".
□ Attempt to use expired token → 403 "has expired".
□ Attempt to use another admin's token → 403 "does not belong to this admin".
□ DB insert error during token issue → Error thrown, 500 returned.
□ DB update error during token consumption → 403.
□ Token used within 5-minute window → valid.
□ Token used after 5 minutes → expired.
15. OPEN QUESTIONS
Should the 5-minute TTL be configurable per environment?
Should reauth be required for additional admin actions (e.g., changing system config)?
Should audit logs include the reauth token ID for traceability?
16. OUT OF SCOPE (v1.1+)
TOTP / authenticator app-based re-authentication.
Biometric re-authentication (WebAuthn).
Configurable reauth TTL per action type.
Reauth requirement for non-admin roles (e.g., agency owners).
17. SUCCESS METRICS
100% of protected destructive actions require valid reauth token.
Zero token reuse incidents.
<2 second reauth flow completion time.
18. DEPENDENCIES
This feature depends on:
Clerk for admin identity verification (password/email validation).
lib/auth/reauth.ts(94 lines):issueReAuthToken(),consumeReAuthToken().lib/auth/authenticate.ts:AuthorizationErrorclass.admin_reauth_tokenstable for token persistence.audit_logstable for action logging.components/admin/ReAuthModal.tsx(240 lines) for UI.
These features depend on this:
Admin user management (delete, role change).
Agency management (delete, ownership transfer).
Gemini AI configuration.
19. TIMELINE & OWNERSHIP
Implemented: Sprint 0 (foundational).
Owner: scorevi (Sean Patrick Caintic)
Document Version
1.0 - Initial version - 2026-06-29 08:06 UTC
1.1 - Added Document Version section and update author to have full name - 2026-06-29 08:41 UTC