JSTAcademy
0 XP
Dashboard
Crash Courses
Authentication in APIs
11 min
Basic+150 XP
Crash Courses · Basic

Authentication in APIs

Secure REST endpoints with JWT tokens and API key authentication.
11 min read+150 XP on completionCert: REST APIs Crash Course
Tap any word in the text below to start reading from there.

Authentication in APIs

REST APIs are stateless — authentication tokens must be sent with every request in headers.

JWT Auth Pattern

// Middleware auth check
import { createServerClient } from '@supabase/ssr'
import { NextRequest, NextResponse } from 'next/server'

async function getAuthUser(req: NextRequest) {
  const authHeader = req.headers.get('Authorization')
  if (!authHeader?.startsWith('Bearer ')) return null

  const token = authHeader.slice(7)
  const supabase = createClient()
  const { data: { user } } = await supabase.auth.getUser(token)
  return user
}

// Protected route
export async function GET(req: NextRequest) {
  const user = await getAuthUser(req)
  if (!user) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
  }

  const progress = await getProgress(user.id)
  return NextResponse.json({ data: progress })
}

Sending Auth from the Client

'use client'
import { createClient } from '@/lib/supabase/client'

async function fetchMyProgress() {
  const supabase = createClient()
  const { data: { session } } = await supabase.auth.getSession()

  const res = await fetch('/api/progress', {
    headers: {
      Authorization: `Bearer ${session?.access_token}`,
      'Content-Type': 'application/json',
    },
  })

  return res.json()
}

API Key Auth (Server-to-Server)

// Route Handler
export async function POST(req: NextRequest) {
  const apiKey = req.headers.get('X-API-Key')

  if (apiKey !== process.env.INTERNAL_API_KEY) {
    return NextResponse.json({ error: 'Forbidden' }, { status: 403 })
  }

  // process request...
}

// Calling from another service
await fetch('/api/internal/sync', {
  method: 'POST',
  headers: {
    'X-API-Key': process.env.INTERNAL_API_KEY,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(payload),
})
0%