---
title: OIDC 排错
description: 排查 OIDC 授权、令牌兑换、刷新和注册错误。
editUrl: true
head: []
template: doc
sidebar:
  order: 6
  hidden: false
  attrs: {}
pagefind: true
draft: false
---

先确定失败的端点，再修改客户端配置。记录 HTTP 状态、协议 `error`、时间，以及响应提供的请求关联信息。不要记录授权码、JWT、客户端密钥、IAT、RAT 或回调请求体。

## 授权错误

提供方验证回调地址后，会将授权错误返回到该地址，携带 `error`、`error_description`、请求提供的 `state` 和 `iss`。处理响应前，验证 `state`，并将 `iss` 与本次请求保存的 issuer 精确比较。回调地址验证之前的错误直接返回 JSON。

| 错误 | 检查内容 | 恢复方法 |
|---|---|---|
| `invalid_client` | `client_id` 是否正确，应用是否已启用，是否配置 OIDC。 | 修正注册，或由具备权限的 OWNER 启用应用。 |
| `invalid_request` | 精确回调 URI、必填字段、重复参数、nonce、PKCE 和支持的 `prompt` 组合。 | 修正请求，重新发起授权。 |
| `unsupported_response_type` | 提供方不支持所请求的响应类型。 | 选择 discovery 已公布且客户端允许的类型。 |
| `access_denied` | 授权或当前账户准入失败。 | 检查返回原因和应用准入规则，不要循环静默重试。 |
| `unauthorized_client` | 客户端是否启用该响应类型及所需 grant。 | 让 OWNER 检查 OIDC 返回规则。 |
| `invalid_scope` | 请求的 scope 是否受支持且在客户端允许范围内。 | 缩小 scope 或更新获准的客户端配置。 |
| `login_required` | `prompt=none` 是否缺少可复用的登录。 | 用户准备好后，发起交互式授权。 |
| `consent_required` | 静默授权是否需要用户同意。 | 发起交互式授权，收集用户同意。 |
| `interaction_required` | 必填账户资料是否需要浏览器交互。 | 让用户完成交互式流程。 |
| `invalid_request_object` | RS256 偏好、所选公钥、JWT 字段、签名和时间声明。 | 修正签名对象，创建新的请求。 |
| `invalid_request_uri` | 允许的引用、精确 URI、HTTPS 访问和文档可用性。 | 修正引用，或直接提交签名对象。 |
| `server_error` | 暂时性的提供方故障。 | 让用户重试，不要缓存错误响应。 |

使用 `form_post` 时，确认回调接受跨站表单 POST。如果缺少关联 Cookie，检查 `SameSite=None; Secure`。无法验证本次请求的 state 时，拒绝回调。

## 令牌兑换和刷新

`/token` 请求使用 `application/x-www-form-urlencoded`。只使用一种客户端认证方式。保留本次授权的精确回调 URI 和 PKCE verifier。

| 错误 | 常见原因 | 恢复方法 |
|---|---|---|
| `invalid_request` | Content-Type 错误、重复字段或缺少表单值。 | 修正表单，不要混用认证方式并重复发送凭据字段。 |
| `invalid_client` | 密钥错误；assertion 的 `iss`、`sub`、`aud` 不匹配；assertion 到期或重用；RP `kid` 缺失或不匹配。 | 检查认证方式和密钥来源。使用全新 `jti` 创建新的 assertion。 |
| `unauthorized_client` | 所请求 grant 已停用。 | 让 OWNER 检查允许的 grant。 |
| `unsupported_grant_type` | 端点不支持所提供的 grant。 | 按需使用 `authorization_code` 或 `refresh_token`。 |
| `invalid_grant` | 授权码到期、已兑换或不匹配；verifier 错误；刷新会话已撤销；刷新 scope 冲突。 | 重新发起授权，不要持续重放同一个授权码或旧 refresh token。 |
| `invalid_scope` | 刷新试图恢复已从会话移除的 scope。 | 使用当前已授权 scope 的子集，或重新授权以获取更大的范围。 |

通过客户端认证的授权码重放可能撤销对应会话。按顺序执行刷新，并保存每次返回的替换 refresh token。移除 `offline_access` 后没有 `refresh_token`、移除 `openid` 后没有 `id_token`，都是预期结果。

OIDC 令牌通过 `/token` 刷新，不使用 Session `/refresh`。见[刷新规则](/zh-cn/oidc/flow/#4-refresh)。

## UserInfo 和声明状态

通过 Bearer header 或支持的表单字段发送 access token，只选择一种传递方式。不接受查询参数中的 token 或重复传递。

收到 `invalid_token` 时，检查到期时间、issuer、客户端和会话是否可用，以及令牌是否属于该 OIDC 流程。预期声明缺失时，检查 scope、应用策略和当前用户授权。只有 `openid` 的声明状态请求会返回空 `claims` 对象。

ID Token 不能用作 UserInfo 的 access token。Access token 使用应用的 Session JWKS；ID Token 和签名 UserInfo 使用提供方 JWKS。见[令牌验证](/zh-cn/concepts/tokens-and-verification/)。

## 注册错误

| 结果 | 检查内容 | 恢复方法 |
|---|---|---|
| HTTP 400 `invalid_client_metadata` | 元数据类型、算法、scope/grant、公钥和命名策略。 | 修正 JSON，保持在 IAT 允许范围内。 |
| HTTP 400 `invalid_redirect_uri` | URI 语法、应用类型、主机归属审批和 sector 文档。 | 修正回调与主机审批。 |
| HTTP 401 `invalid_token` | IAT/RAT 到期、撤销、配额和当前组织权限。 | 让 OWNER 检查或替换对应凭据。 |
| 注册读取或删除返回 HTTP 403 | RAT 属于另一个客户端。 | 使用目标客户端的 RAT 和返回的 `registration_client_uri`。 |

`POST /register` 的网络结果未知时，先在 With 检查已创建的客户端，再决定是否重复请求。新请求可能再次消耗配额。

## 联系支持

提供端点、带时区的时间、HTTP 状态、协议错误和响应提供的请求标识。说明响应类型、认证方式和失败步骤。移除机密值和个人数据。通过 [Sudomimus 支持](https://sudomimus.com/zh-CN/help-center/)提交请求。

## 相关文档

- [OIDC 流程](/zh-cn/oidc/flow/)
- [IAT 与 RAT 管理](/zh-cn/oidc/registration-access/)
- [RP 密钥](/zh-cn/oidc/relying-party-keys/)