Express
使用统一中间件保护 Node.js API
Express 使用 @iwish/auth-sdk/express 验证 App session。Adapter 只信任 IWish Auth 的 session introspection,不读取 x-iwish-user-id、x-role 或其他调用方可伪造 Header。
1. 创建中间件
import { createIWishExpressAuth } from "@iwish/auth-sdk/express";
export const iwishAuth = createIWishExpressAuth({
apiUrl: process.env.IWISH_AUTH_API_URL!,
appKey: process.env.IWISH_AUTH_APP_KEY!,
sessionCookieName: "iwish_app_session",
sessionCacheTtlMs: 5_000
});
登录和 callback 可以使用 TypeScript SDK 的 buildAuthorizeUrl、createPkcePair、createSsoState 和 exchangeAuthorizationCode,也可以由现有服务端 OAuth controller 封装。
2. 中间件顺序
app.get(
"/api/reports",
iwishAuth.requireAuth(),
iwishAuth.requireAppAccess(),
iwishAuth.requirePermission("reporting.report.read"),
async (request, response) => {
const context = request.iwishAuth!.context;
response.json({
reports: await loadReports(context.user.id),
clientAssignments: context.clientAssignments
});
}
);
顺序不可调整:
requireAuth()从 Bearer token 或 App session cookie 读取 opaque token,并调用/v1/sso/session。requireAppAccess()确认 session 的app.appKey与当前服务配置一致。requirePermission()检查当前 App 命名空间内的权限。
3. 类型扩展
SDK 提供 ExpressRequestLike。真实 Express 项目可以使用 declaration merging 把 iwishAuth 加到 Express.Request:
import type { AppSessionContext } from "@iwish/auth-sdk";
declare global {
namespace Express {
interface Request {
iwishAuth?: { context: AppSessionContext; token: string };
}
}
}
4. Cookie 与反向代理
- App session cookie 必须设置
HttpOnly、SameSite=Lax、Path=/。 - HTTPS 环境必须设置
Secure。 - 反向代理需要保留
Cookie或Authorization,但必须移除外部传入的内部身份 Header。 - 每个 App 使用独立 cookie 名称或独立域,避免 session 串用。
5. 错误处理
Adapter 默认返回 { "error": "<stable_code>" }。业务 App 可以在最外层统一记录 request id,但不要把 token、client secret 或 Auth API 响应详情写入日志。
6. 验收重点
- 伪造身份 Header 不改变
request.iwishAuth.context.user。 - 缺少 token 返回 401。
- 其他 App session 返回 403。
- 缺少权限或跨 App 权限返回 403。
- 角色撤销后,短 TTL 到期或强制刷新能立即反映权限变化。