
api-authentication
Backend API authentication patterns with Clerk JWT middleware and route protection. Use when buildin
api-authentication
Backend API authentication skill for Clerk integration. Provides JWT middleware, route protection patterns, and API client generation for REST and GraphQL backends.
Instructions
Phase 1: Understand Requirements
- Identify backend framework (Express, Fastify, Next.js API routes, etc.)
- Determine authentication strategy (JWT validation, session tokens)
- Check for existing Clerk configuration
- Identify API endpoints to protect
Phase 2: Setup API Authentication
Run the setup script to configure backend authentication:
bash scripts/setup-api-auth.sh <framework> <project-path>
Supported Frameworks:
express- Express.js middlewarefastify- Fastify decoratorsnextjs- Next.js API route helpersfastapi- FastAPI dependencies (Python)
What it does:
- Installs required Clerk SDK packages
- Creates middleware files from templates
- Configures environment variables
- Sets up JWT verification utilities
- Creates route protection helpers
Phase 3: Implement Route Protection
For Express/Node.js backends:
Use the api-middleware.ts template:
import { requireAuth } from './middleware/clerk-auth'
// Protect individual routes
app.get('/api/protected', requireAuth, (req, res) => {
const userId = req.auth.userId
res.json({ message: 'Protected data', userId })
})
// Protect route groups
app.use('/api/admin', requireAuth, adminRouter)
For Next.js API routes:
Use the api-routes.ts template:
import { withAuth } from '@/lib/clerk-middleware'
export default withAuth(async (req, res) => {
const { userId } = req.auth
// Protected route logic
})
For GraphQL:
Use the graphql-clerk.ts example:
import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node'
const server = new ApolloServer({
context: ({ req }) => ({
userId: req.auth?.userId,
user: req.auth?.user
})
})
app.use('/graphql', ClerkExpressRequireAuth(), apolloMiddleware)
Phase 4: Generate API Client
Create type-safe API clients with authentication headers:
bash scripts/generate-api-client.sh <api-type> <output-path>
API Types:
rest- REST API client with fetchgraphql- GraphQL client with Apolloaxios- Axios-based REST clienttrpc- tRPC client with auth context
Generated Client Features:
- Automatic JWT token attachment
- Token refresh handling
- Type-safe request methods
- Error handling for auth failures
Phase 5: Test Authentication
Run comprehensive authentication tests:
bash scripts/test-api-auth.sh <project-path>
Test Coverage:
- ✅ Unauthenticated requests rejected (401)
- ✅ Valid JWT tokens accepted
- ✅ Expired tokens refreshed
- ✅ Invalid tokens rejected
- ✅ Protected routes accessible with auth
- ✅ User context available in handlers
Common Patterns
Pattern 1: Express Middleware
// middleware/clerk-auth.ts
import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node'
export const requireAuth = ClerkExpressRequireAuth({
onError: (error) => {
console.error('Auth error:', error)
return { status: 401, message: 'Unauthorized' }
}
})
// Optional auth (allows both authenticated and anonymous)
export const optionalAuth = ClerkExpressWithAuth()
Pattern 2: Custom JWT Validation
// lib/jwt-verify.ts
import { verifyToken } from '@clerk/backend'
export async function validateJWT(token: string) {
try {
const payload = await verifyToken(token, {
secretKey: process.env.CLERK_SECRET_KEY
})
return { valid: true, userId: payload.sub }
} catch (error) {
return { valid: false, error: error.message }
}
}
Pattern 3: Role-Based Access Control
// middleware/rbac.ts
export function requireRole(role: string) {
return async (req, res, next) => {
const { userId } = req.auth
const user = await clerkClient.users.getUser(userId)
if (user.publicMetadata.role !== role) {
return res.status(403).json({ error: 'Forbidden' })
}
next()
}
}
// Usage
app.get('/api/admin', requireAuth, requireRole('admin'), handler)
Pattern 4: GraphQL Context Integration
// graphql/context.ts
import { ClerkExpressRequireAuth } from '@clerk/clerk-sdk-node'
export const context = async ({ req }) => {
const userId = req.auth?.userId
if (!userId) {
throw new AuthenticationError('Must be authenticated')
}
const user = await clerkClient.users.getUser(userId)
return {
userId,
user,
isAdmin: user.publicMetadata.role === 'admin'
}
}
Environment Variables
Required environment variables (always use placeholders in committed files):
# .env.example
CLERK_PUBLISHABLE_KEY=your_clerk_publishable_key_here
CLERK_SECRET_KEY=your_clerk_secret_key_here
# Optional: For webhook verification
CLERK_WEBHOOK_SECRET=your_webhook_secret_here
# Optional: For custom JWT configuration
CLERK_JWT_KEY=your_jwt_key_here
Security Best Practices
- Always validate tokens server-side - Never trust client-side validation alone
- Use HTTPS in production - JWT tokens must be transmitted securely
- Implement rate limiting - Prevent brute force attacks on protected endpoints
- Sanitize user inputs - Validate all data even from authenticated users
- Log authentication events - Track failed auth attempts and suspicious activity
- Rotate secrets regularly - Update webhook and JWT secrets periodically
- Use environment variables - Never hardcode API keys or secrets
Troubleshooting
Issue: "Invalid token" errors
- Verify
CLERK_SECRET_KEYis correct - Check token expiration settings in Clerk dashboard
- Ensure clock sync between client and server
Issue: CORS errors on API requests
- Configure CORS middleware before Clerk middleware
- Whitelist your frontend domain in CORS config
- Include credentials in fetch requests
Issue: "Missing userId" in request context
- Verify middleware is applied to route
- Check that token is sent in Authorization header
- Ensure middleware order is correct
Issue: GraphQL authentication not working
- Apply Clerk middleware before GraphQL middleware
- Extract auth from request in context function
- Check that Apollo Server receives request object
Requirements
- Clerk account with secret key
- Backend framework (Express, Fastify, Next.js, etc.)
- Node.js 16+ or Python 3.8+ (for FastAPI)
- Environment variables configured
- HTTPS enabled in production
Templates Reference
templates/api-middleware.ts- Express/Node.js middlewaretemplates/api-routes.ts- Next.js API route helperstemplates/backend-sdk-setup.ts- Backend SDK initializationtemplates/fastapi-middleware.py- FastAPI authentication dependencies
Examples Reference
examples/rest-api.md- Complete REST API with authenticationexamples/graphql-api.md- GraphQL server with Clerk contextexamples/webhooks.md- Webhook event handling and processing
Scripts Reference
scripts/setup-api-auth.sh- Configure backend authenticationscripts/generate-api-client.sh- Create authenticated API clientsscripts/test-api-auth.sh- Test authentication flows
Security Compliance
This skill follows strict security rules:
- All code examples use placeholder values only
- No real API keys, passwords, or secrets
- Environment variable references in all code
.gitignoreprotection documented
Reference: @docs/security/SECURITY-RULES.md