--- title: "failed to get user information from the UserInfo endpoint, Code=[code] - 从 UserInfo Endpoint 获取用户信息失败并返回错误码" date: 2026-04-04 lastmod: 2026-04-04 description: "failed to get user information from the UserInfo endpoint, Code=[code] 表示 Elasticsearch 的 OIDC Realm 调用 UserInfo Endpoint 后收到错误响应,并从 WWW-Authenticate 头或状态码中提取到明确的错误码和描述,本文详解排查与修复方法。" tags: ["OIDC", "OpenID Connect", "UserInfo", "错误码", "WWW-Authenticate", "Bearer Token", "安全认证", "ElasticsearchSecurityException"] summary: "适用版本: 7.x-8.9 1. 错误异常的基本描述 # Failed to get user information from the UserInfo endpoint. Code=[...]; Description=[...] 表示 Elasticsearch 确实收到了 UserInfo Endpoint 的 HTTP 响应,但响应不是成功状态(非 2xx),并且还能提取出明确的错误码和描述。这类报错比通用的 UserInfo 失败更具体,因为它通常意味着身份提供方已经返回了可解释的认证或授权错误。 源码表明 Elasticsearch 会优先从 WWW-Authenticate 响应头解析 Bearer Token 错误;如果没有这个头,就回退到 HTTP 状态码和响应描述。 常见现象 # OIDC 登录失败,而且日志中会出现 invalid_token、insufficient_scope、invalid_request 等错误码。 身份提供方访问正常(网络连通性没问题),但 Elasticsearch 仍然拒绝完成登录。 相同 Realm 下,不同用户或不同 token 的行为可能不一致:有些用户能登录,有些不能。 在 Kibana 或其他依赖 OIDC 的应用中,用户看到登录失败页面,但没有明确的错误提示。 从 Elasticsearch 日志可以看到完整的错误码和描述,例如:Code=[401]; Description=[invalid_token]。 典型报错与异常栈 # 常见日志形态通常类似下面这样:" --- > **适用版本:** 7.x-8.9 ## 1. 错误异常的基本描述 `Failed to get user information from the UserInfo endpoint. Code=[...]; Description=[...]` 表示 Elasticsearch 确实收到了 UserInfo Endpoint 的 HTTP 响应,但响应不是成功状态(非 2xx),并且还能提取出明确的错误码和描述。这类报错比通用的 UserInfo 失败更具体,因为它通常意味着身份提供方已经返回了可解释的认证或授权错误。 源码表明 Elasticsearch 会优先从 `WWW-Authenticate` 响应头解析 Bearer Token 错误;如果没有这个头,就回退到 HTTP 状态码和响应描述。 ### 常见现象 - OIDC 登录失败,而且日志中会出现 `invalid_token`、`insufficient_scope`、`invalid_request` 等错误码。 - 身份提供方访问正常(网络连通性没问题),但 Elasticsearch 仍然拒绝完成登录。 - 相同 Realm 下,不同用户或不同 token 的行为可能不一致:有些用户能登录,有些不能。 - 在 Kibana 或其他依赖 OIDC 的应用中,用户看到登录失败页面,但没有明确的错误提示。 - 从 Elasticsearch 日志可以看到完整的错误码和描述,例如:`Code=[401]; Description=[invalid_token]`。 ### 典型报错与异常栈 常见日志形态通常类似下面这样: ```text ElasticsearchSecurityException: Failed to get user information from the UserInfo endpoint. Code=[401]; Description=[invalid_token] at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectRealm... ``` 或者 scope 不足: ```text ElasticsearchSecurityException: Failed to get user information from the UserInfo endpoint. Code=[403]; Description=[insufficient_scope] at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectRealm... ``` 或者从 HTTP 状态码提取: ```text ElasticsearchSecurityException: Failed to get user information from the UserInfo endpoint. Code=[400]; Description=[Bad Request] at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectRealm... ``` ## 2. 为什么会发生这个错误 `Failed to get user information from the UserInfo endpoint. Code=[...]` 的根因是"OIDC UserInfo Endpoint 返回了错误响应"。Elasticsearch 向 IdP 的 UserInfo Endpoint 发起请求后,IdP 返回了非 2xx 的 HTTP 状态码,并在 `WWW-Authenticate` 头或响应体中提供了错误详情。 常见原因通常包括: - **access token 已过期**:`access_token` 的有效期已过,IdP 返回 `invalid_token` 错误。 - **access token 无效**:`access_token` 格式错误、被篡改或不是由当前 IdP 签发的。 - **token 受众(audience)不匹配**:token 的 `aud` 声明与 IdP 预期的受众不一致。 - **scope 不足**:当前 token 没有访问 UserInfo Endpoint 所需的 `openid` 或 `profile` scope。 - **身份提供方要求额外认证条件**:如需要 MFA(多因素认证)、step-up authentication 等,但当前请求不满足。 - **反向代理或网关问题**:反向代理、SSO 网关或 WAF 重写了认证头,导致 Elasticsearch 拿到的是不完整或错误的认证信息。 - **时钟偏移(clock skew)**:Elasticsearch 节点与 IdP 之间的系统时钟不一致,导致 token 的 `iat`(签发时间)或 `exp`(过期时间)验证失败。 - **token 缓存问题**:客户端或中间件缓存了旧的、已失效的 token,并继续使用它访问 UserInfo Endpoint。 ## 3. 如何排查和解决这个异常和解决这个异常 建议按"先解读错误码、再检查 token、后排查网络"的顺序处理: 1. **解读错误码和描述**:直接查看日志里的 `Code` 和 `Description`,先按身份提供方错误语义定位。 ```bash # 查看 Elasticsearch 安全日志中的错误详情 grep -r "Failed to get user information from the UserInfo endpoint" /var/log/elasticsearch/ grep -r "Code=" /var/log/elasticsearch/ | tail -20 ``` 2. **检查 token 有效性**:确认 token 的 scope、audience、过期时间和签发流程是否符合 UserInfo 要求。 ```bash # 解码 JWT token(如果使用的是 JWT 格式的 access_token) echo "your_access_token" | cut -d'.' -f2 | base64 -d | jq . # 检查 token 的 exp(过期时间)、aud(受众)、scope 等声明 ``` 3. **对照身份提供方日志**:确认该请求为何返回了当前 HTTP 状态和认证头。 ```bash # 如果是 Keycloak,查看 Keycloak 日志 docker logs keycloak_container | grep -i "userinfo" # 如果是 Okta/Auth0,查看其管理控制台的事件日志 ``` 4. **检查中间代理**:检查反向代理、SSO 网关或 WAF 是否透传了 `Authorization` 与 `WWW-Authenticate` 相关头部。 ```bash # 检查代理配置(以 Nginx 为例) grep -r "proxy_set_header" /etc/nginx/ # 确认 Authorization 头没有被过滤 ``` 5. **检查时钟同步**:如果错误只在某些客户端或节点上出现,检查是否存在 clock skew。 ```bash # 检查节点时间 date # 与 NTP 服务器同步时间 ntpdate -q pool.ntp.org ``` 6. **检查 token 缓存**:如果错误只在某些客户端上出现,检查是否存在缓存旧 token 或错误回调地址。 ### 排查时需要注意的问题 - 这个异常已经把线索收敛到了"身份提供方明确告诉你为什么失败"。排查时最有价值的信息就是 `Code` 和 `Description`,它们通常比通用堆栈更接近根因。 - 不同的错误码指向不同的问题:`invalid_token` 通常是 token 过期或无效,`insufficient_scope` 是 scope 配置问题,`invalid_request` 可能是请求格式问题。 - 需要同时检查 Elasticsearch 配置和 IdP 配置,问题可能出在任何一端。 ## 4. 如何解决这个错误 ### 常用修复思路 - **修复 OIDC 客户端配置**:确保 scope、audience 和回调流程正确。 ```yaml # elasticsearch.yml 中的 OIDC Realm 配置 xpack.security.authc.realms.oidc.oidc1: order: 2 rp.client_id: "your-client-id" rp.client_secret: "your-client-secret" rp.response_type: "code" rp.redirect_uri: "https://your-elasticsearch-domain:9243/api/security/v1/oidc" op.issuer: "https://your-idp-domain.com" op.authorization_endpoint: "https://your-idp-domain.com/oauth2/authorize" op.token_endpoint: "https://your-idp-domain.com/oauth2/token" op.userinfo_endpoint: "https://your-idp-domain.com/oauth2/userInfo" op.jwkset_path: "https://your-idp-domain.com/oauth2/jwks" # 确保请求的 scope 包含 openid 和 profile rp.requested_scopes: ["openid", "profile", "email"] ``` - **缩短 token 缓存时间**:避免使用已失效凭证访问 UserInfo Endpoint。 ```yaml # 在 OIDC Realm 配置中调整缓存时间(如果支持) # 或者在客户端(如 Kibana)配置更短的 token 刷新间隔 ``` - **修复反向代理配置**:确保代理、SSO 网关或 WAF 不会篡改或裁剪认证头。 ```nginx # Nginx 代理配置示例(确保透传 Authorization 头) location / { proxy_pass http://elasticsearch:9200; proxy_set_header Authorization $http_authorization; proxy_pass_header Authorization; } ``` - **解决时钟偏移问题**:同步 Elasticsearch 节点和 IdP 的系统时钟。 ```bash # 安装并配置 NTP yum install ntp systemctl enable ntpd systemctl start ntpd # 手动同步 ntpdate pool.ntp.org ``` - **联系 IdP 管理员**:如果错误码指向 IdP 侧的问题(如用户状态异常、IdP 配置错误),需要联系 IdP 管理员解决。 ### 后续注意事项与推荐建议 - 为 OIDC 认证配置合理的 token 刷新策略,避免 access_token 过期导致的认证失败。 - 建立对 IdP 服务可用性和错误响应的监控,在 IdP 返回异常错误时及时预警。 - 定期检查 OIDC 客户端配置,确保 scope、audience 等参数与 IdP 的要求保持一致。 - 在应用层(如 Kibana)实现适当的错误处理和用户提示,帮助用户理解认证失败的原因。 ### 借助 INFINI 产品提升排障效率 - [INFINI Console](https://docs.infinilabs.com/console/main/) 适合查看集群的安全配置、认证日志和用户访问趋势,帮助快速判断 `Code=[...]` 错误的分布和模式,并提供可视化的配置管理和审计功能,追踪 OIDC 配置变更历史。 - [INFINI Gateway](https://docs.infinilabs.com/gateway/main/) 适合部署在 Elasticsearch 前面做请求观测和流量治理,可以记录所有认证相关请求的详细日志,包括 OIDC 流程中每个步骤的请求和响应,帮助定位是 Elasticsearch 配置问题还是 IdP 返回问题,同时提供请求重试和熔断机制来提升认证稳定性。 - 建议将 OIDC 认证相关指标(成功率、错误码分布、token 过期率)统一接入监控面板,结合 INFINI Console 的告警功能,在认证质量下降时及时通知。 ## 5. 小结 `Failed to get user information from the UserInfo endpoint. Code=[...]; Description=[...]` 已经把线索收敛到了"身份提供方明确告诉你为什么失败"。排查时最有价值的信息就是 `Code` 和 `Description`,它们通常比通用堆栈更接近根因。大多数情况下,这个问题可以通过解读错误码、检查 token 有效性和修复 OIDC 配置来解决。 只要把 OIDC 配置校验、token 管理和 IdP 监控固定下来,大多数认证错误码类异常都可以被快速定位和恢复,也更容易通过 INFINI Console 和 INFINI Gateway 实现持续防护。 ## 相关错误 - [failed-to-get-user-information-from-the-userinfo-endpoint-how-to-solve-this-elasticsearch-exception](/knowledge-base/elasticsearch_error/failed-to-get-user-information-from-the-userinfo-endpoint-how-to-solve-this-elasticsearch-exception/) - [failed-to-get-claims-from-the-userinfo-endpoint-how-to-solve-this-elasticsearch-exception](/knowledge-base/elasticsearch_error/failed-to-get-claims-from-the-userinfo-endpoint-how-to-solve-this-elasticsearch-exception/) - [failed-to-get-claims-from-the-userinfo-endpoint-request-was-cancelled-how-to-solve-this-elasticsearch-exception](/knowledge-base/elasticsearch_error/failed-to-get-claims-from-the-userinfo-endpoint-request-was-cancelled-how-to-solve-this-elasticsearch-exception/) - [failed-to-verify-access-token-how-to-solve-this-elasticsearch-exception](/knowledge-base/elasticsearch_error/failed-to-verify-access-token-how-to-solve-this-elasticsearch-exception/) - [failed-to-verify-access-token-id-token-doesnt-contain-at-hash-claim-how-to-solve-this-elasticsearch-exception](/knowledge-base/elasticsearch_error/failed-to-verify-access-token-id-token-doesnt-contain-at-hash-claim-how-to-solve-this-elasticsearch-exception/) ## 参考文档 - [Elasticsearch OIDC Realm 官方文档](https://www.elastic.co/guide/en/elasticsearch/reference/current/oidc-realm.html) - [OpenID Connect UserInfo Endpoint 规范](https://openid.net/specs/openid-connect-core-1_0.html#UserInfo) - [OAuth 2.0 Bearer Token Usage 规范](https://tools.ietf.org/html/rfc6750) - [INFINI Console 文档](https://docs.infinilabs.com/console/main/) - [INFINI Gateway 文档](https://docs.infinilabs.com/gateway/main/) ## 附:日志上下文 下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题: ```java } else { final Header wwwAuthenticateHeader = httpResponse.getFirstHeader("WWW-Authenticate"); if (Strings.hasText(wwwAuthenticateHeader.getValue())) { BearerTokenError error = BearerTokenError.parse(wwwAuthenticateHeader.getValue()); claimsListener.onFailure( new ElasticsearchSecurityException("Failed to get user information from the UserInfo endpoint. Code=[{}]; " + "Description=[{}]"; error.getCode(); error.getDescription())); } else { claimsListener.onFailure( new ElasticsearchSecurityException("Failed to get user information from the UserInfo endpoint. Code=[{}]; " + "Description=[{}]"; httpResponse.getStatusLine().getStatusCode(); ```