GuidesSoftware DeveloperAuthentication (Next.js)

Authentication with Next.js and Geobase

In this guide, we’ll walk you through implementing a modern authentication blueprint using Next.js 14 and Geobase, featuring server-side session management, protected routes, and secure middleware handling.

geobase-auth-flow

What’s Included

This authentication blueprint provides:

  • 🔐 Server-side and client-side auth utilities
  • 🚀 Middleware session management
  • 🛡️ Protected route handling
  • 🍪 Secure cookie management
  • 📱 SSR-compatible authentication
ℹ️

This implementation uses geobase’s SSR-compatible authentication helpers for optimal security and performance.

GitHub Repository

You can find the complete source code for this authentication system in the following GitHub repository:

Authentication Patterns

Geobase Auth can be implemented in several ways:

  1. Server-Side Authentication (Recommended)

    • Tokens stored in cookies
    • Protected API routes
    • Server-side session verification
  2. Client-Side Authentication

    • Browser-based token storage
    • Real-time subscription support
    • Instant UI updates
ℹ️

Server-side auth is recommended for better security and SEO optimization.

Implementation

Client Setup

Create a browser client for client-side authentication:

// utils/geobase/client.ts
import { createBrowserClient } from '@supabase/ssr'
 
export function createClient() {
  return createBrowserClient(
    process.env.NEXT_PUBLIC_GEOBASE_URL!,
    process.env.NEXT_PUBLIC_GEOBASE_ANON_KEY!
  )
}

Server Setup

Set up server-side authentication handling:

// utils/geobase/server.ts
import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'
 
export function createClient() {
  const cookieStore = cookies()
  
  return createServerClient(
    process.env.NEXT_PUBLIC_GEOBASE_URL!,
    process.env.NEXT_PUBLIC_GEOBASE_ANON_KEY!,
    {
      cookies: {
        get(name) {
          return cookieStore.get(name)?.value
        },
        set(name, value, options) {
          try {
            cookieStore.set(name, value, options)
          } catch {
            // Cookie setting in Server Components can be ignored if middleware handles session refresh
          }
        },
        remove(name, options) {
          try {
            cookieStore.set(name, '', { ...options, maxAge: 0 })
          } catch {
            // Cookie removal in Server Components can be ignored if middleware handles session refresh
          }
        }
      }
    }
  )
}

Middleware Configuration

Create a middleware handler to protect routes and manage sessions:

// middleware.ts
import { type NextRequest } from 'next/server'
import { updateSession } from '@/utils/geobase/middleware'
 
export async function middleware(request: NextRequest) {
  return await updateSession(request)
}
 
export const config = {
  matcher: [
    '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
  ],
}
⚠️

The middleware matcher pattern excludes static files and images while protecting all other routes. Adjust the pattern based on your needs.

Session Management

Implement session updates in the middleware:

// utils/geobase/middleware.ts
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'
 
export async function updateSession(request: NextRequest) {
  let response = NextResponse.next({
    request: {
      headers: request.headers,
    },
  })
 
  const geobase = createServerClient(
    process.env.NEXT_PUBLIC_GEOBASE_URL!,
    process.env.NEXT_PUBLIC_GEOBASE_ANON_KEY!,
    {
      cookies: {
        get(name) {
          return request.cookies.get(name)?.value
        },
        set(name, value, options) {
          request.cookies.set({
            name,
            value,
            ...options,
          })
          response = NextResponse.next({
            request: {
              headers: request.headers,
            },
          })
          response.cookies.set({
            name,
            value,
            ...options,
          })
        },
        remove(name, options) {
          request.cookies.set({
            name,
            value: '',
            ...options,
          })
          response = NextResponse.next({
            request: {
              headers: request.headers,
            },
          })
          response.cookies.set({
            name,
            value: '',
            ...options,
          })
        },
      },
    }
  )
 
  const { data: { user } } = await geobase.auth.getUser()
 
  if (!user && !request.nextUrl.pathname.startsWith('/login')) {
    const url = request.nextUrl.clone()
    url.pathname = '/login'
    return NextResponse.redirect(url)
  }
 
  return response
}
ℹ️

Avoid adding logic between createServerClient and geobase.auth.getUser() to prevent unexpected session termination.

Environment Setup

To connect your app to Geobase, configure these environment variables. Include them in a .env.local file for local development.

NEXT_PUBLIC_GEOBASE_URL=https://YOUR_PROJECT_REF.geobase.app
NEXT_PUBLIC_GEOBASE_ANON_KEY=YOUR_GEOBASE_PROJECT_ANON_KEY

You can locate the project reference and anon key in your Geobase project settings.

Shareable Maps

Local Development

  • Set Node.js version: Use Node version 21:
    nvm use 21
  • Install dependencies: Use your preferred package manager:
    npm install
    # or
    yarn
    # or
    pnpm install
  • Start the development server with HTTPS enabled:
    npm run dev --experimental-https
    # or
    yarn dev --experimental-https
    # or
    pnpm dev --experimental-https
ℹ️

Note: Without --experimental-https, the email verification links might redirect to https://localhost:3000/..., causing errors. You can navigate manually by removing https from the URL if needed.

Access the project at https://localhost:3000.

Local Development

  1. Cookie Management

    • Always return the middleware response object as is
    • Maintain cookie synchronization between browser and server
    • Handle cookie operations carefully in Server Components
  2. Session Handling

    • Implement proper error handling for auth operations
    • Use try-catch blocks for cookie operations
    • Consider middleware refresh patterns for Server Components
  3. Security

    • Protect sensitive routes using middleware
    • Implement proper redirect handling
    • Maintain secure cookie handling practices

geobase-auth-flow

Best Practices

ℹ️

For support and questions, join the Geobase discord community.