@gittielabs/nextjs-fastapi-auth
v0.1.0
Published
Next.js authentication utilities for FastAPI backend
Downloads
5
Maintainers
Readme
@gittielabs/nextjs-fastapi-auth
Authentication and authorization library for Next.js 15+ applications with Supabase backend integration.
Installation
npm install @gittielabs/nextjs-fastapi-auth
# or
yarn add @gittielabs/nextjs-fastapi-auth
# or
pnpm add @gittielabs/nextjs-fastapi-authFeatures
- 🔐 JWT Token Management - Extract and validate Supabase JWT tokens
- 🛡️ Admin Authentication - Server-side admin role verification
- 🔄 Auth Middleware - Automatic authentication and subdomain handling
- 🌐 Multi-Tenancy - Organization context via subdomains
- 📡 WebSocket Support - Authenticated WebSocket connections
- 🚀 Next.js 15 Compatible - Full support for async cookies and headers
Quick Start
1. Environment Setup
Create a .env.local file:
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key2. Middleware Setup
Create or update middleware.ts:
import { authMiddleware } from '@gittielabs/nextjs-fastapi-auth/middleware'
export default authMiddleware
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico|public/).*)',
],
}3. Protected API Routes
Use admin authentication in API routes:
// app/api/admin/users/route.ts
import { validateAdminAuth } from '@gittielabs/nextjs-fastapi-auth/server'
import { NextRequest, NextResponse } from 'next/server'
export async function GET(request: NextRequest) {
const auth = validateAdminAuth(request)
if (auth.error) {
return auth.error
}
// User is authenticated as admin
return NextResponse.json({
user: auth.user,
message: 'Admin access granted'
})
}4. Client-Side Authentication
Use authenticated fetch for API calls:
'use client'
import { authenticatedFetch } from '@gittielabs/nextjs-fastapi-auth/client'
export default function MyComponent() {
const fetchData = async () => {
const response = await authenticatedFetch('/api/data')
const data = await response.json()
console.log(data)
}
return <button onClick={fetchData}>Fetch Data</button>
}Core Components
JWT Utilities
Extract and decode JWT tokens:
import {
extractJwtFromRequest,
extractJwtPayload,
extractSubdomainFromJwt
} from '@gittielabs/nextjs-fastapi-auth/jwt'
// Extract JWT from NextRequest
const token = extractJwtFromRequest(request)
// Decode JWT payload
const payload = extractJwtPayload(token)
if (payload) {
console.log('User ID:', payload.sub)
console.log('Email:', payload.email)
}
// Extract organization subdomain
const subdomain = extractSubdomainFromJwt(token)Admin Authentication
Validate admin access in API routes:
import { validateAdminAuth } from '@gittielabs/nextjs-fastapi-auth/server'
export async function POST(request: NextRequest) {
const auth = validateAdminAuth(request)
if (auth.error) {
return auth.error // Returns 401 or 403 response
}
// Access authenticated user data
const { user } = auth
console.log('Admin user:', user.email)
console.log('Organization:', user.organization_subdomain)
// Proceed with admin operation...
}Middleware
The auth middleware handles:
- Authentication verification
- Subdomain-based routing
- WWW redirect
- Protected route enforcement
import { authMiddleware } from '@gittielabs/nextjs-fastapi-auth/middleware'
// Use as-is or customize configuration
export default authMiddleware
// Or create custom middleware
import { NextRequest, NextResponse } from 'next/server'
import { extractJwtFromRequest } from '@gittielabs/nextjs-fastapi-auth/jwt'
export async function middleware(request: NextRequest) {
const token = extractJwtFromRequest(request)
if (!token && request.nextUrl.pathname.startsWith('/protected')) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}Authenticated Fetch
Client-side fetch with automatic authentication:
import { authenticatedFetch } from '@gittielabs/nextjs-fastapi-auth/client'
// Automatically includes Authorization header
const response = await authenticatedFetch('/api/data', {
method: 'POST',
body: JSON.stringify({ key: 'value' }),
})
const data = await response.json()WebSocket Support
Create authenticated WebSocket connections:
import { createAuthenticatedWebSocket } from '@gittielabs/nextjs-fastapi-auth/client'
const ws = await createAuthenticatedWebSocket('wss://api.example.com/ws')
ws.onmessage = (event) => {
console.log('Message:', event.data)
}
ws.send(JSON.stringify({ action: 'subscribe', channel: 'updates' }))User Roles and Permissions
The library supports role-based access control:
interface JwtPayload {
sub: string // User ID
email: string // User email
user_metadata: {
role?: string // User role
is_super_admin?: boolean // Super admin flag
organization_subdomain?: string
}
// ... other Supabase JWT fields
}Roles are used by the admin authentication to control access:
- Super admins have access to all organizations
- Organization admins can access their organization's admin routes
- Regular users are blocked from admin routes
API Reference
JWT Functions
extractJwtFromRequest(request: NextRequest): string | null
Extract JWT token from request headers or cookies.
extractJwtPayload(token: string): JwtPayload | null
Decode and parse JWT payload.
extractSubdomainFromJwt(token: string): string | null
Extract organization subdomain from JWT metadata.
extractSubdomainFromRequest(request: NextRequest): string | null
Extract subdomain from request hostname.
Server Functions
validateAdminAuth(request: NextRequest): { user: JwtPayload } | { error: NextResponse }
Validate that the request is from an authenticated admin user.
Returns either:
{ user: JwtPayload }- User is authenticated as admin{ error: NextResponse }- Authentication failed (401 or 403)
Middleware
authMiddleware(request: NextRequest): Promise<NextResponse>
Complete authentication middleware with:
- WWW redirect
- Subdomain handling
- Authentication verification
- Protected route enforcement
Client Functions
authenticatedFetch(url: string, options?: RequestInit): Promise<Response>
Fetch with automatic JWT authentication.
createAuthenticatedWebSocket(url: string): Promise<WebSocket>
Create WebSocket connection with JWT authentication.
TypeScript Support
This library is written in TypeScript and includes full type definitions:
import type {
JwtPayload,
AdminAuthResult,
AuthenticatedUser
} from '@gittielabs/nextjs-fastapi-auth'Development
Running Tests
npm test
# With coverage
npm test -- --coverage
# Watch mode
npm test -- --watchBuilding
npm run buildLinting
npm run lintBest Practices
1. Server-Side Authentication
Always validate authentication on the server side:
// ✅ Good - Server-side validation
export async function GET(request: NextRequest) {
const auth = validateAdminAuth(request)
if (auth.error) return auth.error
// ... secure operation
}
// ❌ Bad - Client-side only
'use client'
export default function AdminPanel() {
// Client-side checks can be bypassed
}2. Environment Variables
Keep sensitive keys secure:
// ✅ Good - Use environment variables
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL
// ❌ Bad - Hardcoded values
const supabaseUrl = 'https://myproject.supabase.co'3. Error Handling
Handle authentication errors gracefully:
const auth = validateAdminAuth(request)
if (auth.error) {
// Log error details server-side
console.error('Auth failed:', auth.error)
// Return user-friendly error
return auth.error
}4. Multi-Tenancy
Use subdomains for organization isolation:
// Extract subdomain for data filtering
const subdomain = extractSubdomainFromRequest(request)
// Filter queries by organization
const data = await db.query({
where: { organization_subdomain: subdomain }
})Troubleshooting
"No JWT token found"
Ensure the client is sending the Authorization header:
// Check if token exists in cookies
const cookies = await import('next/headers')
const cookieStore = await cookies.cookies()
const token = cookieStore.get('sb-access-token')"Invalid JWT token"
Verify your Supabase configuration:
- Check
NEXT_PUBLIC_SUPABASE_URLis correct - Ensure
SUPABASE_SERVICE_ROLE_KEYis the service role key (not anon key) - Confirm the JWT hasn't expired
"Subdomain not found"
Ensure your middleware is properly configured:
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico).*)',
],
}Migration Guide
From Previous Versions
If migrating from an older version:
- Update to Next.js 15+
- Make cookies and headers async:
// Before
const cookieStore = cookies()
// After (Next.js 15+)
const cookieStore = await cookies()- Update middleware exports:
// Before
export { middleware } from '@gittielabs/nextjs-fastapi-auth'
// After
import { authMiddleware } from '@gittielabs/nextjs-fastapi-auth/middleware'
export default authMiddlewareContributing
Contributions are welcome! Please see the main repository for guidelines.
License
MIT © GittieLabs
Support
For issues and questions:
- GitHub Issues: Create an issue
- Documentation: Full docs
