Documentation

Protecting Routes

Keep authorization decisions in your app using local sessions backed by Radiant Auth tokens.

Recommended pattern

  1. After OAuth callback, create a server-side session row that stores tokens.
  2. Set an opaque httpOnly cookie referencing that session.
  3. On protected routes, load the session from the cookie.
  4. Refresh tokens if the access token is near expiry.
  5. Redirect unauthenticated users to your login route (which starts OAuth).
require-user.ts
// Pseudocode — adapt to your framework
export async function requireUser(request: Request) {
  const sessionId = getCookie(request, "app_session");
  if (!sessionId) return Response.redirect("/login", 302);

  const session = await db.sessions.find(sessionId);
  if (!session) return Response.redirect("/login", 302);

  if (session.accessTokenExpiresAt < Date.now() + 60_000) {
    await refreshSessionTokens(session);
  }

  return session.user;
}

API routes

For JSON APIs, return 401 instead of redirecting. Optionally accept a Bearer access token for machine clients, verifying JWTs with JWKS when audience-bound tokens are used.

First-party session checks

JWT access tokens cannot be revoked mid-lifetime. First-party Radiant apps should call POST /api/internal/user-access after verifying the token so bans and revoked OAuth grants take effect immediately. Authenticate that call with INTERNAL_API_SECRET.

What not to do

  • Do not trust client-supplied user IDs without a verified session/token.
  • Do not put access tokens in localStorage for confidential web apps.
  • Do not skip state validation on the OAuth callback.
Tip
Pair route guards with logout that both clears the cookie and revokes tokens.