ADR-004: Backend-for-Frontend API Proxy
Status
Accepted
Context
The application needs to communicate with backend APIs (PublicAPI) while:
- Keeping tokens secure: Access tokens must not be exposed to JavaScript
- Avoiding CORS issues: Same-origin requests simplify configuration
- Centralizing auth logic: Single place for token injection
- Supporting anonymous users: Fallback to client credentials
Options considered:
- Direct API calls: Simple but exposes tokens, CORS complexity
- API Gateway: Additional infrastructure, latency
- BFF Proxy: Server-side token injection, same-origin requests
Decision
We will implement a Backend-for-Frontend (BFF) proxy pattern:
- Catch-all route at
/api/eai/[[...rest]]/route.ts - Token injection: Add Authorization header server-side
- Credential forwarding:
credentials: 'include'sends session cookies - Anonymous fallback: Client credentials when no user session
// src/app/api/eai/[[...rest]]/route.ts
export async function GET(request: Request, { params }: Props) {
const path = params.rest?.join('/') || '';
const token = await getAccessToken(); // User or client credentials
return fetch(`${process.env.BASE_URL_PUBLIC_API}/${path}`, {
headers: {
Authorization: `Bearer ${token}`,
...forwardedHeaders(request),
},
});
}
Token Priority
The proxy tries token sources in order:
- User session token: From Auth.js session (logged-in user)
- Client credentials token: Machine-to-machine token (anonymous)
Client Usage
// Client code - simple, no token handling
const response = await fetch('/api/eai/v3/projects', {
credentials: 'include', // Send session cookie
});
Consequences
Positive
- Security: Tokens never in browser JavaScript
- Simplicity: Client code doesn't manage tokens
- CORS-free: Same-origin requests
- Centralized logging: All API calls pass through proxy
Negative
- Latency: Extra hop through Next.js server
- Deployment coupling: API routes must be deployed with frontend
- Streaming complexity: SSE/WebSocket require special handling
Neutral
- Error handling: Proxy can normalize error responses
- Rate limiting: Can be applied at proxy layer
Related ADRs
- ADR-002: Authentication - Token acquisition