mcpField
A
authentication-patterns

authentication-patterns

github.com/zebbern开发4.7k46 次安装1 天前更新
代码仓库

关于 authentication-patterns

authentication-patterns 是为开发者提供的认证实现与安全审查参考技能,涵盖常见认证方案、提供方选择和发布前检查。它汇总令牌、会话、密码及安全控制方面的实践建议。

主要功能

  1. 01比较会话、JWT、OAuth 和 Passkeys
  2. 02提供认证方案选择指引
  3. 03介绍 JWT 生命周期与存储实践
  4. 04比较认证提供方模式
  5. 05提供发布前安全检查清单

适用场景

  1. 01为新项目选择认证方案
  2. 02审查现有认证流程的风险
  3. 03迁移认证策略
  4. 04发布认证相关改动前检查安全项

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/zebbern/claude-code-guide --skill authentication-patterns

安装后在 Claude Code 中输入/authentication-patterns确认已加载。

详细介绍

身份验证模式技能

实现安全、适用于生产环境的身份验证参考。

WHEN_TO_USE

在项目中实现身份验证、审查现有身份验证流程的安全问题、选择身份验证提供商或迁移身份验证策略时,使用此技能。在发布任何身份验证相关更改之前,使用安全检查清单。

AUTH_APPROACHES

方式工作原理适用场景缺点
基于会话服务器在 DB/Redis 中存储会话,客户端通过 Cookie 持有会话 ID传统的服务器渲染应用,需要即时撤销会话的应用需要服务器端存储;若没有共享存储,横向扩展较难
JWT(无状态)服务器对令牌签名,客户端在每次请求中发送令牌API 优先的应用、微服务、移动客户端无法在没有阻止列表的情况下撤销;令牌大小会随声明增加
OAuth 2.0 / OIDC将身份验证委托给外部提供商(Google、GitHub 等)社交登录、企业 SSO、减少身份验证责任流程更复杂,依赖外部提供商的可用性
Passkeys / WebAuthn加密密钥对,无需密码高安全性应用、无密码 UX对旧版浏览器的支持有限;需要进行用户教育
决策指南
  • 具有简单需求的服务器渲染应用 → 基于会话
  • 调用 API 的 SPA 或移动应用 → 使用刷新令牌轮换的 JWT
  • 需要社交登录或 SSO → OAuth 2.0 / OIDC
  • 从零开始且目标是现代 UX → Passkeys + OAuth 回退方案

JWT_BEST_PRACTICES

令牌生命周期
Login → Access Token (short-lived) + Refresh Token (long-lived, rotated)
  │
  ├─ Access Token: 15 min expiry, sent via httpOnly cookie or Authorization header
  │
  └─ Refresh Token: 7-30 day expiry, stored in httpOnly secure cookie
       │
       └─ On use: issue new access + new refresh token, invalidate old refresh token
规则
  • [P0-MUST] 为访问令牌设置较短的有效期(15 分钟或更短)。
  • [P0-MUST] 将令牌存储在 httpOnly、Secure、SameSite=Lax Cookie 中,绝不要存储在 localStorage 或 sessionStorage 中。
  • [P0-MUST] 实现刷新令牌轮换,每个刷新令牌只能使用一次。
  • [P0-MUST] 在服务器端维护已撤销刷新令牌的阻止列表。
  • [P1-SHOULD] JWT 载荷中仅包含必要的声明(sub、iat、exp、role)。保持载荷精简。
  • [P1-SHOULD] 分布式系统使用非对称签名(RS256 或 ES256);单服务场景使用对称签名(HS256)。
  • [P1-SHOULD] 在每个请求中验证 iss、aud 和 exp 声明。
  • [P2-MAY] 当令牌载荷包含敏感数据时,使用 JWE(加密 JWT)。
令牌存储方式对比
存储方式防 XSS防 CSRF建议
httpOnly Cookie是否(需要 CSRF 令牌)推荐
localStorage否是绝不要用于存储身份验证令牌
sessionStorage否是绝不要用于存储身份验证令牌
内存中(JS 变量)是是适用于 SPA,但刷新后会丢失

PROVIDER_PATTERNS

