M-Uzair-dev/RedAuth

GitHub: M-Uzair-dev/RedAuth

一个生产就绪的 Express/TypeScript 认证微服务模板,提供多设备会话管理、令牌轮换和安全防护等企业级特性。

Stars: 1 | Forks: 0

# RedAuth 一个生产就绪的 Express + TypeScript 认证后端。开箱即用的安全、设备感知会话 —— 拿来即用,以此为基础进行构建。 **作者:** Uzair Manan **许可证:** ISC **代码库:** [M-Uzair-dev/Authetication-Template](https://github.com/M-Uzair-dev/Authetication-Template) **问题反馈:** [GitHub Issues](https://github.com/M-Uzair-dev/Authetication-Template/issues) ## 功能特性 - 双令牌会话管理(通过 httpOnly cookies 实现访问 + 刷新 JWT) - 设备作用域会话 —— 每个用户每台设备一个刷新令牌,支持多个并发会话 - 刷新令牌轮换,并自动检测盗用(检测到重放攻击时清除所有会话) - 基于 Redis 的滑动窗口速率限制、用户缓存和即时令牌撤销 - BullMQ 工作队列,用于带有重试和退避机制的异步邮件投递 - 定时的令牌清理 cron(每 10 分钟) - 每个端点均进行 Zod v4 输入验证 - 对所有敏感端点(忘记密码、重发邮件、登录)进行时序攻击缓解 - 用于验证、登录警报和密码重置的 HTML 邮件模板 ## 技术栈 | 层级 | 技术 | |---|---| | 运行时 | Node.js v20+ (ESM) | | 框架 | Express 5 | | 语言 | TypeScript (NodeNext 模块解析) | | 数据库 | PostgreSQL via Prisma 7 + `pg` 连接池适配器 | | 缓存 / 队列代理 | Redis via ioredis | | 后台任务 | BullMQ | | 校验 | Zod 4 | | 认证 | jsonwebtoken + bcrypt (cost 12) | | 邮件 | Nodemailer | | 安全头 | Helmet | ## 文件结构 ``` AuthTemplate/ ├── src/ │ ├── index.ts # App entry — middleware stack, routes, server start │ ├── controllers/ │ │ ├── auth.controller.ts # Login, signup, password reset, email verification, logout │ │ └── user.controller.ts # Get/update/delete user, sessions, revoke session │ ├── services/ │ │ ├── auth.service.ts # Core auth business logic │ │ ├── token.service.ts # JWT signing, verification, rotation, revocation │ │ ├── email.service.ts # Email template rendering + BullMQ job dispatch │ │ └── user.service.ts # User CRUD, session queries │ ├── routes/ │ │ ├── auth.route.ts # /auth/* route definitions + rate limiter attachment │ │ └── user.route.ts # /user/* route definitions │ ├── middleware/ │ │ └── verifyUser.ts # JWT auth middleware, sets req.userId, records last-active │ ├── schemas/ │ │ ├── auth.schema.ts # Zod schemas for all auth endpoint inputs │ │ └── user.schema.ts # Zod schemas for user update and session revoke │ ├── errors/ │ │ └── errors.ts # appError class + errorType enum │ ├── utils/ │ │ ├── rateLimiter.ts # Redis sliding window rate limiter factory │ │ ├── cacheUser.ts # Redis user cache read/write/delete (Zod-validated) │ │ ├── handleError.ts # Centralized error handler (appError, ZodError, unknown) │ │ └── getRequestInfo.ts # Parses User-Agent + IP for login metadata │ ├── lib/ │ │ ├── prisma.ts # Prisma client singleton with pg pool adapter │ │ └── redis.ts # ioredis client singleton │ ├── queues/ │ │ ├── email.queue.ts # BullMQ email queue definition │ │ └── tokenCleanup.queue.ts # BullMQ cleanup queue with repeating job │ ├── workers/ │ │ ├── email.worker.ts # Processes email jobs, handles retry/failure cleanup │ │ └── tokenCleanup.worker.ts # Deletes expired tokens from DB every 10 minutes │ ├── emails/ │ │ ├── emailVerification.html # Verification email template │ │ ├── loginAlert.html # Login alert email template │ │ └── passwordReset.html # Password reset email template │ └── types/ │ └── express.d.ts # Express Request augmentation (req.userId) ├── prisma/ │ ├── schema.prisma # User + Token models │ └── migrations/ # Migration history ├── postman-collection.json # Importable Postman collection (all 14 endpoints) ├── API_ROUTES.md # Full API reference — request/response shapes ├── env_example.txt # All required environment variables with defaults ├── package.json └── tsconfig.json ``` ## 前置条件 - **Node.js** v20+ - **PostgreSQL** 数据库(本地或托管) - **Redis** 服务器(本地 Docker 或托管) - **SMTP 凭证**(例如 Gmail 应用密码) ## 设置 ### 1. 克隆 & 安装 ``` git clone https://github.com/M-Uzair-dev/Authetication-Template.git cd Authetication-Template npm install ``` ### 2. 环境变量 ``` cp env_example.txt .env ``` 填写所有值: | 变量 | 描述 | 默认值 | |---|---|---| | `DATABASE_URL` | PostgreSQL 连接字符串 | — | | `ACCESS_TOKEN_SECRET` | 用于访问令牌的 JWT 签名密钥 | — | | `ACCESS_TOKEN_EXPIRY` | 访问令牌有效期(**毫秒**) | `900000` (15 分钟) | | `REFRESH_TOKEN_SECRET` | 用于刷新令牌的 JWT 签名密钥 | — | | `REFRESH_TOKEN_EXPIRY` | 刷新令牌有效期(**毫秒**) | `604800000` (7 天) | | `RESET_TOKEN_SECRET` | 用于密码重置令牌的 JWT 签名密钥 | — | | `RESET_TOKEN_EXPIRY` | 重置令牌有效期(**毫秒**) | `1800000` (30 分钟) | | `VERIFICATION_TOKEN_SECRET` | 用于邮箱验证令牌的 JWT 签名密钥 | — | | `VERIFICATION_TOKEN_EXPIRY` | 验证令牌有效期(**毫秒**) | `172800000` (2 天) | | `MAIL_HOST` | SMTP 主机 | `smtp.gmail.com` | | `MAIL_PORT` | SMTP 端口 | `587` | | `MAIL_USER` | SMTP 用户名 / 发件人地址 | — | | `MAIL_PASS` | SMTP 密码或应用密码 | — | | `REDIS_HOST` | Redis 主机 | `127.0.0.1` | | `REDIS_PORT` | Redis 端口 | `6379` | | `FRONTEND_URL` | 前端基础 URL(用于邮件链接) | — | ### 3. Redis ``` # 首次运行 — 下载 image 并启动 container docker run -d --name redis-server -p 6379:6379 redis # 后续启动 docker start redis-server ``` ### 4. 数据库 ``` # 应用 migrations npx prisma migrate deploy # 开发期间重置 npx prisma migrate reset # 打开 Prisma Studio (GUI) npx prisma studio ``` ### 5. 运行 ``` # 开发 (TypeScript watch + nodemon) npm run dev # 生产环境 npm run build npm start ``` 服务器在 `PORT`(默认 `5000`)上启动。 ## API 所有 14 个端点的完整请求/响应文档位于 **[API_ROUTES.md](API_ROUTES.md)**。 ### 路由概览 | 方法 | 路径 | 认证 | 描述 | |---|---|---|---| | `POST` | `/auth/signup` | — | 注册新账户 | | `POST` | `/auth/login` | — | 使用邮箱 + 密码登录 | | `POST` | `/auth/forgotPassword` | — | 发送密码重置邮件 | | `POST` | `/auth/resetPassword` | — | 通过令牌重置密码 | | `POST` | `/auth/verifyEmail` | — | 通过令牌验证邮箱 | | `POST` | `/auth/resendVerificationEmail` | — | 重发验证邮件 | | `POST` | `/auth/logout` | 是 | 登出当前设备 | | `POST` | `/auth/logout-all` | 是 | 登出所有设备 | | `POST` | `/auth/get-access-token` | — | 使用刷新 cookie 轮换令牌 | | `GET` | `/user/me` | 是 | 获取当前用户 | | `PATCH` | `/user/me` | 是 | 更新当前用户 | | `DELETE` | `/user/me` | 是 | 删除账户 | | `GET` | `/user/sessions` | 是 | 列出所有活跃会话 | | `POST` | `/user/revoke-session` | 是 | 撤销特定会话 | ### Postman 将仓库根目录下的 `postman-collection.json` 导入 Postman。将 `{{baseUrl}}` 变量设置为 `http://localhost:5000`。 ## 架构 ### 令牌流程 ``` Login / Signup └─ generateTokens() ├─ Signs access JWT { id, email, tokenId } (15 min) ├─ Signs refresh JWT { id, email, tokenId } (7 days) └─ Upserts refresh token hash into Token table (keyed on userId + device) → Both set as httpOnly cookies Authenticated request └─ verifyUser middleware ├─ Verifies access token signature ├─ Checks Redis for revoked-{tokenId} key └─ Sets req.userId, records last-active-{tokenId} in Redis (TTL: 7 days) Access token expired → client calls POST /auth/get-access-token └─ Verifies refresh token ├─ tokenId not in DB → wipe ALL sessions (theft detected) └─ Rotate: delete old record, mint new access + refresh pair Logout └─ Deletes refresh token from DB └─ Sets revoked-{tokenId} in Redis (TTL: 30 min) for instant revocation ``` ### 速率限制 | 限制器 | 应用于 | 限制 | |---|---|---| | `generalLimiter` | 所有路由 | 每 IP 60 秒内 100 次请求 | | `strictAuthLimiter` | login, signup, resetPassword, verifyEmail, logout, logout-all, get-access-token | 每 IP 5 分钟内 10 次请求 | | `stricterEmailLimiter` | forgotPassword, resendVerificationEmail | 每 IP 5 分钟内 3 次请求 | 通过 Redis 有序集合滑动窗口实现 —— 可在多个服务器实例间正确工作。 ### 邮件队列 - 通过 BullMQ 异步分发任务(并发数:5) - 3 次重试尝试,从 5 秒开始的指数退避 - 最终失败时:从数据库中删除孤立的令牌记录 - 触发条件:signup (验证), login (警报), forgot password (重置链接) ### 数据库模式 **User** — `id`, `name`, `email` (唯一), `password` (bcrypt), `emailVerified`, `createdAt`, `updatedAt` **Token** — `id`, `userId` (外键级联), `type` (EMAIL_VERIFICATION | PASSWORD_RESET | REFRESH_TOKEN), `tokenHash` (JWT 的 SHA-256), `device`, `deviceName`, `lastActive`, `expiresAt`, `createdAt` 索引:`userId`, `tokenHash`, 唯一 `(userId, device, type)` ## CORS 为 `http://localhost:3000` 配置,并启用 `credentials: true`。在部署之前,更新 `src/index.ts` 以从 `process.env.FRONTEND_URL` 读取 origin。 ## 许可证 ISC
标签:BullMQ, Express, GNU通用公共许可证, JWT, MITM代理, Modbus, Node.js, Nodemailer, PostgreSQL, Prisma, Redis, Syscall, TypeScript, Web开发, Zod, 企业级, 会话管理, 双Token, 后台, 多设备登录, 安全, 安全插件, 异步任务, 搜索引擎查询, 权限校验, 模板, 测试用例, 自动化攻击, 超时处理, 防盗刷