📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 7.x-8.x 涉及组件: OpenID Connect Realm、Kibana、IdP(Keycloak / Okta / Azure AD 等)

1. 错误异常的基本描述 #

redirect_uri mismatch(部分 IdP 显示为 invalid redirect uri)是 OIDC 认证流程中的典型错误,表示 Elasticsearch 在发起授权码流程时携带的 redirect_uri 参数,与 IdP 应用注册里登记的回调地址不完全一致,IdP 拒绝把授权码返回给该地址。

该错误由 IdP 在授权阶段直接抛出(通常展示在跳转失败的错误页或返回给 Kibana 的错误参数中),Elasticsearch 侧则表现为 OIDC 登录跳转后无法回到 Kibana,认证流程中断。

常见现象 #

  • 用户点击 Kibana 的 OIDC 登录后,IdP 页面直接报错:redirect_uri mismatchInvalid redirect URI
  • 浏览器地址栏里可以看到 redirect_uri=https%3A%2F%2F... 参数,与 IdP 控制台中注册的地址存在差异。
  • 本地或测试环境正常,切换域名、启用代理或修改端口后集中出现。
  • 日志中 Elasticsearch 的 OIDC Realm 报 Failed to complete OIDC authentication 之类的后续错误。

典型报错与异常栈 #

IdP 侧错误(以 Keycloak 为例):

ERROR: invalid redirect_uri
Invalid parameter: redirect_uri

Elasticsearch 侧通常在处理回调时记录:

OpenIdConnectException: Failed to complete OpenId Connect authentication flow
    at org.elasticsearch.xpack.security.authc.oidc.OpenIdConnectAuthenticator...

2. 为什么会发生这个错误 #

OIDC 规范要求:授权请求中的 redirect_uri 必须与客户端注册时登记的回调地址逐字符完全一致(协议、域名、端口、路径、末尾斜杠均不能有差异)。Elasticsearch 的 OIDC Realm 通过 rp.redirect_uri 声明本方回调地址,任何一侧的变化都会造成不匹配。

常见原因包括:

  • IdP 侧注册地址与 Realm 配置不一致rp.redirect_uri 的值与 IdP 应用里配置的回调 URL 差一个斜杠、一个端口或 http/https 不同。
  • Kibana 访问地址变化:用户通过新域名、新端口或 IP 访问 Kibana,而 Realm 中的 rp.redirect_uri 仍是旧地址。
  • 反向代理改写:Nginx / Load Balancer 未正确传递 X-Forwarded-ProtoX-Forwarded-Host,导致 Elasticsearch 拼出的回调地址是内网 http 地址而非对外 https 地址。
  • Kibana server.basePath 配置缺失或错误:回调路径多了或少了一段前缀。
  • 末尾斜杠差异https://kibana.example.com:5601/api/security/oidc/callbackhttps://kibana.example.com:5601/api/security/oidc/callback/ 被视为不同地址。
  • 多环境配置串用:测试 IdP 注册的是测试域名,Elasticsearch 却配置了生产回调地址。

3. 如何排查这个异常 #

建议按"先拿到实际发送的 redirect_uri,再比对 IdP 注册值"的顺序处理:

  1. 抓取实际发送的 redirect_uri

    • 在浏览器开发者工具的 Network 面板中,找到跳转到 IdP 的授权请求(/authorize?...)。
    • 复制其中的 redirect_uri 参数并 URL 解码,得到 Elasticsearch 实际声明的回调地址。
  2. 比对 IdP 侧注册的回调地址

    • 登录 IdP 管理后台,打开对应 Client / Application 的设置页。
    • 将 “Valid Redirect URIs” 与上一步的值逐字符比对,重点看协议、域名、端口、路径和末尾斜杠。
  3. 核对 Elasticsearch Realm 配置

    • 打开 elasticsearch.yml,检查 OIDC Realm 的 rp.redirect_uri
