AI-generert innhold
/Oskar Ydstebø

Supabase Auth i Next.js: Komplett guide for 2026

supabasenextjsauthdatabase

> TL;DR

Supabase Auth integreres i Next.js App Router via @supabase/ssr-pakken, med middleware for session-håndtering og Row Level Security (RLS) i PostgreSQL for sikker datatilgang.

Autentisering er noe av det viktigste — og mest frustrerende — å implementere i en webapplikasjon. Med Supabase og Next.js App Router har du en stack som gir deg full kontroll over brukerautentisering, session-håndtering og datatilgang — uten å skrive en eneste linje backend-kode for auth. Kombinert med Row Level Security, får du en komplett sikkerhetsmodell.

Vi bruker denne stacken i produksjon på Boligposten.com, og i denne guiden deler vi oppsettet steg for steg.

Hva trenger du for å komme i gang?

Før du starter, sørg for at du har:

| Krav | Detaljer | |------|----------| | Node.js | v18 eller nyere | | Next.js | v14+ med App Router | | Supabase-prosjekt | Opprett gratis på supabase.com | | Miljøvariabler | NEXT_PUBLIC_SUPABASE_URL og NEXT_PUBLIC_SUPABASE_ANON_KEY |

Hvordan installerer du Supabase i Next.js?

Start med å installere de nødvendige pakkene:

npm install @supabase/supabase-js @supabase/ssr

@supabase/ssr er den offisielle pakken for server-side rendering med Supabase. Den håndterer cookies og sessions automatisk i App Router.

Opprett deretter hjelpefunksjoner for å lage Supabase-klienter:

// lib/supabase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'

export async function createClient() {
  const cookieStore = await cookies()

  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) =>
            cookieStore.set(name, value, options)
          )
        },
      },
    }
  )
}
// lib/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr'

export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
  )
}

Hvordan setter du opp middleware for sessions?

Middleware er kritisk for å holde sessions oppdatert. Uten dette vil brukere logges ut uventet:

// middleware.ts
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'

export async function middleware(request: NextRequest) {
  let response = NextResponse.next({
    request: { headers: request.headers },
  })

  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return request.cookies.getAll()
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value }) =>
            request.cookies.set(name, value)
          )
          response = NextResponse.next({
            request: { headers: request.headers },
          })
          cookiesToSet.forEach(({ name, value, options }) =>
            response.cookies.set(name, value, options)
          )
        },
      },
    }
  )

  // Refresh session
  await supabase.auth.getUser()

  return response
}

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
}

Hvordan implementerer du login og registrering?

Med Supabase Auth kan du bruke flere strategier — e-post/passord, magic link, OAuth (Google, GitHub) og mer. Her er et eksempel med e-post:

// app/login/actions.ts
'use server'

import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'

export async function login(formData: FormData) {
  const supabase = await createClient()

  const { error } = await supabase.auth.signInWithPassword({
    email: formData.get('email') as string,
    password: formData.get('password') as string,
  })

  if (error) {
    redirect('/login?error=Feil e-post eller passord')
  }

  redirect('/dashboard')
}

export async function signup(formData: FormData) {
  const supabase = await createClient()

  const { error } = await supabase.auth.signUp({
    email: formData.get('email') as string,
    password: formData.get('password') as string,
  })

  if (error) {
    redirect('/login?error=Kunne ikke opprette konto')
  }

  redirect('/login?message=Sjekk e-posten din for bekreftelse')
}

Hva er Row Level Security og hvorfor er det viktig?

Row Level Security (RLS) er PostgreSQL sin mekanisme for å kontrollere hvilke rader en bruker kan lese, opprette, oppdatere og slette. Det er sikkerhetsmodellen som gjør at du kan eksponere Supabase-klienten direkte til frontend uten risiko. Les vår komplette RLS-guide for avanserte mønstre og beste praksis.

-- Aktiver RLS på en tabell
ALTER TABLE posts ENABLE ROW LEVEL SECURITY;

-- Bare autentiserte brukere kan lese
CREATE POLICY "Autentiserte kan lese"
  ON posts FOR SELECT
  TO authenticated
  USING (true);

-- Brukere kan bare oppdatere egne poster
CREATE POLICY "Brukere oppdaterer egne poster"
  ON posts FOR UPDATE
  TO authenticated
  USING (auth.uid() = user_id);

-- Brukere kan bare slette egne poster
CREATE POLICY "Brukere sletter egne poster"
  ON posts FOR DELETE
  TO authenticated
  USING (auth.uid() = user_id);

| RLS-policy | Effekt | |-----------|--------| | FOR SELECT | Kontrollerer hvem som kan lese | | FOR INSERT | Kontrollerer hvem som kan opprette | | FOR UPDATE | Kontrollerer hvem som kan endre | | FOR DELETE | Kontrollerer hvem som kan slette | | USING (auth.uid() = user_id) | Begrenser til egne rader |

Hvordan beskytter du sider med autentisering?

I Next.js App Router kan du sjekke auth-status i Server Components:

// app/dashboard/page.tsx
import { createClient } from '@/lib/supabase/server'
import { redirect } from 'next/navigation'

export default async function DashboardPage() {
  const supabase = await createClient()
  const { data: { user } } = await supabase.auth.getUser()

  if (!user) {
    redirect('/login')
  }

  return (
    <div>
      <h1>Velkommen, {user.email}</h1>
    </div>
  )
}

Hva er vanlige fallgruver?

Basert på erfaring fra Boligposten.com og andre prosjekter utviklet av Webagent AS:

  1. Manglende middleware — Uten middleware for session-refresh vil brukere oppleve uventede utlogginger.
  2. RLS ikke aktivert — Supabase deaktiverer RLS som standard. Alltid aktiver det på alle tabeller.
  3. Bruk getUser() ikke getSession()getUser() validerer mot Supabase-serveren, mens getSession() bare leser lokalt token. For sikkerhetskritiske sjekker, bruk alltid getUser().
  4. Glemmer auth callback route — For OAuth og magic links trenger du en /auth/callback route handler.

For bedrifter som bygger moderne nettsider med brukerinnlogging, er dette oppsettet en solid grunnmur.

// app/auth/callback/route.ts
import { createClient } from '@/lib/supabase/server'
import { NextResponse } from 'next/server'

export async function GET(request: Request) {
  const { searchParams, origin } = new URL(request.url)
  const code = searchParams.get('code')

  if (code) {
    const supabase = await createClient()
    await supabase.auth.exchangeCodeForSession(code)
  }

  return NextResponse.redirect(origin)
}

Denne stacken er også ideell for prosjekter som krever AI-integrasjon og GEO-optimalisering.

Oppsummering

Supabase + Next.js gir deg en moderne, sikker auth-stack uten å måtte bygge backend fra scratch. Nøklene er:

  • Bruk @supabase/ssr for korrekt cookie-håndtering
  • Implementer middleware for session-refresh
  • Aktiver RLS på alle tabeller
  • Bruk Server Actions for login/signup
  • Valider med getUser() i Server Components

Denne stacken skalerer fra MVP til produksjon — den er rask å sette opp, trygg å drifte, og fleksibel nok til å vokse med produktet.

Fra teori til praksis

Denne artikkelen er en del av hjelp.dev-eksperimentet — der vi tester om AI-drevet innhold kan bygge ekte autoritet. Alt innhold er åpent og GEO-optimalisert.

Bygget av Webagent AS i Bergen.