ComponentForge uses Auth.js v5 (NextAuth) for authentication with JWT tokens.
- JWT-based authentication with secure httpOnly cookies
- Session management with Redis backend
- Multiple auth providers supported
- Automatic token refresh for seamless UX
POST /api/auth/signin
Content-Type: application/json
{
"email": "user@example.com",
"password": "secure_password"
}Response:
{
"status": "success",
"data": {
"user": {
"id": "user_123",
"email": "user@example.com",
"name": "John Doe"
},
"session": {
"expires": "2025-10-15T14:00:00Z"
}
}
}- JWT token stored in secure httpOnly cookie
- Not accessible via JavaScript (XSS protection)
- Automatic inclusion in subsequent requests
# Token automatically sent via cookie
curl http://localhost:8000/api/v1/generate/screenshot \
-X POST \
-F "file=@screenshot.png"Tokens are automatically refreshed before expiration. No manual refresh needed.
POST /api/auth/signout# backend/.env
AUTH_SECRET=your-32-char-secret-key-here
DATABASE_URL=postgresql+asyncpg://user:pass@localhost:5432/db
# Generate secret
openssl rand -base64 32# app/.env.local
AUTH_SECRET=same-as-backend-secret
NEXTAUTH_URL=http://localhost:3000
API_URL=http://localhost:8000- Backend: Redis with 7-day TTL
- Cookie: Secure, httpOnly, sameSite=lax
- Refresh: Automatic before expiration
{
"user": {
"id": "user_123",
"email": "user@example.com",
"name": "John Doe",
"role": "user"
},
"expires": "2025-10-15T14:00:00Z",
"sessionToken": "..."
}- ✅ Secure httpOnly cookies - No JavaScript access
- ✅ CSRF protection - Built-in token validation
- ✅ Short expiration - 7-day max lifetime
- ✅ Automatic refresh - Seamless token rotation
- ✅ bcrypt hashing - Industry-standard hashing
- ✅ Salt rounds: 12 - Strong against brute force
- ✅ Never logged - Passwords never in logs
- ✅ TLS encryption - HTTPS in production
- ✅ Rate limiting - Prevents abuse
- ✅ CORS configuration - Allowed origins only
- ✅ Input validation - Pydantic models
- ✅ SQL injection prevention - Parameterized queries
from src.core.auth import get_current_user
@router.post("/generate/screenshot")
async def generate_from_screenshot(
file: UploadFile,
current_user: User = Depends(get_current_user)
):
# Only authenticated users reach here
...import { auth } from "@/auth"
export default auth((req) => {
if (!req.auth && req.nextUrl.pathname !== "/signin") {
return Response.redirect("/signin")
}
}){
"status": "error",
"error": {
"code": "UNAUTHORIZED",
"message": "Authentication required"
}
}{
"status": "error",
"error": {
"code": "INVALID_TOKEN",
"message": "Token has expired or is invalid"
}
}{
"status": "error",
"error": {
"code": "FORBIDDEN",
"message": "Insufficient permissions"
}
}# Force HTTPS in production
NEXTAUTH_URL=https://app.componentforge.comcookies: {
sessionToken: {
name: '__Secure-next-auth.session-token',
options: {
httpOnly: true,
sameSite: 'lax',
path: '/',
secure: true // HTTPS only
}
}
}Redis automatically expires sessions after TTL. Manual cleanup not needed.
- Check AUTH_SECRET matches between frontend and backend
- Verify Redis is running:
docker-compose ps - Clear cookies and re-login
- Check backend logs:
docker-compose logs backend
- Add frontend URL to ALLOWED_ORIGINS in backend config
- Verify credentials: 'include' in fetch requests
- Check CORS middleware configuration