Claude
Skills
Sign in
Back

authentication-setup

Included with Lifetime
$97 forever

Design and implement authentication and authorization systems. Use when setting up user login, JWT tokens, OAuth, session management, or role-based access control. Handles password security, token management, SSO integration.

Design

What this skill does



# Authentication Setup


## When to use this skill

Lists specific situations where this skill should be triggered:

- **User Login System**: When adding user authentication to a new application
- **API Security**: When adding an authentication layer to a REST or GraphQL API
- **Permission Management**: When role-based access control is needed
- **Authentication Migration**: When migrating an existing auth system to JWT or OAuth
- **SSO Integration**: When integrating social login with Google, GitHub, Microsoft, etc.

## Input Format

The required and optional input information to collect from the user:

### Required Information
- **Authentication Method**: Choose from JWT, Session, or OAuth 2.0
- **Backend Framework**: Express, Django, FastAPI, Spring Boot, etc.
- **Database**: PostgreSQL, MySQL, MongoDB, etc.
- **Security Requirements**: Password policy, token expiry times, etc.

### Optional Information
- **MFA Support**: Whether to enable 2FA/MFA (default: false)
- **Social Login**: OAuth providers (Google, GitHub, etc.)
- **Session Storage**: Redis, in-memory, etc. (if using sessions)
- **Refresh Token**: Whether to use (default: true)

### Input Example

```
Build a user authentication system:
- Auth method: JWT
- Framework: Express.js + TypeScript
- Database: PostgreSQL
- MFA: Google Authenticator support
- Social login: Google, GitHub
- Refresh Token: enabled
```

## Instructions

Specifies the step-by-step task sequence to follow precisely.

### Step 1: Design the Data Model

Design the database schema for users and authentication.

**Tasks**:
- Design the User table (id, email, password_hash, role, created_at, updated_at)
- RefreshToken table (optional)
- OAuthProvider table (if using social login)
- Never store passwords in plaintext (bcrypt/argon2 hashing is mandatory)

**Example** (PostgreSQL):
```sql
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email VARCHAR(255) UNIQUE NOT NULL,
    password_hash VARCHAR(255),  -- NULL if OAuth only
    role VARCHAR(50) DEFAULT 'user',
    is_verified BOOLEAN DEFAULT false,
    mfa_secret VARCHAR(255),
    created_at TIMESTAMP DEFAULT NOW(),
    updated_at TIMESTAMP DEFAULT NOW()
);

CREATE TABLE refresh_tokens (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    user_id UUID REFERENCES users(id) ON DELETE CASCADE,
    token VARCHAR(500) UNIQUE NOT NULL,
    expires_at TIMESTAMP NOT NULL,
    created_at TIMESTAMP DEFAULT NOW()
);

CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens(user_id);
```

### Step 2: Implement Password Security

Implement password hashing and verification logic.

**Tasks**:
- Use bcrypt (Node.js) or argon2 (Python)
- Set salt rounds to a minimum of 10
- Password strength validation (minimum 8 chars, upper/lowercase, numbers, special characters)

**Decision Criteria**:
- Node.js projects → use the bcrypt library
- Python projects → use argon2-cffi or passlib
- Performance-critical cases → choose bcrypt
- Cases requiring maximum security → choose argon2

**Example** (Node.js + TypeScript):
```typescript
import bcrypt from 'bcrypt';

const SALT_ROUNDS = 12;

export async function hashPassword(password: string): Promise<string> {
    // Validate password strength
    if (password.length < 8) {
        throw new Error('Password must be at least 8 characters');
    }

    const hasUpperCase = /[A-Z]/.test(password);
    const hasLowerCase = /[a-z]/.test(password);
    const hasNumber = /\d/.test(password);
    const hasSpecial = /[!@#$%^&*(),.?":{}|<>]/.test(password);

    if (!hasUpperCase || !hasLowerCase || !hasNumber || !hasSpecial) {
        throw new Error('Password must contain uppercase, lowercase, number, and special character');
    }

    return await bcrypt.hash(password, SALT_ROUNDS);
}

export async function verifyPassword(password: string, hash: string): Promise<boolean> {
    return await bcrypt.compare(password, hash);
}
```

