Skip to content

Admin Authentication & Security

How admin sessions work and security features protecting admin routes

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:

  1. JWT token is created with your admin user ID and expiration (24 hours)
  2. Token is signed using HMAC-SHA256 with the ADMIN_JWT_SECRET
  3. Token stored in cookies as admin-token and sent with all admin API requests
  4. 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/*:

  1. Public paths allowed - /admin/login, /admin/forgot-password, /admin/reset-password
  2. Token validation - All other admin routes require valid admin token
  3. Automatic redirects - Unauthenticated users redirected to /admin/login
  4. Session refresh - Valid tokens extend session automatically

Cron Route Protection

Cron routes at /api/cron/* are protected separately:

  • Vercel Cron Secret - Must match CRON_SECRET environment 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

  1. Navigate to /admin/login
  2. Enter admin email and password
  3. System validates credentials against User table
  4. Check ADMIN role - Non-admins rejected
  5. Generate JWT token with 24-hour expiration
  6. 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:

  1. Check token expiration - Log in again if session expired
  2. Verify ADMIN role - User must have role: ADMIN in database
  3. Check environment variables - ADMIN_JWT_SECRET must be set
  4. Clear cookies - Old/invalid tokens may be cached

Mobile iOS Auth Issues

If admin routes fail on iOS mobile:

  1. Check X-Auth-Token header - Ensure mobile app sends this fallback header
  2. Verify token format - Must be raw JWT, no "Bearer" prefix on X-Auth-Token
  3. Test on Android - Confirm Authorization header works on non-iOS devices
  4. Check middleware logs - Look for "iOS auth header fallback" messages
  • Audit Logs - Track all admin actions
  • User Roles - Understand ADMIN vs MEMBER permissions
  • Cron Auth - Automated task authentication
  • OAuth Security - Third-party API authentication
Was this helpful?
Contact Support →