// Expert knowledge on CLI testing with auth bypass, automated endpoint testing, and the 3 bypass methods (headers, environment, test headers). Use this skill when user asks about "test endpoint", "cli testing", "auth bypass", "curl", "automated testing", "local development", or "testing without clerk".
| name | test-auth-wrapper |
| description | Expert knowledge on CLI testing with auth bypass, automated endpoint testing, and the 3 bypass methods (headers, environment, test headers). Use this skill when user asks about "test endpoint", "cli testing", "auth bypass", "curl", "automated testing", "local development", or "testing without clerk". |
| allowed-tools | Read, Bash, Grep |
You are an expert in testing API endpoints locally without full Clerk authentication. This skill provides knowledge about the 3 auth bypass methods and CLI testing patterns.
This skill activates when users:
Bypass Resolution (from /lib/auth/get-auth-or-test.ts):
Use Case: Automated tests, CI/CD
Headers:
x-test-user-id: User ID to impersonatex-test-email: Email (optional)Example:
curl http://localhost:3000/api/campaigns \
-H "x-test-user-id: user_2abc123xyz" \
-H "x-test-email: test@example.com"
Implementation:
// In /lib/auth/get-auth-or-test.ts
const payload = verifyTestAuthHeaders(headerStore);
if (payload?.userId) {
return {
userId: payload.userId,
sessionId: `test_${payload.userId}`,
sessionClaims: payload.email ? { email: payload.email } : undefined,
};
}
Advantages:
Disadvantages:
Use Case: Manual CLI testing, Postman
Headers:
x-dev-auth: dev-bypass (token must match AUTH_BYPASS_TOKEN)x-dev-user-id: User ID (optional, falls back to AUTH_BYPASS_USER_ID)x-dev-email: Email (optional, falls back to AUTH_BYPASS_EMAIL)Environment Variables:
# .env.local
AUTH_BYPASS_TOKEN=dev-bypass # Default if not set
AUTH_BYPASS_HEADER=x-dev-auth # Default if not set
AUTH_BYPASS_USER_ID=user_2abc123xyz # Fallback user
AUTH_BYPASS_EMAIL=dev@example.com # Fallback email
Example:
curl http://localhost:3000/api/campaigns \
-H "x-dev-auth: dev-bypass"
# Uses AUTH_BYPASS_USER_ID from .env.local
curl http://localhost:3000/api/campaigns \
-H "x-dev-auth: dev-bypass" \
-H "x-dev-user-id: user_different123"
# Overrides with specific user
Implementation:
const defaultBypassToken = process.env.AUTH_BYPASS_TOKEN || 'dev-bypass';
const bypassHeaderName = process.env.AUTH_BYPASS_HEADER?.toLowerCase() || 'x-dev-auth';
if (
process.env.NODE_ENV !== 'production' &&
headerStore.get(bypassHeaderName) === defaultBypassToken
) {
const userIdFromHeader = headerStore.get('x-dev-user-id') || process.env.AUTH_BYPASS_USER_ID;
return {
userId: userIdFromHeader,
sessionId: 'bypass',
sessionClaims: { /* ... */ }
};
}
Advantages:
Disadvantages:
Use Case: Long dev sessions, scripts
Environment Variables:
# .env.local
ENABLE_AUTH_BYPASS=true
AUTH_BYPASS_USER_ID=user_2abc123xyz
AUTH_BYPASS_EMAIL=dev@example.com # Optional
Example:
# No headers needed!
curl http://localhost:3000/api/campaigns
curl -X POST http://localhost:3000/api/campaigns \
-H "Content-Type: application/json" \
-d '{"name":"Test","searchType":"instagram-reels"}'
Implementation:
const bypassEnabled = process.env.ENABLE_AUTH_BYPASS === 'true';
const bypassUserId = process.env.AUTH_BYPASS_USER_ID;
if (bypassEnabled && bypassUserId && process.env.NODE_ENV !== 'production') {
return {
userId: bypassUserId,
sessionId: 'bypass',
sessionClaims: { /* ... */ }
};
}
Advantages:
Disadvantages:
# Quick test with dev bypass
curl http://localhost:3000/api/billing/status \
-H "x-dev-auth: dev-bypass"
# Test specific user
curl http://localhost:3000/api/billing/status \
-H "x-test-user-id: user_2abc123xyz"
# POST with JSON body
curl -X POST http://localhost:3000/api/campaigns \
-H "x-dev-auth: dev-bypass" \
-H "Content-Type: application/json" \
-d '{"name":"Test Campaign","searchType":"instagram-reels","keywords":["fitness"]}'
# DELETE endpoint
curl -X DELETE http://localhost:3000/api/campaigns/xxx-xxx-xxx \
-H "x-dev-auth: dev-bypass"
// scripts/test-endpoint.js
require('dotenv').config({ path: '.env.local' });
async function testEndpoint() {
const response = await fetch('http://localhost:3000/api/campaigns', {
headers: {
'x-dev-auth': 'dev-bypass',
'x-dev-user-id': 'user_2abc123xyz'
}
});
const data = await response.json();
console.log('Response:', data);
}
testEndpoint();
Run: node scripts/test-endpoint.js
// tests/api/campaigns.test.ts
import { describe, it, expect } from 'vitest';
const BASE_URL = 'http://localhost:3000';
const TEST_USER_ID = 'user_test123';
describe('Campaigns API', () => {
it('should create campaign', async () => {
const response = await fetch(`${BASE_URL}/api/campaigns`, {
method: 'POST',
headers: {
'x-test-user-id': TEST_USER_ID,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Test Campaign',
searchType: 'instagram-reels',
keywords: ['fitness']
})
});
expect(response.status).toBe(201);
const data = await response.json();
expect(data.success).toBe(true);
expect(data.data.name).toBe('Test Campaign');
});
it('should enforce plan limits', async () => {
// Create user with limit of 3 campaigns
// ... create 3 campaigns ...
// 4th should fail
const response = await fetch(`${BASE_URL}/api/campaigns`, {
method: 'POST',
headers: {
'x-test-user-id': TEST_USER_ID,
'x-plan-bypass': 'none', // Don't bypass plan limits
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Campaign 4',
searchType: 'instagram-reels'
})
});
expect(response.status).toBe(403);
const data = await response.json();
expect(data.error).toContain('limit');
});
});
# Bypass campaign limits
curl -X POST http://localhost:3000/api/campaigns \
-H "x-dev-auth: dev-bypass" \
-H "x-plan-bypass: campaigns" \
-H "Content-Type: application/json" \
-d '{"name":"Test","searchType":"instagram-reels"}'
# Bypass all limits
curl -X POST http://localhost:3000/api/campaigns \
-H "x-dev-auth: dev-bypass" \
-H "x-plan-bypass: all"
# Via environment (for scripts)
# .env.local
PLAN_VALIDATION_BYPASS=all # or "campaigns,creators"
// BAD: Hardcoded test user
export async function POST(req: Request) {
const userId = 'user_2abc123xyz'; // WRONG!
// ...
}
Why it's bad: Breaks production, not flexible
Do this instead:
// GOOD: Use auth resolver
const auth = await getAuthOrTest();
if (!auth?.userId) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// BAD: No environment check
if (process.env.ENABLE_AUTH_BYPASS === 'true') {
return { userId: process.env.AUTH_BYPASS_USER_ID };
}
Why it's bad: Massive security hole in production
Do this instead:
// GOOD: Environment check
if (
process.env.ENABLE_AUTH_BYPASS === 'true' &&
process.env.NODE_ENV !== 'production'
) {
return { userId: process.env.AUTH_BYPASS_USER_ID };
}
# BAD: Using bypass to modify production data
curl https://production.com/api/campaigns/delete-all \
-H "x-dev-auth: dev-bypass"
# This should NEVER work in production!
Why it's bad: Bypasses should only work locally
Symptoms:
Diagnosis:
AUTH_BYPASS_TOKENSolution:
# 1. Verify environment
echo $NODE_ENV # Should be "development" or empty
# 2. Check .env.local
cat .env.local | grep AUTH_BYPASS
# 3. Test with exact headers
curl http://localhost:3000/api/debug/whoami \
-H "x-dev-auth: dev-bypass" \
-H "x-dev-user-id: user_2abc123xyz" \
-v # Verbose mode to see headers
# 4. Restart dev server (to reload .env.local)
Symptoms:
Solution: Use test headers (Method 1) instead of environment bypass:
# User 1
curl http://localhost:3000/api/campaigns \
-H "x-test-user-id: user_1"
# User 2
curl http://localhost:3000/api/campaigns \
-H "x-test-user-id: user_2"
/lib/auth/get-auth-or-test.ts - Auth resolver with bypass logic/lib/auth/testable-auth.ts - Test header verification/app/api/debug/whoami/route.ts - Debug endpoint for testing auth/app/api/test/auth-echo/route.ts - Echo auth contextHeaders:
# Test headers (highest priority)
x-test-user-id: user_xxx
x-test-email: test@example.com
# Dev bypass headers
x-dev-auth: dev-bypass
x-dev-user-id: user_xxx # Optional override
x-dev-email: dev@example.com # Optional
# Plan bypass (for testing without limits)
x-plan-bypass: all # or "campaigns" or "creators"
Environment:
# Auth bypass
ENABLE_AUTH_BYPASS=true
AUTH_BYPASS_USER_ID=user_xxx
AUTH_BYPASS_EMAIL=dev@example.com
AUTH_BYPASS_TOKEN=dev-bypass
AUTH_BYPASS_HEADER=x-dev-auth
# Plan bypass
PLAN_VALIDATION_BYPASS=all # or "campaigns,creators"
Testing Commands:
# Simple GET
curl http://localhost:3000/api/endpoint \
-H "x-dev-auth: dev-bypass"
# POST with JSON
curl -X POST http://localhost:3000/api/endpoint \
-H "x-dev-auth: dev-bypass" \
-H "Content-Type: application/json" \
-d '{"key":"value"}'
# Different user
curl http://localhost:3000/api/endpoint \
-H "x-test-user-id: user_different"
# With plan bypass
curl http://localhost:3000/api/endpoint \
-H "x-dev-auth: dev-bypass" \
-H "x-plan-bypass: all"