从一次414报错理解OAuth2、OIDC与Keycloak登录链路

·踩坑

从一次414报错理解OAuth2、OIDC与Keycloak登录链路

最近排查了一个登录问题。现象很直观:页面跳转到认证中心后,浏览器里出现了一条越来越长的认证地址,最后返回 414 URI Too Long

这类问题表面看像网关报错,实际上往往不是请求头太大,而是登录跳转 URL 本身被反复嵌套了。

先把几个概念理顺

  • OAuth2:一套授权流程,解决“客户端怎样合法拿到 token”。
  • OIDC:建立在 OAuth2 之上的身份认证层,解决“当前登录用户是谁”。
  • JWT:一种常见的 token 格式。
  • Keycloak:把 OAuth2 和 OIDC 工程化落地的认证平台。

可以把它们理解成一套门禁系统:

  • Keycloak 是门禁中心
  • OAuth2 是发卡规则
  • OIDC 是身份核验规则
  • JWT 是最后发到手里的门禁卡

一个典型的登录流程

  1. 前端发现用户未登录。
  2. 浏览器跳转到 Keycloak 登录页。
  3. Keycloak 完成认证后,不直接返回 token,而是先回跳一个短时有效的 code
  4. 前端再用 code + code_verifier 去 token 接口换取 access_tokenid_tokenrefresh_token
  5. 后续前端带着 access_token 去访问业务 API。

这里“先拿 code,再换 token”不是多余设计,而是为了安全。因为浏览器跳转链路不适合直接暴露高价值 token。

这次 414 是怎么发生的

问题的核心不是认证协议本身,而是错误的登录地址被重复当成了下一轮的 redirect_uri

正常情况下,认证地址应该类似这样:

/realms/{realm}/protocol/openid-connect/auth

如果中间的 realm 为空,就会变成:

/realms//protocol/openid-connect/auth

如果同时 client_id 也是空的,而前端又把当前完整页面地址直接作为下一次登录的 redirect_uri,那么错误地址就会被一层层重新编码进新的请求里。几轮之后,URL 就会膨胀到被代理或服务拒绝,最终返回 414 URI Too Long

这次排查带来的几个结论

  • 414 更常见地意味着 URL 太长,而不是请求头太大。
  • redirect_uri 是 OAuth2 / OIDC 里的标准参数名,不是 redirect_url
  • 出现 /realms//... 这类路径时,通常可以优先怀疑认证配置里的 realm 为空。
  • 如果登录 SDK 默认使用当前完整地址作为回跳地址,就要特别小心错误 URL 被重复利用。

一个很实用的经验

当你在登录问题里同时看到下面几个信号时,可以优先往“认证配置错误 + redirect_uri 套娃”方向排查:

  • /realms//...
  • client_id= 为空
  • redirect_uri= 里又嵌了一整条认证地址
  • 最终报 414 URI Too Long

这类问题不一定难,但很适合用来真正理解一次 OAuth2、OIDC 和 Keycloak 是怎么协同工作的。