Admin Authentication & Security
How admin sessions work and security features protecting admin routes
On this page
Overview
BlueClerk admin routes are protected by multiple layers of security to prevent unauthorized access. Admin authentication uses JWT tokens with HMAC-SHA256 verification, automatic expiration, and fallback mechanisms to ensure only authorized administrators can access sensitive platform operations.
How Admin Authentication Works
Admin Session Tokens
When you log in to the admin panel:
- JWT token is created with your admin user ID and expiration (24 hours)
- Token is signed using HMAC-SHA256 with the ADMIN_JWT_SECRET
- Token stored in cookies as
admin-tokenand sent with all admin API requests - Middleware validates the token on every admin route access
Token Verification
Every admin request goes through verification:
- Signature check - Token must be signed with the correct secret
- Expiration check - Token must not be expired (24-hour limit)
- Type check - Token must have
type: "admin"in payload - User lookup - Admin user must exist and have ADMIN role
iOS Authorization Header Workaround
Mobile iOS devices strip the standard Authorization header. Admin routes accept tokens from:
- Authorization header - Standard
Bearer <token>format (web/Android) - X-Auth-Token header - Fallback for iOS mobile apps
- admin-token cookie - Browser sessions
Admin Route Protection
Middleware Security
The admin middleware protects routes at /admin/* and /api/admin/*:
- Public paths allowed -
/admin/login,/admin/forgot-password,/admin/reset-password - Token validation - All other admin routes require valid admin token
- Automatic redirects - Unauthenticated users redirected to
/admin/login - Session refresh - Valid tokens extend session automatically
Cron Route Protection
Cron routes at /api/cron/* are protected separately:
- Vercel Cron Secret - Must match
CRON_SECRETenvironment variable - Authorization header -
Bearer <CRON_SECRET>required on all cron requests - 503 rejection - Missing or invalid secret returns Service Unavailable
API Route Protection
Admin API routes use getAdminSession() helper:
const admin = await getAdminSession()
if (!admin) return NextResponse.json({ error: "Unauthorized" }, { status: 401 })
This ensures:
- Admin token is validated
- User has ADMIN role
- Session is active and not expired
Security Features
Token Hardening
- 256-bit HMAC-SHA256 - Cryptographically secure signing
- 24-hour expiration - Automatic timeout for inactive sessions
- Type validation - Only tokens with
type: "admin"accepted - No client manipulation - Signature prevents tampering
Signup Guards
Company signups are protected with:
- Email domain validation - No disposable email services (yopmail, mailinator, etc.)
- Approval workflow - Company accounts require admin approval before activation
- Turnstile verification - Cloudflare bot protection on signup forms
Session Management
- Automatic logout - Expired tokens require re-authentication
- Cookie security - HTTPOnly, Secure flags on production
- Token rotation - New token on each login (old tokens invalidated)
Admin Login Flow
- Navigate to
/admin/login - Enter admin email and password
- System validates credentials against User table
- Check ADMIN role - Non-admins rejected
- Generate JWT token with 24-hour expiration
- Set admin-token cookie and redirect to
/admin/operations/overview
Security Best Practices
For Admins
- Use strong passwords - Minimum 8 characters with complexity
- Log out when done - Don't leave sessions open on shared devices
- Monitor audit logs - Review login activity regularly
- Rotate secrets - Update ADMIN_JWT_SECRET periodically
For Developers
- Never log tokens - Keep admin tokens out of logs and error messages
- Use getAdminSession() - Don't reimplement auth checks
- Validate on every route - Never assume authentication
- Test token expiration - Verify 24-hour timeout works correctly
Troubleshooting
"Unauthorized" Errors
If you see 401 errors on admin routes:
- Check token expiration - Log in again if session expired
- Verify ADMIN role - User must have role: ADMIN in database
- Check environment variables - ADMIN_JWT_SECRET must be set
- Clear cookies - Old/invalid tokens may be cached
Mobile iOS Auth Issues
If admin routes fail on iOS mobile:
- Check X-Auth-Token header - Ensure mobile app sends this fallback header
- Verify token format - Must be raw JWT, no "Bearer" prefix on X-Auth-Token
- Test on Android - Confirm Authorization header works on non-iOS devices
- Check middleware logs - Look for "iOS auth header fallback" messages
Related Features
- Audit Logs - Track all admin actions
- User Roles - Understand ADMIN vs MEMBER permissions
- Cron Auth - Automated task authentication
- OAuth Security - Third-party API authentication