### Step 3: Generate and Verify JWT Tokens

Implement a token system for JWT-based authentication.

**Tasks**:
- Access Token (short expiry: 15 minutes)
- Refresh Token (long expiry: 7–30 days)
- Use a strong SECRET key for JWT signing (manage via environment variables)
- Include only the minimum necessary information in the token payload (user_id, role)

**Example** (Node.js):
```typescript
import jwt from 'jsonwebtoken';

const ACCESS_TOKEN_SECRET = process.env.ACCESS_TOKEN_SECRET!;
const REFRESH_TOKEN_SECRET = process.env.REFRESH_TOKEN_SECRET!;
const ACCESS_TOKEN_EXPIRY = '15m';
const REFRESH_TOKEN_EXPIRY = '7d';

interface TokenPayload {
    userId: string;
    email: string;
    role: string;
}

export function generateAccessToken(payload: TokenPayload): string {
    return jwt.sign(payload, ACCESS_TOKEN_SECRET, {
        expiresIn: ACCESS_TOKEN_EXPIRY,
        issuer: 'your-app-name',
        audience: 'your-app-users'
    });
}

export function generateRefreshToken(payload: TokenPayload): string {
    return jwt.sign(payload, REFRESH_TOKEN_SECRET, {
        expiresIn: REFRESH_TOKEN_EXPIRY,
        issuer: 'your-app-name',
        audience: 'your-app-users'
    });
}

export function verifyAccessToken(token: string): TokenPayload {
    return jwt.verify(token, ACCESS_TOKEN_SECRET, {
        issuer: 'your-app-name',
        audience: 'your-app-users'
    }) as TokenPayload;
}

export function verifyRefreshToken(token: string): TokenPayload {
    return jwt.verify(token, REFRESH_TOKEN_SECRET, {
        issuer: 'your-app-name',
        audience: 'your-app-users'
    }) as TokenPayload;
}
```

### Step 4: Implement Authentication Middleware

Write authentication middleware to protect API requests.

**Checklist**:
- [x] Extract Bearer token from the Authorization header
- [x] Verify token and check expiry
- [x] Attach user info to req.user for valid tokens
- [x] Error handling (401 Unauthorized)

**Example** (Express.js):
```typescript
import { Request, Response, NextFunction } from 'express';
import { verifyAccessToken } from './jwt';

export interface AuthRequest extends Request {
    user?: {
        userId: string;
        email: string;
        role: string;
    };
}

export function authenticateToken(req: AuthRequest, res: Response, next: NextFunction) {
    const authHeader = req.headers['authorization'];
    const token = authHeader && authHeader.split(' ')[1]; // Bearer TOKEN

    if (!token) {
        return res.status(401).json({ error: 'Access token required' });
    }

    try {
        const payload = verifyAccessToken(token);
        req.user = payload;
        next();
    } catch (error) {
        if (error.name === 'TokenExpiredError') {
            return res.status(401).json({ error: 'Token expired' });
        }
        return res.status(403).json({ error: 'Invalid token' });
    }
}

// Role-based authorization middleware
export function requireRole(...roles: string[]) {
    return (req: AuthRequest, res: Response, next: NextFunction) => {
        if (!req.user) {
            return res.status(401).json({ error: 'Authentication required' });
        }

        if (!roles.includes(req.user.role)) {
            return res.status(403).json({ error: 'Insufficient permissions' });
        }

        next();
    };
}
```

### Step 5: Implement Authentication API Endpoints

Write APIs for registration, login, token refresh, etc.

**Tasks**:
- POST /auth/register - registration
- POST /auth/login - login
- POST /auth/refresh - token refresh
- POST /auth/logout - logout
- GET /auth/me - current user info

**Example**:
```typescript
import express from 'express';
import { hashPassword, verifyPassword } from './password';
import { generateAccessToken, generateRefreshToken, verifyRefreshToken } from './jwt';
import { authenticateToken } from './middleware';

const router = express.Router();

// Registration
router.post('/register', async (req, res) => {
    try {
        const { email, password } = req.body;

        // Check for duplicate email

Related in Design