Skip to content

Authentication

LaunchKit Pro uses JWT access tokens and refresh tokens stored in the database. The frontend persists tokens in localStorage and attaches Authorization: Bearer <accessToken> to API requests.

Endpoints (summary)

MethodPathAuthDescription
POST/auth/registerPublicCreate account
POST/auth/loginPublicSign in
POST/auth/refreshPublicRotate tokens
POST/auth/logoutPublicRevoke refresh token
GET/auth/meBearerCurrent user profile
POST/auth/forgot-passwordPublicRequest reset email (mock)
POST/auth/reset-passwordPublicReset with token
POST/auth/resend-verificationPublicResend verification email
POST/auth/verify-emailPublicVerify email with token

Register

bash
curl -s -X POST http://localhost:4000/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "ChangeMe123",
    "name": "Demo User"
  }' | jq

Password rules: minimum 8 characters with at least one letter and one number.

Login

bash
curl -s -X POST http://localhost:4000/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "ChangeMe123"
  }' | jq

Response includes accessToken, refreshToken, and user.

Refresh token

When the access token expires, the client calls:

bash
curl -s -X POST http://localhost:4000/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{"refreshToken": "<refreshToken>"}' | jq

Logout

bash
curl -s -X POST http://localhost:4000/auth/logout \
  -H "Content-Type: application/json" \
  -d '{"refreshToken": "<refreshToken>"}'

Forgot password

bash
curl -s -X POST http://localhost:4000/auth/forgot-password \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'

With EMAIL_PROVIDER=MOCK, reset links appear in email logs — not real inbox delivery.

Reset password

bash
curl -s -X POST http://localhost:4000/auth/reset-password \
  -H "Content-Type: application/json" \
  -d '{
    "token": "reset-token-from-email-log",
    "newPassword": "NewPass123"
  }'

Email verification

bash
curl -s -X POST http://localhost:4000/auth/verify-email \
  -H "Content-Type: application/json" \
  -d '{"token": "verification-token-from-email-log"}'

Resend:

bash
curl -s -X POST http://localhost:4000/auth/resend-verification \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com"}'

Token security

  • Use long random JWT_ACCESS_SECRET and JWT_REFRESH_SECRET in production
  • Rotate secrets if compromised (invalidates existing tokens)
  • Never log access or refresh tokens
  • Never commit tokens to git or support tickets
  • Frontend stores tokens in localStorage today — acceptable for starter kit; consider hardened storage for high-security products

Future improvement: HttpOnly cookies

A future module may move refresh tokens to HttpOnly, Secure, SameSite cookies to reduce XSS exposure. Current implementation uses JSON body + localStorage for simplicity and SPA compatibility.

Protected route redirect (from)

When an unauthenticated user opens a protected page (e.g. /dashboard/billing):

  1. GuestGuard redirects to /login?from=/dashboard/billing
  2. After successful login, the app navigates to the sanitized from path
  3. Invalid or external URLs fall back to /dashboard

Implementation: sanitizeRedirectPath() — blocks open redirects and login loops.

Logout behavior

Logout clears local session and uses hard navigation to / so:

  • No stale ?from= query from the previous page
  • Workspace and auth context reset cleanly

Suspended accounts

When User.status = SUSPENDED:

LayerBehavior
Login403 — friendly message in UI (not raw USER_SUSPENDED code)
RefreshBlocked for non-active users
JWTRejects non-ACTIVE users

Login page message:

Your account is suspended. Please contact your workspace administrator or support team.

Contact Support opens a mailto link (NEXT_PUBLIC_SUPPORT_EMAIL, default support@launchkitlabs.com).

Normal invalid-password errors do not show the support CTA.

Workspace context on login

Login and GET /auth/me return:

  • activeWorkspace — first ACTIVE workspace only
  • hasActiveWorkspace / workspaceUnavailableReason when user has only suspended memberships

See Workspaces & Team and UI/UX Polish.

LaunchKit Pro by LaunchKit Labs — buyer documentation. No secrets in this site.