How the Edge Middleware in proxy.ts Validates Supabase Auth and Injects X‑Request‑Id
The proxy.ts edge middleware verifies Supabase JWTs via auth.getUser(), rejects unauthenticated requests with a 401 response, and injects a crypto.randomUUID() as the X‑Request‑Id header for distributed tracing.
The DeskcommCRM repository implements a secure entrance point for all API traffic using Next.js edge middleware. Located in the root proxy.ts file, this middleware intercepts every incoming request to validate Supabase authentication tokens and ensure every request carries a unique trace identifier before reaching application routes.
Supabase Authentication Validation at the Edge
The primary security function of the middleware is to verify that every request presents a valid Supabase session. This prevents unauthorized access to protected API endpoints and server actions.
Token Extraction from Cookies
The middleware extracts the authentication token from the sb:token cookie, falling back to the legacy supabase-auth-token cookie name for backward compatibility. These cookies contain the JWT issued by Supabase Auth upon user login.
JWT Verification with auth.getUser()
Rather than trusting the cookie value directly, the middleware initializes a server-side Supabase client using createSupabaseClient() from lib/supabase/server.ts. It then calls auth.getUser() to validate the JWT signature, expiration, and audience with Supabase's servers. This approach ensures that revoked tokens or malformed payloads are rejected immediately at the edge.
Returning 401 for Invalid Sessions
If the token is missing, malformed, or auth.getUser() returns an error, the middleware responds with a 401 Unauthorized status. According to the DeskcommCRM source, the middleware utilizes response helpers from lib/api/wrappers.ts to standardize error formatting before terminating the request.
Distributed Tracing with X‑Request‑Id Injection
Beyond authentication, the middleware ensures observability by guaranteeing every request carries a unique identifier suitable for distributed tracing across services.
Generating UUIDs with crypto.randomUUID()
When a request arrives without an X‑Request‑Id header, the middleware generates a new UUID v4 using the Web Crypto API's crypto.randomUUID() method. This identifier is attached to the request headers as X‑Request‑Id, ensuring that logs, database queries, and external API calls can be correlated to the original request.
Header Propagation to Downstream Services
The injected X‑Request‑Id value propagates through the Next.js routing pipeline. Downstream components, including the structured logger in lib/logger.ts, capture this identifier to create coherent trace chains across the application stack.
Implementation Structure in proxy.ts
The middleware follows a sequential pattern: extract cookies, validate with Supabase, check/generate request ID, then forward. The implementation returns NextResponse.next() to continue processing when both checks pass.
// proxy.ts - Implementation pattern in DeskcommCRM
import { NextResponse } from 'next/server'
import { createSupabaseClient } from './lib/supabase/server'
export async function middleware(request: NextRequest) {
// Extract token from cookies
const token = request.cookies.get('sb:token')?.value ||
request.cookies.get('supabase-auth-token')?.value
// Validate with Supabase
const supabase = createSupabaseClient()
const { data: { user }, error } = await supabase.auth.getUser(token)
if (error || !user) {
return new NextResponse('Unauthorized', { status: 401 })
}
// Inject X-Request-Id
const requestId = request.headers.get('X-Request-Id') || crypto.randomUUID()
const requestHeaders = new Headers(request.headers)
requestHeaders.set('X-Request-Id', requestId)
// Forward with modified headers
return NextResponse.next({
request: {
headers: requestHeaders,
},
})
}
Consuming the Validated Context
Once the middleware completes, application code can safely assume a valid authentication context and access the trace identifier.
Accessing the Supabase User in API Routes
API routes can access the validated user object attached to the request context. The middleware enriches the request with the Supabase user data retrieved during the auth.getUser() call:
// app/api/v1/orders/route.ts
export async function GET(req: Request) {
// User object set by proxy.ts middleware
const user = (req as any).context?.supabaseUser
if (!user) {
return new Response('Unauthorized', { status: 401 })
}
return Response.json({ email: user.email })
}
Retrieving X‑Request‑Id in Server Actions
Server actions can access the injected header using Next.js headers() helper to maintain trace context through asynchronous operations:
import { headers } from 'next/headers'
export const processOrder = async (orderId: string) => {
const requestId = headers().get('X-Request-Id')
if (!requestId) {
throw new Error('Request ID not found')
}
// Pass ID to downstream services or logging
await logOrderAccess(orderId, requestId)
return { success: true, requestId }
}
Summary
- The
proxy.tsedge middleware validates every request against Supabase Auth usingauth.getUser()before allowing access to protected routes. - Authentication tokens are extracted from the
sb:tokenorsupabase-auth-tokencookies and verified server-side to prevent tampering. - Invalid or missing tokens trigger an immediate 401 Unauthorized response, preventing unauthorized access to backend resources.
- The middleware injects a
X‑Request‑Idheader usingcrypto.randomUUID()if one is not present, enabling distributed tracing across the application. - Validated user context and request IDs are propagated downstream to API routes and server actions for secure, traceable request processing.
Frequently Asked Questions
How does proxy.ts handle expired Supabase tokens?
The middleware validates tokens by calling auth.getUser() from the server-side Supabase client. If the JWT has expired or been revoked, Supabase returns an error, and the middleware responds with a 401 status code, forcing the client to re-authenticate.
Can I customize the X‑Request‑Id generation logic?
Yes, the middleware checks for existing X‑Request‑Id headers before generating a new UUID. If your infrastructure already injects this header (via a load balancer or CDN), the middleware preserves that value. To customize generation, modify the crypto.randomUUID() call in proxy.ts to use your preferred ID format.
Which files depend on the X‑Request‑Id set by the middleware?
According to the DeskcommCRM source, the structured logger in lib/logger.ts and API response wrappers in lib/api/wrappers.ts both utilize the X‑Request‑Id header to correlate logs and standardize error responses with trace identifiers.
What happens if the Supabase client fails to initialize in the middleware?
If createSupabaseClient() from lib/supabase/server.ts throws an exception or returns an invalid client, the auth.getUser() call will fail, resulting in a 401 response. This fail-safe ensures that authentication state is never assumed without explicit verification.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →