authentication-setup by akillness/oh-my-skills
npx skills add https://github.com/akillness/oh-my-skills --skill authentication-setup列出应触发此技能的具体情况:
需要从用户处收集的必需和可选输入信息:
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
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
指定要精确遵循的逐步任务序列。
为用户和认证设计数据库模式。
任务:
示例(PostgreSQL):
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);
实现密码哈希和验证逻辑。
任务:
决策标准:
示例(Node.js + 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);
}
为基于 JWT 的认证实现令牌系统。
任务:
示例(Node.js):
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;
}
编写认证中间件以保护 API 请求。
检查清单:
示例(Express.js):
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();
};
}
编写用于注册、登录、令牌刷新等的 API。
任务:
示例:
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;
定义交付成果应遵循的确切格式。
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
# 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
指定强制性规则和禁止的操作。
演示如何通过实际用例应用此技能。
情况:为 Node.js Express 应用添加基于 JWT 的用户认证
用户请求:
Add JWT authentication to an Express.js app using PostgreSQL,
with access token expiry of 15 minutes and refresh token expiry of 7 days.
技能应用过程:
安装包:
npm install jsonwebtoken bcrypt pg
npm install --save-dev @types/jsonwebtoken @types/bcrypt
创建数据库模式(使用上面的 SQL)
设置环境变量:
ACCESS_TOKEN_SECRET=$(openssl rand -base64 32)
REFRESH_TOKEN_SECRET=$(openssl rand -base64 32)
实现认证模块(使用上面的代码示例)
连接 API 路由:
import authRoutes from './auth/routes';
app.use('/api/auth', authRoutes);
最终结果:基于 JWT 的认证系统完成,注册/登录/令牌刷新 API 正常工作
情况:区分管理员和普通用户的权限系统
用户请求:
Create an API accessible only to administrators.
Regular users should receive a 403 error.
最终结果:
// 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
有效使用此技能的建议。
常见问题及其解决方案。
症状:
原因:访问令牌和刷新令牌的密钥不同,但使用了相同的密钥来验证两者。
解决方案:
ACCESS_TOKEN_SECRET、REFRESH_TOKEN_SECRETdotenv)症状:浏览器控制台中出现 "CORS policy" 错误
原因:Express 服务器缺少 CORS 配置
解决方案:
import cors from 'cors';
app.use(cors({
origin: process.env.FRONTEND_URL || 'http://localhost:3000',
credentials: true
}));
症状:用户频繁被登出
原因:刷新令牌未在数据库中正确管理
解决方案:
#authentication #authorization #JWT #OAuth #security #backend
每周安装次数
1
仓库
GitHub 星标数
3
首次出现
1 天前
安全审计
安装于
mcpjam1
claude-code1
junie1
windsurf1
zencoder1
crush1
Lists specific situations where this skill should be triggered:
The required and optional input information to collect from the user:
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
Specifies the step-by-step task sequence to follow precisely.
Design the database schema for users and authentication.
Tasks :
Example (PostgreSQL):
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);
Implement password hashing and verification logic.
Tasks :
Decision Criteria :
Example (Node.js + 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);
}
Implement a token system for JWT-based authentication.
Tasks :
Example (Node.js):
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;
}
Write authentication middleware to protect API requests.
Checklist :
Example (Express.js):
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();
};
}
Write APIs for registration, login, token refresh, etc.
Tasks :
Example :
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;
Defines the exact format that deliverables should follow.
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
# 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
Specifies mandatory rules and prohibited actions.
Password Security : Never store passwords in plaintext
Environment Variable Management : Manage all secret keys via environment variables
Token Expiry : Access Tokens should be short-lived (15 min), Refresh Tokens appropriately longer (7 days)
Plaintext Passwords : Never store passwords in plaintext or print them to logs
Hardcoding JWT SECRET : Do not write SECRET keys directly in code
Sensitive Data in Tokens : Do not include passwords, card numbers, or other sensitive data in JWT payloads
Demonstrates how to apply the skill through real-world use cases.
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 :
Install packages:
npm install jsonwebtoken bcrypt pg
npm install --save-dev @types/jsonwebtoken @types/bcrypt
Create the database schema (use the SQL above)
Set environment variables:
ACCESS_TOKEN_SECRET=$(openssl rand -base64 32)
REFRESH_TOKEN_SECRET=$(openssl rand -base64 32)
Implement auth modules (use the code examples above)
Connect API routes:
import authRoutes from './auth/routes';
app.use('/api/auth', authRoutes);
Final Result : JWT-based authentication system complete, registration/login/token-refresh APIs working
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 :
// 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
Recommendations for using this skill effectively.
Password Rotation Policy : Recommend periodic password changes
Multi-Factor Authentication (MFA) : Apply 2FA to important accounts
Audit Logging : Log all authentication events
Common problems and their solutions.
Symptom :
Cause : The SECRET keys for Access Token and Refresh Token are different, but the same key is being used to verify both.
Solution :
ACCESS_TOKEN_SECRET, REFRESH_TOKEN_SECRETdotenv)Symptom : "CORS policy" error in the browser console
Cause : Missing CORS configuration on the Express server
Solution :
import cors from 'cors';
app.use(cors({
origin: process.env.FRONTEND_URL || 'http://localhost:3000',
credentials: true
}));
Symptom : Users are frequently logged out
Cause : Refresh Token is not properly managed in the DB
Solution :
#authentication #authorization #JWT #OAuth #security #backend
Weekly Installs
1
Repository
GitHub Stars
3
First Seen
1 day ago
Security Audits
Gen Agent Trust HubPassSocketFailSnykPass
Installed on
mcpjam1
claude-code1
junie1
windsurf1
zencoder1
crush1
agent-browser 浏览器自动化工具 - Vercel Labs 命令行网页操作与测试
150,000 周安装
TypeScript/JavaScript 开发技能 - 掌握 Metabase 开源项目开发流程与工具
206 周安装
Upstash Redis SDK 完整指南 - Redis-JS 安装、使用与性能优化教程
206 周安装
Tavily API 网络搜索技能 - 实现网页爬取、内容提取和智能研究功能
206 周安装
企业合规助手:GDPR、CCPA等隐私法规合规指南与数据处理协议审查清单
206 周安装
DeepSpeed 开发助手:官方文档指南、API 使用与性能优化教程
207 周安装
utrace-analysis - GitHub API 代码分析与追踪工具 | 开源项目监控与调试
1 周安装