xpack.security.authc.realms.oidc.oidc1:
  order: 1
  rp:
    redirect_uri: "https://kibana.example.com:5601/api/security/oidc/callback"
    client_id: "..."
    response_type: "code"
  1. 检查反向代理头传递
    • 确认代理将原始协议与主机名传给 Kibana:
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  1. 检查 Kibana basePath
    • 若 Kibana 挂在子路径下,确认 server.basePath 与外部访问路径一致,且 server.rewritePath 配置正确。

排查时需要注意的问题 #

  • 比对必须逐字符进行:肉眼容易漏掉末尾斜杠、大小写、默认端口(:443 显式写出与否)。建议把两个值分别 URL 解码后放入文本对比工具。
  • 区分授权回调与退出回调:部分 IdP 还要求注册 post_logout_redirect_uri,退出登录失败时也要检查该地址。
  • 代理环境下看"真实到达"的值:浏览器地址栏可能显示正常,但 Elasticsearch 按请求头拼出的回调可能是内网地址,要以授权请求里实际发送的 redirect_uri 为准。

4. 如何解决这个错误 #

常用修复思路 #

方案一:统一回调地址(推荐以 IdP 注册表为准)

将 Elasticsearch Realm 的 rp.redirect_uri 改为与 IdP 注册值完全一致:

xpack.security.authc.realms.oidc.oidc1:
  rp:
    redirect_uri: "https://kibana.example.com/api/security/oidc/callback"

修改后重启 Elasticsearch(或 reload realm)使配置生效。

方案二:在 IdP 侧补齐注册地址

如果回调地址本身是正确的,则登录 IdP 管理后台,在 Client 的 “Valid Redirect URIs” 中加入该精确地址。开发调试期可临时使用通配(如 https://*.example.com/api/security/oidc/callback,以 IdP 支持为准),生产环境建议登记精确值。

方案三:修正代理与 Kibana 外部地址

代理后部署时,确保 Kibana 知道对外地址:

# kibana.yml
server.basePath: "/kibana"
server.rewritePath: true
xpack.security.publicBaseUrl: "https://kibana.example.com"

并正确传递 X-Forwarded-* 头,使拼出的 redirect_uri 与外部访问地址一致。

方案四:多环境隔离

为测试与生产分别建立 IdP Client 和 Realm 配置,避免回调地址互相串用;通过配置管理工具(如 Ansible / Helm values)统一维护,杜绝手工修改造成的漂移。

后续注意事项与推荐建议 #

  • 将回调地址纳入变更管理:任何域名、端口、basePath、证书更换,都要同步更新 IdP 注册表与 rp.redirect_uri
  • 在 IdP 侧开启详细的客户端访问日志,回调不匹配时可直接看到 IdP 拒绝的完整 redirect_uri 值。
  • 上线前用浏览器隐身模式完整走一遍登录 + 退出流程,验证授权回调与退出回调均已注册。

借助 INFINI 产品提升排障效率 #

  • INFINI Console 可以统一管理多套集群的 OIDC Realm 配置并留存变更记录,回调地址被误改时可快速回滚。
  • INFINI Gateway 部署在 Elasticsearch 前面,可以完整记录认证跳转链路中的请求头与转发地址,判断 X-Forwarded-* 是否被正确传递,定位代理改写问题。
  • 建议将 OIDC 登录成功率纳入监控,回调类错误骤增通常意味着域名、证书或代理配置发生了变更。

5. 小结 #

redirect_uri mismatch 的核心原因是授权请求中的回调地址与 IdP 注册值不完全一致,差异往往只是末尾斜杠、端口、协议或 basePath 前缀。排查时先从浏览器抓到实际发送的 redirect_uri,再与 IdP 注册表和 rp.redirect_uri 逐字符比对,代理环境下重点检查 X-Forwarded-* 头的传递。只要三处(IdP 注册、Realm 配置、外部访问地址)保持一致,该问题即可彻底解决。

相关错误 #

附:日志上下文 #

下面保留当前页面中的源码片段,便于结合异常调用栈定位问题:

throw new OpenIdConnectException("redirect_uri [" + redirectUri + "] does not match the registered value");