ASAASA Standard
Active Phase 1Production Foundation

getUser() vs getSession()

Auth Safety · AUTH-13 · Priority: P0

Why It Matters

In Supabase, getSession() reads the JWT from the local cookie or storage without verifying it with the server. An attacker can craft or modify a JWT locally, and getSession() will trust it. Only getUser() makes a server-side call to Supabase Auth to verify the token is valid and the user actually exists.

AI code generators almost universally use getSession() for auth checks because it's faster and appears in more Supabase examples. But using it for authorization decisions means your app trusts unverified client-side data.

Priority: P0 — Using getSession() for auth checks is equivalent to trusting a self-signed ID card.

Affected Stack: Supabase Auth (SSR and client)


The Problem

// ❌ What AI tools typically generate
export async function GET(req: Request) {
  const supabase = createServerClient(/* ... */);
  const { data: { session } } = await supabase.auth.getSession();

  if (!session) {
    return new Response('Unauthorized', { status: 401 });
  }

  // Trusts the JWT without server verification!
  const userId = session.user.id;
  const data = await supabase.from('profiles').select('*').eq('id', userId);
  return Response.json(data);
}

The session.user object comes from decoding the JWT locally. If the JWT is expired, revoked, or tampered with, getSession() won't detect it.


The Fix

Use getUser() for any auth decision that controls access to data or actions.

// ✅ Server-verified auth
export async function GET(req: Request) {
  const supabase = createServerClient(/* ... */);
  const { data: { user }, error } = await supabase.auth.getUser();

  if (error || !user) {
    return new Response('Unauthorized', { status: 401 });
  }

  // user.id is verified by Supabase Auth server
  const data = await supabase.from('profiles').select('*').eq('id', user.id);
  return Response.json(data);
}

When is getSession() acceptable?

  • For non-sensitive UI decisions (showing/hiding a menu item)
  • For pre-checks before a full getUser() call (performance optimization)
  • Never for authorization, data access, or mutations

References


Related Checks


Is your app safe? Run Free Scan →