对比
提供商类型适用场景定价主要功能
NextAuth / Auth.js开源库希望完全掌控的 Next.js 应用免费80+ 个提供商、DB 适配器、可自托管
Clerk托管服务快速上线、预构建 UI、用户管理免费套餐,之后按 MAU 计费即插即用组件、用户控制面板、组织支持
Supabase Auth托管服务(Supabase 的一部分)已使用 Supabase 处理 DB/存储的应用免费套餐,之后按 MAU 计费行级安全集成、魔法链接、SSO
Lucia开源库完全掌控、最少抽象免费基于会话、与框架无关、类型安全
何时使用各提供商
  • NextAuth / Auth.js:需要灵活选择提供商、可自托管,并控制数据库会话。适用于需要自定义流程的场景。
  • Clerk:希望通过预构建 UI 组件快速完成身份验证。适用于 MVP 和不想自行构建身份验证 UI 的团队。
  • Supabase Auth:已经在使用 Supabase。身份验证可与 RLS 策略集成,实现行级安全。
  • Lucia:需要一个精简、类型安全且不受框架限制的会话库。
NextAuth.js 设置模式
// app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth";
import GitHub from "next-auth/providers/github";
import { PrismaAdapter } from "@auth/prisma-adapter";
import { prisma } from "@/lib/prisma";

export const { handlers, auth, signIn, signOut } = NextAuth({
  adapter: PrismaAdapter(prisma),
  providers: [
    GitHub({
      clientId: process.env.GITHUB_CLIENT_ID!,
      clientSecret: process.env.GITHUB_CLIENT_SECRET!,
    }),
  ],
  callbacks: {
    session({ session, user }) {
      session.user.id = user.id;
      return session;
    },
  },
});

SECURITY_CHECKLIST

发布身份验证前
  • 速率限制:登录端点对每个 IP 每分钟限制 5-10 次尝试。
  • CSRF 保护:对所有会更改状态的请求使用反 CSRF 令牌(或使用 SameSite=Lax Cookie)。
  • 密码哈希:使用 bcrypt(成本因子 12+)或 argon2id——绝不使用 MD5、SHA-1 或纯 SHA-256。
  • 仅使用 HTTPS:所有身份验证端点均通过 TLS 提供服务。Cookie 带有 Secure 标志。
  • 输入验证:验证电子邮件格式、密码长度(最少 8 个字符,最多 128 个字符),并确保不存在 SQL/NoSQL 注入漏洞。
  • 账户枚举:无论账户是否存在,登录和注册都返回相同的响应。
  • 会话失效:注销时应使服务端会话/刷新令牌失效,而不只是清除客户端 Cookie。
  • 支持 MFA:对敏感账户,将 TOTP(身份验证器应用)或 WebAuthn 用作第二重验证。
  • 密码重置:令牌应有时限(1 小时)、只能使用一次,并通过安全通道发送。
  • 审计日志:记录身份验证事件(登录、注销、失败尝试、密码更改),并包含时间戳和 IP。
密码哈希
// Using bcrypt
import bcrypt from "bcrypt";

const SALT_ROUNDS = 12;

async function hashPassword(password: string): Promise<string> {
  return bcrypt.hash(password, SALT_ROUNDS);
}

async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return bcrypt.compare(password, hash);
}
// Using argon2 (preferred for new projects)
import argon2 from "argon2";

async function hashPassword(password: string): Promise<string> {
  return argon2.hash(password, { type: argon2.argon2id });
}

async function verifyPassword(hash: string, password: string): Promise<boolean> {
  return argon2.verify(hash, password);
}

常见错误

错误风险修复方法
将 JWT 存储在 localStorage 中XSS 可窃取令牌使用 httpOnly Cookie
JWT 有效期过长(数天/数周)被盗令牌会在较长时间内有效使用 15 min 访问令牌 + 轮换刷新令牌
缺少 CSRF 保护攻击者可从其他网站伪造请求使用 SameSite=Lax Cookie + CSRF 令牌
密码要求过弱暴力破解和凭据填充攻击至少 8 个字符,并检查密码是否出现在已泄露密码列表中
登录时暴露用户是否存在账户枚举使用通用的“凭据无效”消息
不轮换刷新令牌被盗的刷新令牌会授予无限期访问权限使用单次有效的刷新令牌并进行轮换
在源代码中硬编码密钥凭据可能通过 git 历史泄露使用环境变量,绝不提交密钥
登录时缺少速率限制暴力破解攻击每个 IP 每分钟限制 5-10 次尝试,并采用指数退避
自行实现加密存在不易察觉的漏洞使用成熟的库(bcrypt、argon2、jose)
不验证 JWT 声明令牌可能在不同服务间被滥用始终验证 iss、aud、exp

评论

支持 Markdown