HyperSaaS
FrontendAuthentication

Overview

Auth.js sessions, signing in through django-allauth, and two-factor authentication.

HyperSaaS uses Auth.js (NextAuth.js v5) for the browser's session. Signing in goes through the Django backend's allauth API: the email and password, then, when two-factor authentication is on, a code from an authenticator app or one emailed to them. The Next.js server makes those calls and keeps the tokens; the browser never sees one.

Architecture

Browser                      Next.js                              Django (allauth)
  │                            │                                     │
  │  email + password          │                                     │
  │───────────────────────────►│  POST /_allauth/app/v1/auth/login   │
  │                            │────────────────────────────────────►│
  │                            │  ◄── tokens, or "code needed" ──────│
  │  (code needed)             │                                     │
  │  ◄── "enter your code" ────│  session token kept in an           │
  │                            │  httpOnly cookie for 5 minutes      │
  │  6-digit code              │                                     │
  │───────────────────────────►│  POST .../auth/2fa/authenticate     │
  │                            │────────────────────────────────────►│
  │                            │  ◄── access + refresh tokens ───────│
  │                            │                                     │
  │  ◄── session cookie ───────│  Tokens kept in the encrypted       │
  │                            │  Auth.js cookie                     │
  │  API request               │                                     │
  │───────────────────────────►│  Authorization: Bearer {token}      │
  │                            │────────────────────────────────────►│

Key Components

ComponentLocationPurpose
Auth.js configlib/auth/providers.tsThe token provider, refresh, sign-out
Sign-in actionslib/auth/actions.tsThe password step, the code step, changing the password
allauth callslib/auth/allauth.tsCalls allauth as the user; relayToAllauth for API routes
Tokenslib/auth/tokens.ts, lib/auth/utils.tsgetAccessToken(), refresh, the browser-safe session
Proxyproxy.tsProtects routes, and saves refreshed tokens
Two-factor settingscomponents/settings/two-factor/The Security card, recovery codes, "confirm it's you"

Auth Pages

PageRouteDescription
Login/loginEmail + password, then a code if two-factor is on
Register/registerAccount creation → email verification
Activate/user-activation/[uid]/[token]Email verification link
Reset Password/reset-passwordRequest password reset email
Confirm Reset/confirm-password-reset/[uid]/[token]Set new password
Resend Activation/resend-activationRequest new activation email
Change Email/reset-usernameEmails a link to the current address
Choose New Email/confirm-username-reset/[uid]/[token]Sends a confirmation link to the new address
Confirm Email Change/confirm-email-change/[token]Makes the change; the old address is told

A failed sign-in says why: a wrong email or password, an account that hasn't been activated yet, or too many attempts.

Session Shape

The session the browser can read says who you are, and nothing more:

interface Session {
  user: {
    id: string;
    name?: string | null;
    email?: string | null;
  };
  error?: "RefreshAccessTokenError";
}

Server code gets the access token with getAccessToken(). Before a session reaches the browser, from /api/auth/session or the session passed to SessionProvider, the token is taken out (forBrowser in lib/auth/tokens.ts).

Plans belong to workspaces, so the session carries no subscription details; the workspace layout reads them from /api/workspaces/{id}/plan/. After the account settings change your name or email, the page calls useSession().update(), and the session reads them again from /auth/users/me/.

Token Refresh

The access token lasts 15 minutes. Auth.js refreshes it a minute before it expires, in its jwt callback, and keeps the new refresh token (each one works once). If refreshing fails, because you signed out elsewhere, the password changed or the session expired, the session ends and you sign in again. See Token Flow.

On this page