authentication-setup

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.

242 stars

Best use case

authentication-setup is best used when you need a repeatable AI agent workflow instead of a one-off prompt. It is especially useful for teams working in multi. 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 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.

Users should expect a more consistent workflow output, faster repeated execution, and less time spent rewriting prompts from scratch.

Practical example

Example input

Use the "authentication-setup" skill to help with this workflow task. Context: 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.

Example output

A structured workflow result with clearer steps, more consistent formatting, and an output that is easier to reuse in the next run.

When to use this skill

  • Use this skill when you want a reusable workflow rather than writing the same prompt again and again.

When not to use this skill

  • Do not use this when you only need a one-off answer and do not need a reusable workflow.
  • Do not use it if you cannot install or maintain the related files, repository context, or supporting tools.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/authentication-setup/SKILL.md --create-dirs "https://raw.githubusercontent.com/aiskillstore/marketplace/main/skills/supercent-io/authentication-setup/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/authentication-setup/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How authentication-setup Compares

Feature / Agentauthentication-setupStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

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.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# 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
        const existingUser = await db.user.findUnique({ where: { email } });
        if (existingUser) {
            return res.status(409).json({ error: 'Email already exists' });
        }

        // Hash the password
        const passwordHash = await hashPassword(password);

        // Create the user
        const user = await db.user.create({
            data: { email, password_hash: passwordHash, role: 'user' }
        });

        // Generate tokens
        const accessToken = generateAccessToken({
            userId: user.id,
            email: user.email,
            role: user.role
        });
        const refreshToken = generateRefreshToken({
            userId: user.id,
            email: user.email,
            role: user.role
        });

        // Store Refresh token in DB
        await db.refreshToken.create({
            data: {
                user_id: user.id,
                token: refreshToken,
                expires_at: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) // 7 days
            }
        });

        res.status(201).json({
            user: { id: user.id, email: user.email, role: user.role },
            accessToken,
            refreshToken
        });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

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

        // Find the user
        const user = await db.user.findUnique({ where: { email } });
        if (!user || !user.password_hash) {
            return res.status(401).json({ error: 'Invalid credentials' });
        }

        // Verify the password
        const isValid = await verifyPassword(password, user.password_hash);
        if (!isValid) {
            return res.status(401).json({ error: 'Invalid credentials' });
        }

        // Generate tokens
        const accessToken = generateAccessToken({
            userId: user.id,
            email: user.email,
            role: user.role
        });
        const refreshToken = generateRefreshToken({
            userId: user.id,
            email: user.email,
            role: user.role
        });

        // Store Refresh token
        await db.refreshToken.create({
            data: {
                user_id: user.id,
                token: refreshToken,
                expires_at: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
            }
        });

        res.json({
            user: { id: user.id, email: user.email, role: user.role },
            accessToken,
            refreshToken
        });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

// Token refresh
router.post('/refresh', async (req, res) => {
    try {
        const { refreshToken } = req.body;

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

        // Verify Refresh token
        const payload = verifyRefreshToken(refreshToken);

        // Check token in DB
        const storedToken = await db.refreshToken.findUnique({
            where: { token: refreshToken }
        });

        if (!storedToken || storedToken.expires_at < new Date()) {
            return res.status(403).json({ error: 'Invalid or expired refresh token' });
        }

        // Generate new Access token
        const accessToken = generateAccessToken({
            userId: payload.userId,
            email: payload.email,
            role: payload.role
        });

        res.json({ accessToken });
    } catch (error) {
        res.status(403).json({ error: 'Invalid refresh token' });
    }
});

