multiAI Summary Pending
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.
231 stars
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
- Download SKILL.md from GitHub
- Place it in
.claude/skills/authentication-setup/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How authentication-setup Compares
| Feature / Agent | authentication-setup | Standard Approach |
|---|---|---|
| Platform Support | multi | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/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.
Which AI agents support this skill?
This skill is compatible with multi.
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`