快速开始
完成统一登录、上下文与 App 本地授权接入
快速开始
本指南用于把一个有服务端的业务 App 接入 IWish Auth。接入完成后,内部员工使用飞书统一登录,外部账号使用邀请和邮箱密码登录;业务 App 获得稳定的 iwish_auth_user_id、员工目录和客户项目上下文。业务 App 的成员、角色、页面动作和数据范围仍由业务 App 自己管理。
浏览器不能持有 Client Secret,也不能直接交换授权码。登录、callback、App Session Cookie 和服务端授权都必须在业务 App 服务端完成。
1. 选择接入档案
- 新应用且没有需要保留的生产账号、身份外键和旧 Session:选择
greenfield,阅读新应用接入。 - 已有生产用户、角色、业务外键和历史数据:选择
legacy-migration,阅读存量账号迁移。
greenfield 不生成迁移计划或 mapping ledger。legacy-migration 不允许首次登录自动创建空账号,也不允许运行期按邮箱关联。
2. 管理员准备
管理员在 Auth Admin 完成应用注册、组织开通、OAuth Client 和精确回调地址配置。Client Secret 只显示一次,应保存到 staging 或 production 的 Secret 管理中,不得写入仓库、前端变量或聊天记录。
3. 创建 Manifest 2.0
{
"$schema": "https://auth-docs-staging.iwishapp.cn/auth-manifest.schema.json",
"schemaVersion": "2.0",
"appKey": "reporting",
"name": "数据报表",
"description": "跨境电商数据报表系统",
"appUrl": "https://reporting-staging.example.com",
"environment": "staging",
"manifestVersion": "2026.07.22-1",
"authorizationMode": "application_owned",
"requiredContext": ["identity", "employee", "departments", "clientAssignments"]
}
Manifest 只声明应用元数据和需要的 Auth 上下文,不声明业务 roles 或 permissions。通过 CLI 先执行 validate,确认差异后再执行 sync。
4. 接入登录与 Session
使用官方 SDK 实现 /auth/login、/auth/callback 和 /auth/logout。SDK 使用 PKCE,callback 在服务端交换一次性 code,并把 opaque App Session 写入 HttpOnly、SameSite=Lax Cookie。每个受保护请求调用 requireAppAccess;它会验证 session 有效、组织和 App 已启用、员工没有离职,以及 session 确实属于当前 appKey。
export async function GET(request: Request) {
const session = await auth.requireAppAccess(request);
const member = await localMembers.findByAuthUserId(session.user.id);
if (!member || member.status !== "active") {
return Response.json({ error: "local_member_required" }, { status: 403 });
}
await localAuthorization.require(member, "report.read");
return Response.json({ user: session.user, projects: session.clientAssignments });
}
5. 建立本地授权
业务 App 使用 session.user.id 作为 iwish_auth_user_id,建立本地成员记录并分配本地角色。greenfield App 由管理员从 Auth 受控目录选择身份,不能手工复制 User ID,也不能在第一次登录时自动授予 admin/viewer。legacy-migration App 则必须在切换前把 Auth User ID 预绑定到原本地成员。无本地成员、成员停用、无角色或权限不足时一律返回 403。前端隐藏按钮只是体验优化,不能代替服务端检查。clientAssignments 可以用于预选客户项目或缩小查询范围,但它不是权限凭证,不能自动授予全量数据。
6. 验收
至少验证:无本地成员 403、角色不足 403、跨 App session 401/403、回调地址不匹配失败、Client Secret 不出现在浏览器、飞书离职后旧 session 被拒绝、外部邮箱账号可登录但仍需要 App 本地成员和角色。接入不得直接调用飞书、Supabase Auth 或 Auth 数据库。