Skip to content
    SeaCode
    Learning tracksCode ArenaWorkshops & EventsInstructors
    Log inSign up
    NNext.js

    Next.js foundations

    • What is Next.js?
    • The App Router: folders are routes
    • Dynamic routes
    • Client-side navigation

    Server, client and data

    • Server and Client Components
    • Fetching data on the server
    • loading, error and not-found
    • Caching and revalidation

    Mutations, APIs and security

    • Server Actions
    • Route Handlers: building an API
    • Proxy (formerly Middleware)
    • Authentication and protecting pages

    Going to production

    • Metadata and SEO
    • Images, fonts and performance
    • Environment variables and deploying to Vercel
    • Project: a course catalogue
    Next.js

    Mutations, APIs and security · Lesson 12 of 16

    Authentication and protecting pages

    Sessions in cookies, checking at every layer, and Supabase Auth.

    11 minutes2 games

    Authentication = "who are you?"; authorization = "what may you do?". In Next.js the session usually lives in a secure cookie (httpOnly, secure, sameSite), so the server can read it in the proxy, pages and actions, while browser JavaScript can't steal it.

    TypeScript
    // lib/auth.ts: one helper, used everywhere on the server
    import "server-only"
    import { redirect } from "next/navigation"
    import { createClient } from "@/utils/supabase/server"
    
    export async function requireUser(role?: "instructor" | "admin") {
      const supabase = await createClient()
      const { data: { user } } = await supabase.auth.getUser()     // verified with Supabase, not just decoded
      if (!user) redirect("/login")
      if (role) {
        const { data: profile } = await supabase.from("profiles").select("role").eq("id", user.id).single()
        if (profile?.role !== role && profile?.role !== "admin") redirect("/dashboard")
      }
      return user
    }
    
    // app/instructor/page.tsx
    export default async function InstructorPage() {
      const user = await requireUser("instructor")
      return <h1>Welcome back, {user.email}</h1>
    }
    LayerWhat it doesEnough alone?

    proxy.ts

    quick redirect for signed-out users

    no

    page / layout

    requireUser() before rendering

    no (actions are called directly)

    server action / route

    requireUser() + permission on this resource

    almost

    database (RLS)

    rows only readable/writable by their owner

    the last line of defence

    Defense in depth: each layer assumes the one before may fail.

    Important

    Verify the user on the server with getUser() (which asks Supabase), not getSession(), which only reads the cookie, since cookies can be forged. And never rely on hiding a button as protection: if the action or API doesn't check, anyone can call it from the console.

    Quick question

    The /admin page is protected only in the proxy. The deleteUser server action it uses doesn't check the role. Is that safe?

    Interview question

    Session cookies versus a JWT in localStorage: which is safer?

    Exercise

    Write canEdit(user, project): a user may edit when they own the project (project.ownerId === user.id) or their role is admin. A null user may not. Print the four results.

    Expected output:
    true
    false
    true
    false
    JavaScript
    function canEdit(user, project) {
      return true
    }
    
    const project = { id: 7, ownerId: "u1" }
    console.log(canEdit({ id: "u1", role: "student" }, project))
    console.log(canEdit({ id: "u2", role: "student" }, project))
    console.log(canEdit({ id: "u3", role: "admin" }, project))
    console.log(canEdit(null, project))

    Learn more from

    • Next.js docs: Authentication guidenextjs.org
    • Supabase docs: Server-side auth for Next.jssupabase.com
    • Supabase docs: Row Level Securitysupabase.com
    • OWASP: Session Management Cheat Sheetcheatsheetseries.owasp.org

    Played 0 of 2 games

    Sign in to save your progress and earn XP.

    PreviousProxy (formerly Middleware)NextMetadata and SEO
    SeaCode

    Learn to code for real, online or at our branch in front of Cairo University, Giza.

    Learn

    • All courses
    • Interactive tutorials
    • Interview practice problems
    • Mock interview
    • Learning tracks
    • Code Arena
    • Workshops & Events
    • Knowledge library
    • Team projects

    Your account

    • Log in
    • Sign up
    • Learning plan
    • Certificates
    • Site map

    Contact us

    • WhatsApp
    • 010 9094 1104
    • In front of Cairo University, Giza

    © 2026 SeaCode. All rights reserved.