// Current user info
router.get('/me', authenticateToken, async (req: AuthRequest, res) => {
    try {
        const user = await db.user.findUnique({
            where: { id: req.user!.userId },
            select: { id: true, email: true, role: true, created_at: true }
        });

        res.json({ user });
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

export default router;
```

## Output format

Defines the exact format that deliverables should follow.

### Basic Structure

```
Project directory/
├── src/
│   ├── auth/
│   │   ├── password.ts          # password hashing/verification
│   │   ├── jwt.ts                # JWT token generation/verification
│   │   ├── middleware.ts         # authentication middleware
│   │   └── routes.ts             # authentication API endpoints
│   ├── models/
│   │   └── User.ts               # user model
│   └── database/
│       └── schema.sql            # database schema
├── .env.example                  # environment variable template
└── README.md                     # authentication system documentation
```

### Environment Variable File (.env.example)

```bash
# JWT Secrets (MUST change in production)
ACCESS_TOKEN_SECRET=your-access-token-secret-min-32-characters
REFRESH_TOKEN_SECRET=your-refresh-token-secret-min-32-characters

# Database
DATABASE_URL=postgresql://user:password@localhost:5432/myapp

# OAuth (Optional)
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
GITHUB_CLIENT_ID=your-github-client-id
GITHUB_CLIENT_SECRET=your-github-client-secret
```

## Constraints

Specifies mandatory rules and prohibited actions.

### Mandatory Rules (MUST)

1. **Password Security**: Never store passwords in plaintext
   - Use a proven hashing algorithm such as bcrypt or argon2
   - Salt rounds minimum of 10

2. **Environment Variable Management**: Manage all secret keys via environment variables
   - Add .env files to .gitignore
   - Provide a list of required variables via .env.example

3. **Token Expiry**: Access Tokens should be short-lived (15 min), Refresh Tokens appropriately longer (7 days)
   - Balance security and user experience
   - Store Refresh Tokens in the DB to enable revocation

### Prohibited Actions (MUST NOT)

1. **Plaintext Passwords**: Never store passwords in plaintext or print them to logs
   - Serious security risk
   - Legal liability issues

2. **Hardcoding JWT SECRET**: Do not write SECRET keys directly in code
   - Risk of being exposed on GitHub
   - Production security vulnerability

3. **Sensitive Data in Tokens**: Do not include passwords, card numbers, or other sensitive data in JWT payloads
   - JWT can be decoded (it is not encrypted)
   - Include only the minimum information (user_id, role)

### Security Rules

- **Rate Limiting**: Apply rate limiting to the login API (prevents brute-force attacks)
- **HTTPS Required**: Use HTTPS only in production environments
- **CORS Configuration**: Allow only approved domains to access the API
- **Input Validation**: Validate all user input (prevents SQL Injection and XSS)

## Examples

Demonstrates how to apply the skill through real-world use cases.

### Example 1: Express.js + PostgreSQL JWT Authentication

**Situation**: Adding JWT-based user authentication to a Node.js Express app

**User Request**:
```
Add JWT authentication to an Express.js app using PostgreSQL,
with access token expiry of 15 minutes and refresh token expiry of 7 days.
```

**Skill Application Process**:

1. Install packages:
   ```bash
   npm install jsonwebtoken bcrypt pg
   npm install --save-dev @types/jsonwebtoken @types/bcrypt
   ```

2. Create the database schema (use the SQL above)

3. Set environment variables:
   ```bash
   ACCESS_TOKEN_SECRET=$(openssl rand -base64 32)
   REFRESH_TOKEN_SECRET=$(openssl rand -base64 32)
   ```

4. Implement auth modules (use the code examples above)

5. Connect API routes:
   ```typescript
   import authRoutes from './auth/routes';
   app.use('/api/auth', authRoutes);
   ```

**Final Result**: JWT-based authentication system complete, registration/login/token-refresh APIs working

### Example 2: Role-Based Access Control (RBAC)

**Situation**: A permission system that distinguishes administrators from regular users

**User Request**:
```
Create an API accessible only to administrators.
Regular users should receive a 403 error.
```

**Final Result**:
```typescript
// Admin-only API
router.delete('/users/:id',
    authenticateToken,           // verify authentication
    requireRole('admin'),         // verify role
    async (req, res) => {
        // user deletion logic
        await db.user.delete({ where: { id: req.params.id } });
        res.json({ message: 'User deleted' });
    }
);

// Usage example
// Regular user (role: 'user') request → 403 Forbidden
// Admin (role: 'admin') request → 200 OK
```

## Best practices

Recommendations for using this skill effectively.

### Quality Improvement

1. **Password Rotation Policy**: Recommend periodic password changes
   - Change notification every 90 days
   - Prevent reuse of the last 5 passwords
   - Balance user experience and security

2. **Multi-Factor Authentication (MFA)**: Apply 2FA to important accounts
   - Use TOTP apps such as Google Authenticator or Authy
   - SMS is less secure (risk of SIM swapping)
   - Provide backup codes

3. **Audit Logging**: Log all authentication events
   - Record login success/failure, IP address, and User Agent
   - Anomaly detection and post-incident analysis
   - GDPR compliance (exclude sensitive data)

### Efficiency Improvements

- **Token Blacklist**: Revoke Refresh Tokens on logout
- **Redis Caching**: Cache frequently used user data
- **Database Indexing**: Add indexes on email and refresh_token

## Common Issues

Common problems and their solutions.

### Issue 1: "JsonWebTokenError: invalid signature"

**Symptom**:
- Error occurs during token verification
- Login succeeds but authenticated API calls fail

**Cause**:
The SECRET keys for Access Token and Refresh Token are different,
but the same key is being used to verify both.

**Solution**:
1. Check environment variables: `ACCESS_TOKEN_SECRET`, `REFRESH_TOKEN_SECRET`
2. Use the correct SECRET for each token type
3. Verify that environment variables load correctly (initialize `dotenv`)

### Issue 2: Frontend Cannot Log In Due to CORS Error

**Symptom**: "CORS policy" error in the browser console

**Cause**: Missing CORS configuration on the Express server

**Solution**:
```typescript
import cors from 'cors';

app.use(cors({
    origin: process.env.FRONTEND_URL || 'http://localhost:3000',
    credentials: true
}));
```

### Issue 3: Refresh Token Keeps Expiring

**Symptom**: Users are frequently logged out

**Cause**: Refresh Token is not properly managed in the DB

**Solution**:
1. Confirm Refresh Token is saved to DB upon creation
2. Set an appropriate expiry time (minimum 7 days)
3. Add a cron job to regularly clean up expired tokens

## References

### Official Documentation
- [JWT.io - JSON Web Token Introduction](https://jwt.io/introduction)
- [OWASP Authentication Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html)
- [OAuth 2.0 RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749)

### Libraries
- [jsonwebtoken (Node.js)](https://github.com/auth0/node-jsonwebtoken)
- [bcrypt (Node.js)](https://github.com/kelektiv/node.bcrypt.js)
- [Passport.js](http://www.passportjs.org/) - multiple authentication strategies
- [NextAuth.js](https://next-auth.js.org/) - Next.js authentication

### Security Guides
- [OWASP Top 10](https://owasp.org/www-project-top-ten/)
- [NIST Digital Identity Guidelines](https://pages.nist.gov/800-63-3/)

## Metadata

### Version
- **Current Version**: 1.0.0
- **Last Updated**: 2025-01-01
- **Compatible Platforms**: Claude, ChatGPT, Gemini

### Related Skills
- [api-design](../api-design/SKILL.md): API endpoint design
- [security](../../infrastructure/security/SKILL.md): Security best practices

### Tags
`#authentication` `#authorization` `#JWT` `#OAuth` `#security` `#backend`

Related Skills

system-environment-setup

242
from aiskillstore/marketplace

Configure development and production environments for consistent and reproducible setups. Use when setting up new projects, Docker environments, or development tooling. Handles Docker Compose, .env configuration, dev containers, and infrastructure as code.

environment-setup

242
from aiskillstore/marketplace

Configure and manage development, staging, and production environments. Use when setting up environment variables, managing configurations, or separating environments. Handles .env files, config management, and environment-specific settings.

observability-monitoring-monitor-setup

242
from aiskillstore/marketplace

You are a monitoring and observability expert specializing in implementing comprehensive monitoring solutions. Set up metrics collection, distributed tracing, log aggregation, and create insightful da

microsoft-azure-webjobs-extensions-authentication-events-dotnet

242
from aiskillstore/marketplace

Microsoft Entra Authentication Events SDK for .NET. Azure Functions triggers for custom authentication extensions. Use for token enrichment, custom claims, attribute collection, and OTP customization in Entra ID. Triggers: "Authentication Events", "WebJobsAuthenticationEventsTrigger", "OnTokenIssuanceStart", "OnAttributeCollectionStart", "custom claims", "token enrichment", "Entra custom extension", "authentication extension".

environment-setup-guide

242
from aiskillstore/marketplace

Guide developers through setting up development environments with proper tools, dependencies, and configurations

conductor-setup

242
from aiskillstore/marketplace

Initialize project with Conductor artifacts (product definition, tech stack, workflow, style guides)

broken-authentication

242
from aiskillstore/marketplace

This skill should be used when the user asks to "test for broken authentication vulnerabilities", "assess session management security", "perform credential stuffing tests", "evaluate ...

broken-authentication-testing

242
from aiskillstore/marketplace

This skill should be used when the user asks to "test for broken authentication vulnerabilities", "assess session management security", "perform credential stuffing tests", "evaluate password policies", "test for session fixation", or "identify authentication bypass flaws". It provides comprehensive techniques for identifying authentication and session management weaknesses in web applications.

convex-setup-auth

242
from aiskillstore/marketplace

Sets up Convex authentication with user management, identity mapping, and access control. Use this skill when adding login or signup to a Convex app, configuring Convex Auth, Clerk, WorkOS AuthKit, Auth0, or custom JWT providers, wiring auth.config.ts, protecting queries and mutations with ctx.auth.getUserIdentity(), creating a users table with identity mapping, or setting up role-based access control, even if the user just says "add auth" or "make it require login."

expo-tailwind-setup

242
from aiskillstore/marketplace

Set up Tailwind CSS v4 in Expo with react-native-css and NativeWind v5 for universal styling

ci-pipeline-setup

242
from aiskillstore/marketplace

Set up CI/CD pipelines with GitHub Actions. Use when creating new projects, adding automation, or when manual verification becomes bottleneck. Covers lint, test, build, deploy automation.

when-setting-network-security-use-network-security-setup

242
from aiskillstore/marketplace

Configure Claude Code sandbox network isolation with trusted domains, custom access policies, and environment variables for secure network communication.