错误处理与验收¶
区分“用户需要重新登录”“服务暂时不可用”和“应用配置错误”。不要把所有非 200 响应都转换成退出登录,也不要以失败为理由忽略签名、状态或权限校验。
常见结果¶
| 情况 | 处理方式 |
|---|---|
回调 access_denied |
核验 state 后结束事务,允许用户返回应用或主动再试,不循环跳转 |
invalid_request、invalid_scope、unauthorized_client |
检查请求与登记范围,记录应用诊断;不要改用密码直传等未批准 grant |
token endpoint invalid_client |
检查客户端认证、密钥、公钥和轮换状态,作为应用故障处理;不要因此让用户退出登录 |
token endpoint invalid_grant |
授权码或刷新凭据不再可用,结束对应事务/登录;不要重复使用旧授权码或刷新令牌 |
UserInfo 401 invalid_token |
当前访问凭据被拒;检查令牌有效期并尝试刷新,无法恢复时重新登录,不沿用旧资料授权 |
UserInfo 403 insufficient_scope |
当前 grant 无所需权限,不能通过刷新或换接口扩大范围 |
| 网络错误、502/503/504 | 保留当前凭据和用户输入,显示暂时不可用;只读请求可限制次数重试;不要删除账号或自动重复提交修改 |
429 |
尊重 Retry-After,限制请求频率,不并发绕过 |
| issuer/签名/audience/nonce/state 不符 | 拒绝当前登录或响应,保留不含敏感数据的诊断;不能回退到只解码不验签 |
错误正文可能是标准 OAuth JSON,也可能是网关 HTML。按 HTTP 状态与标准错误码分类,不把上游 HTML、堆栈或任意 error_description 直接显示给用户。协议端点通常使用 error,不要依赖其他 SAI 业务 API 的错误结构。
重试期间不把旧资料用于新的权限提升。登录验证结果不应改变应用自身的角色或封禁记录。
日志与排查¶
可记录时间、应用请求 ID、协议步骤、状态码和经过允许的错误码。不要记录密码、Cookie、Authorization 头、client assertion、授权码、访问/刷新/ID token、完整回调查询串或 UserInfo 全文。
需要 SAI 协助时,向 SAI 提供应用名、环境、发生时间、协议步骤和错误码。不要附带令牌或密钥。
上线检查¶
| 检查 | 应看到的结果 |
|---|---|
| 首次登录与已有 SSO | 同一应用回调;有效 SSO 不强制再次输入密码 |
| 拒绝授权 | 应用可恢复,不循环跳登录 |
| state/nonce/PKCE/回调错误 | 拒绝错误事务,不创建会话 |
| 授权码重复换取 | 第二次失败 |
| 不同应用 sector | 不同应用收到不同的用户标识;不能凭邮箱自动合并账号 |
| 资料未填写与 scope 缩减 | 缺少资料时不编造默认值;停止使用已撤回授权的字段 |
| 访问令牌先于应用 Cookie 到期 | 正常在线续期,新凭据替换旧凭据,绝对期限不被延长 |
| 刷新暂时失败 | 保留可恢复状态,不把服务故障说成用户退出 |
| SAI 登录过期或已退出 | 进入普通 OIDC 登录,确需认证时由 SAI 显示登录表单 |
| 撤销、退出与服务端退出通知 | 只失效对应会话,原应用返回地址正确,重复通知幂等 |
| 签名密钥轮换 | 依 Discovery/JWKS 正常更新,不关闭验签 |
规范与参考¶
- OpenID Connect Core 1.0
- OpenID Connect Discovery 1.0
- PKCE,RFC 7636
- OAuth JWT 客户端认证,RFC 7523
- OAuth Token Revocation,RFC 7009
- OAuth Token Introspection,RFC 7662
- RP-Initiated Logout 1.0
- Back-Channel Logout 1.0
- OAuth 2.0 Security Best Current Practice,RFC 9700
受控资源服务如需 token introspection,须另行批准客户端认证与用途。Discovery 公布该端点不代表普通应用获得任意令牌查询权。