@ access-tokens/ 表达
使用OAuth 2.0相容的JWT令牌交换进行个人访问Token(PAT)认证的快道和中间软件.
特征
- 准备使用路线: 预建的认证和管理令牌管理端点
- JWT 托肯交换: OAuth 2.0相容的 PAT 至 JWT 交换符号端点
- 表达式中件数字 :
requireJwt, (中文(简体) ),requireAdmin,以及requireRole用于路由保护的中间软件 - JOSE 整合工业标准JWT签署和核查
- 类型脚本: 带有Express请求增强功能的全类型安全
- 弹性配置: 自定义路径、符号寿命和密钥管理
安装
npm install @access-tokens/express @access-tokens/core
快速启动
import express from "express";
import { DynamoDBPat } from "@access-tokens/core";
import {
createAuthRouter,
createAdminTokensRouter,
createRequireJwt,
createRequireAdmin,
createRequireRole,
buildSignerVerifier,
generateKeySet,
} from "@access-tokens/express";
import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
const app = express();
app.use(express.json());
// Initialize DynamoDB
const dynamoClient = new DynamoDBClient({ region: "us-east-1" });
const docClient = DynamoDBDocumentClient.from(dynamoClient);
const pat = new DynamoDBPat({ tableName: "tokens", docClient });
// Generate JWT signing keys
const keySet = await generateKeySet("my-key-id-1");
const signerVerifier = await buildSignerVerifier({
keySet,
issuer: "my-app",
ttl: "1h",
});
// Add authentication and token admin routes
app.use("/auth", createAuthRouter({ pat, signerVerifier }));
app.use("/admin", createAdminTokensRouter({ pat, signerVerifier }));
const requireJwt = createRequireJwt({ signerVerifier });
const requireAdmin = createRequireAdmin();
const requireEditor = createRequireRole({ role: "editor" });
// Your protected routes
app.get("/api/data", requireJwt, (req, res) => {
res.json({
message: "User data",
user: req.user, // { sub, owner, admin, roles }
});
});
app.get("/api/admin/data", requireJwt, requireAdmin, (req, res) => {
res.json({
message: "Admin data",
user: req.user, // { sub, owner, admin, roles }
});
});
app.put("/api/content", requireJwt, requireEditor, (req, res) => {
res.json({
message: "Content updated",
user: req.user, // { sub, owner, admin, roles }
});
});
app.listen(3000, () => console.log("Server running on port 3000"));
API 参考
路线
createAuthRouter(options)
创建带有认证端点的Express路由器.
选项 :
{
pat: DynamoDBPat; // DynamoDBPat instance
signerVerifier: JwtSignerVerifier; // JWT signer/verifier from buildSignerVerifier()
logger?: pino.Logger; // Optional logger
}
说明: JWT 寿命配置于 buildSignerVerifier()。 。 。 .
终点 :
-
POST /token- JWT交换 PAT(OAuth 2.0标志终点)请求正文 :
{ grant_type?: "client_credentials"; // Optional, must be "client_credentials" if provided client_secret?: string; // PAT (for OAuth 2.0 client_secret_post method) client_id?: string; // Optional, accepted but not used state?: string; // Optional, echoed back in response }认证方法 (按此顺序排列):
- 主体参数 (第2.0号)
client_secret_post: 包含client_secret请求机构 - 基本认证 (第2.0号)
client_secret_basic编号: 使用Authorization: Basic <base64>页眉(格式:Basic base64(":<token>")(中文(简体) ) - 借记符: 使用
Authorization: Bearer <token>标题
回应:
{ "access_token": "eyJ...", // The signed JWT "token_type": "Bearer", // Always "Bearer" "expires_in": 3600, // JWT lifetime in seconds "state": "..." // Optional, echoed from request } - 主体参数 (第2.0号)
实例:
# Method 1: Body parameter (client_secret_post)
curl -X POST http://localhost:3000/auth/token \
-H "Content-Type: application/json" \
-d '{"grant_type":"client_credentials","client_secret":"pat_abc123..."}'
# Method 2: Basic authentication (client_secret_basic)
curl -X POST http://localhost:3000/auth/token \
-H "Authorization: Basic $(echo -n ":pat_abc123..." | base64)"
# Method 3: Bearer token (non-OAuth)
curl -X POST http://localhost:3000/auth/token \
-H "Authorization: Bearer pat_abc123..."
createAdminTokensRouter(options)
创建带有管理令牌管理端点的快递路由器。 需要 JWT 认证和管理员权限 .
选项 :
{
pat: DynamoDBPat; // DynamoDBPat instance
signerVerifier: JwtSignerVerifier; // JWT signer/verifier
logger?: pino.Logger; // Optional logger
}
终点 :
-
GET /tokens- 列表符号- 查询参数 :
afterTokenId, (中文(简体) ),limit, (中文(简体) ),includeRevoked, (中文(简体) ),includeExpired, (中文(简体) ),includeSecretPhc, (中文(简体) ),hasRole - 回应:
{ "records": [...] }
- 查询参数 :
-
POST /tokens- 发个新令牌- 请求正文 :
{ "owner": "[email protected]", "isAdmin"?: false, "roles"?: ["reader"], "tokenId"?: "...", "expiresAt"?: 1234567890 } - 回应:
{ "token": "pat_...", "record": {...} }
- 请求正文 :
-
PUT /tokens/:tokenId- 登记预先生成的代号- 请求正文 :
{ "secretPhc": "...", "owner": "...", "isAdmin"?: false, "roles"?: ["reader"], "expiresAt"?: 1234567890 } - 回应:
{ "record": {...} }
- 请求正文 :
-
PATCH /tokens/:tokenId- 更新符号- 请求正文 :
{ "owner"?: "...", "isAdmin"?: true, "secretPhc"?: "...", "roles"?: ..., "expiresAt"?: 1234567890 } - 角色更新语法 :
{ "roles": ["role1", "role2"] } // Replace all roles { "roles": { "add": ["admin"] } } // Atomic add (cannot combine with remove) { "roles": { "remove": ["guest"] } } // Atomic remove (cannot combine with add) - 回应: 204 无内容
- 请求正文 :
-
PUT /tokens/:tokenId/revoke- 撤销证书- 请求正文 :
{ "expiresAt"?: 1234567890 }(可选) - 回应: 204 无内容
- 请求正文 :
-
PUT /tokens/:tokenId/restore- 恢复已撤销的代号- 回应: 204 无内容
-
POST /tokens/batch- 批量取回代币- 请求正文 :
{ "tokenIds": ["id1", "id2"], "includeSecretPhc"?: false } - 回应:
{ "found": [...], "missing": [...] }
- 请求正文 :
说明: 所有端点都需要JWT认证和管理员权限. 他们
使用情况 requireJwt 财务报告和审定财务报表 requireAdmin 内部中间软件.
中间软件
createRequireJwt(options)
创建验证 JWT 令牌和插件的中间软件 req.user。 。 。 .
选项 :
{
signerVerifier: JwtSignerVerifier; // JWT signer/verifier from buildSignerVerifier()
logger?: pino.Logger; // Optional logger
}
请求扩展 :
req.user = {
sub: string; // Token ID
owner: string; // Token owner
admin: boolean; // Admin status
roles: string[]; // Array of role strings
};
说明: 这个 roles 阵列取自JWT有效载荷并反映了JWT发行时赋予标志的作用.
用法 :
const requireJwt = createRequireJwt({ signerVerifier });
app.get("/protected", requireJwt, (req, res) => {
console.log("User:", req.user?.owner);
res.json({ data: "secret" });
});
createRequireAdmin(options?)
创建需要的中间软件 req.user.admin 将会是 true。必须在 requireJwt。 。 。 .
选项 :
{
logger?: pino.Logger; // Optional logger
}
用法 :
const requireAdmin = createRequireAdmin();
app.delete("/users/:id", requireJwt, requireAdmin, (req, res) => {
// Only admin users can access this
res.json({ success: true });
});
createRequireRole(options)
创建需要的中间软件 req.user.roles 包括具体的作用。 必须在之后使用 requireJwt。 。 。 .
选项 :
{
role: string; // Required role name
logger?: pino.Logger; // Optional logger
}
用法 :
const requireEditor = createRequireRole({ role: "editor" });
app.put("/content/:id", requireJwt, requireEditor, (req, res) => {
// Only users with "editor" role can access this
res.json({ success: true });
});
JWT 公用事业
generateKeySet(kid: string, algorithm?: "EdDSA" | "RS256")
为 JWT 签名生成一个新的不对称密钥集.
参数:
kid: string- 密钥ID( 需要) - 此密钥集的独有标识符algorithm?: "EdDSA" | "RS256"- 签名算法( 默认: “ EdDSA ”)
回返情况:
{
active_kid: string; // The active key ID
private_keys: JWK[]; // Array of private keys in JWK format
public_keys: JWK[]; // Array of public keys in JWK format
}
示例
const keySet = await generateKeySet("my-key-id-1");
// or with specific algorithm
const rsaKeySet = await generateKeySet("rsa-key-1", "RS256");
说明: 安全存储密钥( 如 AWS 密钥管理器, 环境变量) 。 生成一次再用.
buildSignerVerifier(config)
从密钥集创建 JWT 签名和验证器.
配置 :
{
keySet: KeySet; // From generateKeySet()
issuer: string; // JWT issuer claim
ttl: string; // Token time-to-live (e.g., "1h", "30m")
}
回返情况:
JwtSignerVerifier {
sign: (claims) => Promise<string>;
verify: (jws: string) => Promise<JWTVerifyResult>;
jwks: { keys: readonly JWK[] };
}
示例
const keySet = await generateKeySet("my-key-id");
const signerVerifier = await buildSignerVerifier({
keySet,
issuer: "my-app",
ttl: "1h",
});
OAuth 2.0 流量
此库执行一个简化的 OAuth 2. 0 客户端证书流 :
- 客户端认证 将 PAT 改为
POST /auth/token - 服务器验证 PAT和发行寿命短的JWT(默认:1小时)
- 客户端使用 JWT 用于通过
Authorization: Bearer <jwt> - 服务器验证 JWT 使用
requireJwt中间软件
为什么是JWT交换?
- 业绩: 避免对每次请求进行DynamoDB检查并进行尖叫
- 可缩放性: 无国籍的JWT核查
- 短寿: JWT 受损的风险降低
- 标准: OAuth 2.0 兼容
安保最佳做法
- 使用 HTTPS - 生产时始终使用TLS
- 安全密钥存储 - 将私人钥匙存放在安全金库(AWS保密管理器等)
- 短JWT( 短JWT) 终身 - 建议默认1小时
- 旋转密钥 - 实施长期服务的关键轮换
- 核证发行人/观众 - 在生产中配置这些
- 限制费率 - 增加税率限制
/auth/token结束点
密钥生成
使用包含的工具生成密钥 :
pnpm --filter @access-tokens/express genkey
或在方案方面:
import { generateKeySet } from "@access-tokens/express";
const keys = await generateKeySet("my-key-id-1");
console.log("Public Key:", keys.public_keys);
console.log("Private Key:", keys.private_keys);
安全存储这些密钥,并通过环境变量传递给您的应用程序 .
处理错误
所有端点返回标准的 HTTP 错误代码 :
400 Bad Request- 无效的请求正文或参数401 Unauthorized- 无效或缺失的符号403 Forbidden- 权限不足(不是管理员)404 Not Found- 没有找到托肯500 Internal Server Error- 服务器出错
示例错误响应 :
{
"error": "Invalid token",
"details": "Token has been revoked"
}
类型脚本
软件包扩展了Express类型 :
declare global {
namespace Express {
interface Request {
user?: {
sub: string; // Token ID
owner: string; // Token owner
admin: boolean; // Admin status
roles: string[]; // Array of role strings
};
logger?: Logger; // Optional Pino logger
clientIp?: string; // Optional client IP (from request-ip)
}
}
}
所需资源
- 节点.js 20+
- 捷运 4.18+或 5.0+
- @ access-tokens/ core (帮助)
相关软件包
- @ access-tokens/ core (帮助) - 核心符号管理库
- @ access-tokens/ 客户端 - PAT API的HTTP客户端
- @ access-tokens/cli (英语) - 命令行符号管理
许可证
公务员制度委员会 2025年贷款信贷有限公司.