Skip to main content

auth-implementation-patterns

Master authentication and authorization patterns including JWT, OAuth2, session management, and RBAC to build secure, scalable access control systems. Use when implementing auth systems, securing APIs, or debugging security issues.

来源信息

仓库
majiayu000/claude-skill-registry-data
最近来源活动
2026年4月21日 02:21
检测到的 SKILL.md 语言
英语
星标
22
分支
8

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

文件资源管理器
2 个文件

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
auth-implementation-patterns
description
Master authentication and authorization patterns including JWT, OAuth2, session management, and RBAC to build secure, scalable access control systems. Use when implementing auth systems, securing APIs, or debugging security issues.
# Authentication & Authorization Implementation Patterns Build secure, scalable authentication and authorization systems using industry-standard patterns and modern best practices. ## When to Use This Skill - Implementing user authentication systems - Securing REST or GraphQL APIs - Adding OAuth2/social login - Implementing role-based access control (RBAC) - Designing session management - Migrating authentication systems - Debugging auth issues - Implementing SSO or multi-tenancy ## Core Concepts ### 1. Authentication vs Authorization **Authentication (AuthN)**: Who are you? - Verifying identity (username/password, OAuth, biometrics) - Issuing credentials (sessions, tokens) - Managing login/logout **Authorization (AuthZ)**: What can you do? - Permission checking - Role-based access control (RBAC) - Resource ownership validation - Policy enforcement ### 2. Authentication Strategies **Session-Based:** - Server stores session state - Session ID in cookie - Traditional, simple, stateful **Token-Based (JWT):** - Stateless, self-contained - Scales horizontally - Can store claims **OAuth2/OpenID Connect:** - Delegate authentication - Social login (Google, GitHub) - Enterprise SSO ## JWT Authentication ### Pattern 1: JWT Implementation ```typescript // JWT structure: header.payload.signature import jwt from 'jsonwebtoken' import { Request, Response, NextFunction } from 'express' interface JWTPayload { userId: string email: string role: string iat: number exp: number } // Generate JWT function generateTokens(userId: string, email: string, role: string) { const accessToken = jwt.sign( { userId, email, role }, process.env.JWT_SECRET!, { expiresIn: '15m' } // Short-lived ) const refreshToken = jwt.sign( { userId }, process.env.JWT_REFRESH_SECRET!, { expiresIn: '7d' } // Long-lived ) return { accessToken, refreshToken } } // Verify JWT function verifyToken(token: string): JWTPayload { try { return jwt.verify(token, process.env.JWT_SECRET!) as JWTPayload } catch (error) { if (error instanceof jwt.TokenExpiredError) { throw new Error('Token expired') } if (error instanceof jwt.JsonWebTokenError) { throw new Error('Invalid token') } throw error } } // Middleware function authenticate(req: Request, res: Response, next: NextFunction) { const authHeader = req.headers.authorization if (!authHeader?.startsWith('Bearer ')) { return res.status(401).json({ error: 'No token provided' }) } const token = authHeader.substring(7) try { const payload = verifyToken(token) req.user = payload // Attach user to request next() } catch (error) { return res.status(401).json({ error: 'Invalid token' }) } } // Usage app.get('/api/profile', authenticate, (req, res) => { res.json({ user: req.user }) }) ``` ### Pattern 2: Refresh Token Flow ```typescript interface StoredRefreshToken { token: string userId: string expiresAt: Date createdAt: Date } class RefreshTokenService { // Store refresh token in database async storeRefreshToken(userId: string, refreshToken: string) { const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000) await db.refreshTokens.create({ token: await hash(refreshToken), // Hash before storing userId, expiresAt, }) } // Refresh access token async refreshAccessToken(refreshToken: string) { // Verify refresh token let payload try { payload = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET!) as { userId: string } } catch { throw new Error('Invalid refresh token') } // Check if token exists in database const storedToken = await db.refreshTokens.findOne({ where: { token: await hash(refreshToken), userId: payload.userId, expiresAt: { $gt: new Date() }, }, }) if (!storedToken) { throw new Error('Refresh token not found or expired') } // Get user const user = await db.users.findById(payload.userId) if (!user) { throw new Error('User not found') } // Generate new access token const accessToken = jwt.sign({ userId: user.id, email: user.email, role: user.role }, process.env.JWT_SECRET!, { expiresIn: '15m', }) return { accessToken } } // Revoke refresh token (logout) async revokeRefreshToken(refreshToken: string) { await db.refreshTokens.deleteOne({ token: await hash(refreshToken), }) } // Revoke all user tokens (logout all devices) async revokeAllUserTokens(userId: string) { await db.refreshTokens.deleteMany({ userId }) } } // API endpoints app.post('/api/auth/refresh', async (req, res) => { const { refreshToken } = req.body try { const { accessToken } = await refreshTokenService.refreshAccessToken(refreshToken) res.json({ accessToken }) } catch (error) { res.status(401).json({ error: 'Invalid refresh token' }) } }) app.post('/api/auth/logout', authenticate, async (req, res) => { const { refreshToken } = req.body await refreshTokenService.revokeRefreshToken(refreshToken) res.json({ message: 'Logged out successfully' }) }) ``` ## Session-Based Authentication ### Pattern 1: Express Session ```typescript import session from 'express-session' import RedisStore from 'connect-redis' import { createClient } from 'redis' // Setup Redis for session storage const redisClient = createClient({ url: process.env.REDIS_URL, }) await redisClient.connect() app.use( session({ store: new RedisStore({ client: redisClient }), secret: process.env.SESSION_SECRET!, resave: false, saveUninitialized: false, cookie: { secure: process.env.NODE_ENV === 'production', // HTTPS only httpOnly: true, // No JavaScript access maxAge: 24 * 60 * 60 * 1000, // 24 hours sameSite: 'strict', // CSRF protection }, }) ) // Login app.post('/api/auth/login', async (req, res) => { const { email, password } = req.body const user = await db.users.findOne({ email }) if (!user || !(await verifyPassword(password, user.passwordHash))) { return res.status(401).json({ error: 'Invalid credentials' }) } // Store user in session req.session.userId = user.id req.session.role = user.role res.json({ user: { id: user.id, email: user.email, role: user.role } }) }) // Session middleware function requireAuth(req: Request, res: Response, next: NextFunction) { if (!req.session.userId) { return res.status(401).json({ error: 'Not authenticated' }) } next() } // Protected route app.get('/api/profile', requireAuth, async (req, res) => { const user = await db.users.findById(req.session.userId) res.json({ user }) }) // Logout app.post('/api/auth/logout', (req, res) => { req.session.destroy((err) => { if (err) { return res.status(500).json({ error: 'Logout failed' }) } res.clearCookie('connect.sid') res.json({ message: 'Logged out successfully' }) }) }) ``` ## OAuth2 / Social Login ### Pattern 1: OAuth2 with Passport.js ```typescript import passport from 'passport' import { Strategy as GoogleStrategy } from 'passport-google-oauth20' import { Strategy as GitHubStrategy } from 'passport-github2' // Google OAuth passport.use( new GoogleStrategy( { clientID: process.env.GOOGLE_CLIENT_ID!, clientSecret: process.env.GOOGLE_CLIENT_SECRET!, callbackURL: '/api/auth/google/callback', }, async (accessToken, refreshToken, profile, done) => { try { // Find or create user let user = await db.users.findOne({ googleId: profile.id, }) if (!user) { user = await db.users.create({ googleId: profile.id, email: profile.emails?.[0]?.value, name: profile.displayName, avatar: profile.photos?.[0]?.value, }) } return done(null, user) } catch (error) { return done(error, undefined) } } ) ) // Routes app.get( '/api/auth/google', passport.authenticate('google', { scope: ['profile', 'email'], }) ) app.get('/api/auth/google/callback', passport.authenticate('google', { session: false }), (req, res) => { // Generate JWT const tokens = generateTokens(req.user.id, req.user.email, req.user.role) // Redirect to frontend with token res.redirect(`${process.env.FRONTEND_URL}/auth/callback?token=${tokens.accessToken}`) }) ``` ## Authorization Patterns ### Pattern 1: Role-Based Access Control (RBAC) ```typescript enum Role { USER = 'user', MODERATOR = 'moderator', ADMIN = 'admin', } const roleHierarchy: Record<Role, Role[]> = { [Role.ADMIN]: [Role.ADMIN, Role.MODERATOR, Role.USER], [Role.MODERATOR]: [Role.MODERATOR, Role.USER], [Role.USER]: [Role.USER], } function hasRole(userRole: Role, requiredRole: Role): boolean { return roleHierarchy[userRole].includes(requiredRole) } // Middleware function requireRole(...roles: Role[]) { return (req: Request, res: Response, next: NextFunction) => { if (!req.user) { return res.status(401).json({ error: 'Not authenticated' }) } if (!roles.some((role) => hasRole(req.user.role, role))) { return res.status(403).json({ error: 'Insufficient permissions' }) } next() } } // Usage app.delete('/api/users/:id', authenticate, requireRole(Role.ADMIN), async (req, res) => { // Only admins can delete users await db.users.delete(req.params.id) res.json({ message: 'User deleted' }) }) ``` ### Pattern 2: Permission-Based Access Control ```typescript enum Permission { READ_USERS = 'read:users', WRITE_USERS = 'write:users', DELETE_USERS = 'delete:users', READ_POSTS = 'read:posts', WRITE_POSTS = 'write:posts', } const rolePermissions: Record<Role, Permission[]> = { [Role.USER]: [Permission.READ_POSTS, Permission.WRITE_POSTS], [Role.MODERATOR]: [Permission.READ_POSTS, Permission.WRITE_POSTS, Permission.READ_USERS], [Role.ADMIN]: Object.values(Permission), } function hasPermission(userRole: Role, permission: Permission): boolean { return rolePermissions[userRole]?.includes(permission) ?? false } function requirePermission(...permissions: Permission[]) { return (req: Request, res: Response, next: NextFunction) => { if (!req.user) { return res.status(401).json({ error: 'Not authenticated' }) } const hasAllPermissions = permissions.every((permission) => hasPermission(req.user.role, permission)) if (!hasAllPermissions) { return res.status(403).json({ error: 'Insufficient permissions' }) } next() } } // Usage app.get('/api/users', authenticate, requirePermission(Permission.READ_USERS), async (req, res) => { const users = await db.users.findAll() res.json({ users }) }) ``` ### Pattern 3: Resource Ownership ```typescript // Check if user owns resource async function requireOwnership(resourceType: 'post' | 'comment', resourceIdParam: string = 'id') { return async (req: Request, res: Response, next: NextFunction) => { if (!req.user) { return res.status(401).json({ error: 'Not authenticated' }) }
在 GitHub 查看
这个 SKILL.md 很大,SkillsMP 这里只预览前一段内容。 在 GitHub 查看