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),
})Reading progress
0% read
In this module
JWT
Bearer token
API key
Token expiry
0%