Files
meida/docs/开发任务包/T10-华为登录代码先行.md
T
xsl e511b6a66f 收尾两批并行开发的文档回写与任务包
- Sprint 执行计划 v1.1:§1.1 补第一批交付实据;T9 SPIKE 结论回写 Sprint 1 表
  (T-P0-16 通过 2.8ms;T-P0-12 有条件;T-P0-10 原型 6/6 + 真实照片重验前置);
  Sprint 2 表标注 T-P2-01~06 交付;新增 §9 两批交付记录
- 开发任务拆解 v1.5:交付回写 + 新风险登记(RTMPose 域差异、BiRefNet 异步化)
- 新增 开发任务包/:三批多 agent 并行的协作规程与 14 份任务契约
- 新增 前置开通清单-云资源与资质.md
- 清理已用毕的评审报告(文档评审 2026-08-13、项目整体评审 2026-08-14),
  README 中相应引用改为留痕表述
2026-08-14 21:07:20 +08:00

5.7 KiB
Raw Blame History

T10 · 登录·华为账号(代码先行,联调后置)

对应任务:T-P1-12 | 需求:FR-ACC-01(登录成功率 ≥99%、UnionID 映射唯一、首次自动建用户)| 分支:task/t10-auth-huawei | worktree:/home/xsl/meida_backend-t10 先读《README.md(协作规程)》,遵守全部纪律。

1. 目标

实现 POST /auth/huawei:客户端传华为 Account Kit 签发的 id_token,服务端按 OIDC 标准做 JWKS 验签 + claims 校验,映射到内部用户并签发双令牌(access + refresh,复用 T4 已交付的 issue_session)。

本任务性质是"代码先行":华为 AGC 后台尚未配置(见《前置开通清单》§3),因此真实联调后置;全部逻辑用自造 RSA 密钥对 + 本地 JWKS 做单测/集成,凭证到位后只改 .env 即可上线。

2. 已就绪的契约(协调提交已提供)

配置(config.py 已加)

huawei_jwks_url: str = "https://oauth-login.cloud.huawei.com/oauth2/v3/certs"  # HUAWEI_JWKS_URL
huawei_audience: str = ""      # HUAWEI_AUDIENCE,= AGC App ID,联调时填
huawei_issuer: str = "https://accounts.huawei.com"  # HUAWEI_ISSUER(以 Account Kit 文档为准,可配)
huawei_jwks_cache_seconds: int = 86400

可复用的现有设施(先读再写)

  • packages/identity/service.py:get_or_create_by_external_identity(provider, union_id, open_id, register_source)(T4 已有);issue_session(user_id) -> SessionIssued(T4 交付,含 refresh 轮换结构)。
  • packages/shared/security.py:create_access_token(...)(HS256 access)。
  • packages/identity/schemas.py:TokenPairResponse(T4 交付)——直接复用,不要在本任务重复定义。
  • pyjwt[crypto] 已装(含 cryptography,RS256 验签可用)。

端点归属

apps/api/routers/auth.py 归你(T4 已合并完,本批无他人碰它)。apps/api/routers/auth_sms.py 归 T11,禁碰。

3. 实现要点

允许改动:packages/identity/huawei.py(新建,核心逻辑全在此)、apps/api/routers/auth.py(追加端点)、测试文件。不改 identity/service.py 与 identity/schemas.py(避免与 T11 冲突——你的模型定义在 huawei.py 内)。

  1. packages/identity/huawei.py:
    • HuaweiIdTokenVerifier:构造参数 (jwks_url, audience, issuer, cache_seconds, *, http_fetch=None, now=None)——http_fetch 是 Callable[[str], Awaitable[str]](单测注入本地 JWKS,不连外网);JWKS 内存缓存(TTL 按配置,kid 变化时强制刷新一次并重试验签);
    • verify(id_token) -> HuaweiClaims(frozen dataclass:union_id/open_id/exp/iat):RS256 验签(jwt.decode + PyJWK/手工 kid 匹配)、aud(等于配置 audience,空配置时拒绝而不是跳过——联调前后都必须严格)、iss、exp/iat、union_id 缺失拒绝(华为子账号场景无 union_id 时降级用 open_id 的策略不做,注释说明留给联调期决定);
    • 错误映射:验签失败/claims 不符 → AppError(TOKEN_INVALID)(40102,已有);JWKS 拉取失败 → AppError(UPSTREAM_ERROR)(60000,已有)——不需要新错误码。
  2. 路由(auth.py 追加):
    @router.post("/huawei", summary="华为账号授权登录(FR-ACC-01)")
    async def huawei_login(payload: HuaweiLoginRequest, ...) -> ...:
        claims = await verifier.verify(payload.id_token)
        user = await identity.get_or_create_by_external_identity(
            provider="huawei", union_id=claims.union_id, open_id=claims.open_id,
            register_source="huawei")
        issued = await identity.issue_session(user.user_id)
        access = create_access_token(...)
        return ok(TokenPairResponse(...))   # 复用 T4 模型
    
    • verifier 用依赖注入(路由模块内建一个 get_huawei_verifier 的 FastAPI Depends,从 settings 构造并缓存到 app.state 或模块级 lru——不改 deps.py,在 auth.py 内实现);
    • HuaweiLoginRequest(id_token: str) 定义在 huawei.py。
  3. 模块 docstring 写明:真实联调前置 = AGC 应用创建 + 证书指纹双套 + HUAWEI_AUDIENCE 填 App ID(引用《前置开通清单》§3)。

4. 测试要求

  • 单测 tests/unit/test_huawei_verifier.py:测试内用 cryptography 生成 RSA 密钥对、自签 id_token + 本地 JWKS dict:
    1. 合法 token → claims 解析正确;
    2. 错误签名(换密钥)→ 40102;过期 → 40101(复用 TOKEN_EXPIRED);aud 不符 → 40102;audience 未配置 → 40102;
    3. JWKS 拉取失败 → 60000;kid 轮换 → 缓存刷新后验签成功。
  • 集成 tests/integration/test_auth_huawei.py(新文件):monkeypatch 注入 FakeFetcher(本地 JWKS)→ POST /v1/auth/huawei → 200 双令牌;再次登录同 union_id → 同一 user_id(映射唯一);新 access 可调 GET /v1/quota。

5. 禁改清单

通用禁改之外:packages/identity/{service,repo,schemas,tokens}.py、apps/api/routers/auth_sms.py、packages/{kb,rules,retrieval}/**。

6. 验收标准(FR-ACC-01)

  1. 验签逻辑完整(签名/aud/iss/exp/iat 全查),audience 未配置时拒绝启动校验路径;
  2. UnionID→内部 user_id 映射唯一,首次登录自动建用户(集成断言同 ID 复登);
  3. 全链路不连外网(FakeFetcher 注入);
  4. 全部检查绿(mypy 范围同 T6 列表)。

7. 提交信息

feat(identity): Huawei Account Kit login via OIDC JWKS verification

POST /auth/huawei:JWKS 验签(kid 缓存/轮换)+ claims 严格校验 +
UnionID 映射 + T4 双令牌签发(FR-ACC-01;真实联调待 AGC 配置)。

偏差说明:<如有写在这里,无则写"无">