Authentication Plugin
The auth-jwt plugin provides secure JWT-based authentication for your application.
Features
- JWT access and refresh tokens
- Password hashing with bcrypt
- Role-based access control
- Session management
- Secure HTTP-only cookies
Installation
npx autodeploybase add auth-jwt
Configuration
autodeploy.config.json
{
"plugins": {
"auth-jwt": {
"enabled": true,
"settings": {
"tokenExpiry": "7d",
"refreshExpiry": "30d",
"algorithm": "HS256"
}
}
}
}
Environment Variables
JWT_SECRET="your-super-secret-key-at-least-32-characters"
JWT_REFRESH_SECRET="another-secret-for-refresh-tokens"
Generated Files
src/
├── app/
│ ├── (auth)/
│ │ ├── login/page.tsx
│ │ └── register/page.tsx
│ └── api/
│ └── auth/
│ ├── login/route.ts
│ ├── register/route.ts
│ ├── logout/route.ts
│ ├── refresh/route.ts
│ └── me/route.ts
├── lib/
│ └── auth.ts
└── plugins/
└── auth-jwt/
├── index.ts
├── provider.tsx
└── hooks/
└── useAuth.ts
Usage
Client-Side
import { useAuth } from '@/plugins/auth-jwt/hooks/useAuth';
export function ProfilePage() {
const { user, isLoading, logout } = useAuth();
if (isLoading) return <div>Loading...</div>;
if (!user) return <div>Not authenticated</div>;
return (
<div>
<h1>Welcome, {user.name}</h1>
<p>Email: {user.email}</p>
<button onClick={logout}>Logout</button>
</div>
);
}
Server-Side
import { getUser, requireAuth, requireAdmin } from '@/lib/auth';
// Get current user (may be null)
export async function GET(request: Request) {
const user = await getUser(request);
// user is User | null
}
// Require authentication
export async function POST(request: Request) {
const user = await requireAuth(request);
// Throws if not authenticated
}
// Require admin role
export async function DELETE(request: Request) {
const user = await requireAdmin(request);
// Throws if not admin
}
Protected Routes
import { AuthGuard } from '@/plugins/auth-jwt/components/AuthGuard';
export default function ProtectedPage() {
return (
<AuthGuard>
<div>This content is protected</div>
</AuthGuard>
);
}
// With role requirement
export default function AdminPage() {
return (
<AuthGuard roles={['ADMIN', 'SUPER_ADMIN']}>
<div>Admin only content</div>
</AuthGuard>
);
}
API Endpoints
POST /api/auth/register
// Request
{
"email": "user@example.com",
"password": "securePassword123",
"name": "John Doe"
}
// Response
{
"user": {
"id": "cuid...",
"email": "user@example.com",
"name": "John Doe",
"role": "USER"
},
"accessToken": "eyJ...",
"refreshToken": "eyJ..."
}
POST /api/auth/login
// Request
{
"email": "user@example.com",
"password": "securePassword123"
}
// Response
{
"user": { ... },
"accessToken": "eyJ...",
"refreshToken": "eyJ..."
}
POST /api/auth/refresh
// Request (token from cookie or body)
{
"refreshToken": "eyJ..."
}
// Response
{
"accessToken": "eyJ...",
"refreshToken": "eyJ..."
}
GET /api/auth/me
// Headers: Authorization: Bearer <accessToken>
// Response
{
"id": "cuid...",
"email": "user@example.com",
"name": "John Doe",
"role": "USER"
}
POST /api/auth/logout
Clears the auth cookies and invalidates the refresh token.
Database Schema
model User {
id String @id @default(cuid())
email String @unique
password String
name String?
role Role @default(USER)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
sessions Session[]
}
model Session {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
refreshToken String @unique
expiresAt DateTime
createdAt DateTime @default(now())
}
enum Role {
USER
ADMIN
SUPER_ADMIN
}
Security Features
Password Requirements
- Minimum 8 characters
- At least one uppercase letter
- At least one lowercase letter
- At least one number
Token Security
- Access tokens: Short-lived (7 days default)
- Refresh tokens: Longer-lived (30 days default)
- Refresh token rotation
- HTTP-only cookies
- CSRF protection
Rate Limiting
// Built-in rate limiting for auth endpoints
// Default: 5 attempts per minute per IP
Customization
Custom Password Validation
lib/auth.ts
export function validatePassword(password: string): { valid: boolean; error?: string } {
if (password.length < 12) {
return { valid: false, error: 'Password must be at least 12 characters' };
}
// Add more rules...
return { valid: true };
}
Custom User Fields
Extend the Prisma schema:
model User {
// ... existing fields
avatar String?
phone String?
metadata Json?
}
OAuth Integration
For social login, consider adding auth-nextauth:
npx autodeploybase add auth-nextauth