如何通过Keycloak + 外部SSO获取token

问题描述 投票:0回答:1

我正在外部 sso 中编写身份验证的后端实现。我使用 Spring Boot 3 进行微服务,Keycloak 负责身份验证。 Keycloak 包含多个领域来支持多租户。我们的服务和前端使用 jwt 令牌进行授权,因此作为 sso 身份验证的结果,我们应该收到 Keycloak 的令牌。

预计实施:

  1. 前端调用“bff”(前端的后端)微服务,传递用户的登录信息作为输入。
  2. “bff”调用“auth”微服务,该微服务根据登录情况判断用户属于哪个Keycloak领域以及是否配置了IDP。
  3. “auth”服务必须将用户重定向到外部 IDP 页面,绕过 Keycloak 表单,因为登录表单在前面提供。
  4. 输入外部单点登录的用户数据后,将返回一个授权码,必须兑换令牌。
  5. 连同 jwt 令牌一起重定向回原始前端页面,这将颁发我们的 Keycloak。

** 我尝试使用keycloak帐户客户端URL转到sso表单,Keycloak本身在redirect_uri中替换其URL并且身份验证成功,但这不是我需要的,因为前端已经有一个登录表单。

我的问题是: 步骤 3 中的链接应该是什么样的,“auth”微服务将在 Keycloak 中调用该链接?需要在重定向中插入什么内容 - 原始前端 URL、Keycloak URL 还是外部 sso 端点?如何返还 Keycloak 令牌?

我是这样写的: {keycloakUrl}/realms/{realmName}/protocol/openid-connect/auth?client_id={clientId}&redirect_uri={???}&response_type=code&scope=openId&kc_idp_hint={alias}

spring-boot authentication keycloak single-sign-on idp
1个回答
0
投票

您想象的解决方案违背了当前的建议,并违反了多项 OAuth2 规则。

前端调用“bff”(前端的后端)微服务,将用户的登录信息作为输入传递

这不是 OAuth2 的工作原理。在 OAuth2 授权代码流程(这是唯一推荐的用户登录流程)中,前端和 OAuth2 客户端都不应访问用户凭据。只有授权服务器可以(Keycloak 或在您的情况下是其背后的 IDP)。

将用户重定向到外部 IDP 页面,绕过 Keycloak 表单

使用 Keycloak,这是通过在授权请求中提供

kc_idp_hint
参数来完成的。

连同 jwt 令牌一起重定向回原始前端页面

根据最新建议,OAuth2 令牌不应离开您的服务器。前端和后端之间的通信应使用会话 cookie 进行授权(并防止 CSRF)。 BFF 在会话中保留令牌,并在转发请求时用承载令牌替换会话 cookie。我在 Baeldung 写了一篇文章

你应该做什么:

假设BFF是Spring Cloud Gateway实例:

  • 为每个领域定义一个 OAuth2 客户端 provider
  • 为每个“租户”定义一个 OAuht2 客户端
  • 注册,其中 authorization_code
    (每个领域至少一个,如果您希望每个领域对外部 IDP 进行“直接访问”,则需要更多)
  • 在 BFF 上公开一个端点,列出启动登录的各种选项(每个注册一个)
  • 前端选择其中一个选项(向用户呈现选择、“记住”之前的选择等)并将用户代理重定向到 BFF 上的正确端点,而 BFF 又重定向到授权服务器(本身可能会重定向到外部 IDP)
  • 登录成功后,授权服务器将用户代理重定向回BFF并带有代码
  • BFF 将代码交换为令牌并将用户代理重定向回前端
  • 将请求从前端路由到资源服务器时,BFF 上的
  • TokenRelay=
     过滤器会用会话中的 Bearer 令牌替换会话 cookie 
我维护了一个 Spring Boot 启动器来帮助配置 BFF(使用前端代码可访问的 cookie 来防止 CSRF,在会话中保存登录/注销后 URL 等等)。它的用法在上面链接的

Baeldung文章中有解释。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.