IWish Auth开发者文档
V1 Alpha GitHub

Express

使用统一中间件保护 Node.js API

Express 使用 @iwish/auth-sdk/express 验证 App session。Adapter 只信任 IWish Auth 的 session introspection,不读取 x-iwish-user-idx-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 的 buildAuthorizeUrlcreatePkcePaircreateSsoStateexchangeAuthorizationCode,也可以由现有服务端 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
    });
  }
);

顺序不可调整:

  1. requireAuth() 从 Bearer token 或 App session cookie 读取 opaque token,并调用 /v1/sso/session
  2. requireAppAccess() 确认 session 的 app.appKey 与当前服务配置一致。
  3. 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 };
    }
  }
}
  • App session cookie 必须设置 HttpOnlySameSite=LaxPath=/
  • HTTPS 环境必须设置 Secure
  • 反向代理需要保留 CookieAuthorization,但必须移除外部传入的内部身份 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 到期或强制刷新能立即反映权限变化。