coreos/go-oidc (Go)Go
错误信息
oidc: expected audience "api-client" got ["web-client"]
coreos/go-oidc (Go) — IDTokenVerifier.Verify
含义
ID 令牌由正确的提供商签名,但其 `aud` 声明中不包含你在 `oidc.Config` 中配置的 `ClientID`。go-oidc 实现了 OpenID Connect 的规则:ID 令牌只对签发时指定的客户端有效;第一个带引号的值是你的 `ClientID`,列表则是令牌的受众。
原因
转发了另一个客户端的 ID 令牌
常见前端把自己的 ID 令牌发送给后端 API,后端 API 用自己的客户端 ID 验证它。ID 令牌是给请求它的客户端用的;API 应该接收访问令牌。
配置的客户端 ID 有误
常见复制了另一个应用注册或另一个环境的客户端 ID,或者误把客户端密钥的名称当作 ID。令牌的 `aud` 显示了正确的值。
把访问令牌当作 ID 令牌来验证
偶见JWT 访问令牌的 `aud` 中携带的是 API 的标识符,而不是客户端 ID。`IDTokenVerifier` 默认检查客户端 ID,因此除非你自己检查受众,否则访问令牌的验证会失败。
修复方法
- 1.
使用让用户登录的那个应用的客户端 ID
对于 ID 令牌,准确配置令牌签发时指定的那个客户端 ID。
go verifier := provider.Verifier(&oidc.Config{ ClientID: os.Getenv("OIDC_CLIENT_ID"), // the client the user signed in to; must equal the token's aud }) idToken, err := verifier.Verify(ctx, rawIDToken) - 2.
对于 API 访问令牌,自行检查 API 受众
`SkipClientIDCheck` 只会禁用内置的客户端 ID 比较。要用针对你的 API 标识符的显式检查来替代它——切勿完全跳过受众校验。
go // Verifying a JWT access token for an API: check signature/issuer/expiry here, // then check the API audience yourself. verifier := provider.Verifier(&oidc.Config{SkipClientIDCheck: true}) tok, err := verifier.Verify(ctx, rawAccessToken) if err != nil { return err } if !slices.Contains(tok.Audience, "https://api.example.com") { return errors.New("token not issued for this API") }