【问题标题】:Establish SSO/set cookies with access or id token/token exchange通过访问或 id 令牌/令牌交换建立 SSO/设置 cookie
【发布时间】:2020-11-05 01:10:24
【问题描述】:

我允许登录外部应用程序的用户通过 Keycloak 的身份代理和外部的内部令牌交换使用他们的访问令牌跳转到我们的应用程序。

现在我想在我们的应用程序的嵌入式 JxBrowser 中建立 SSO 会话,类似于常规浏览器登录流程,其中在浏览器中设置了三个 cookie:AUTH_SESSION、KEYCLOAK_SESSION(_LEGACY) 和 KEYCLOAK_IDENTITY(_LEGACY)。

KEYCLOAK_IDENTITY 包含一个 Serialized-ID 类型的令牌,看起来有点类似于 ID 令牌。

是否可以使用交换的(内部)访问和/或 ID 令牌创建 KEYCLOAK_IDENTITY cookie,并且如果其他两个 cookie 也正确创建,这是否会建立有效的 SSO 会话?

基本上我所缺少的只是如何获取或创建Serialized-ID 类型的令牌。

【问题讨论】:

    标签: cookies single-sign-on keycloak keycloak-services token-exchange


    【解决方案1】:

    实现此目的的一种方法:

    1. example 之后实现自定义端点

    请注意,无需在standalone.xml 中注册,提供程序就可以正常工作,我只是将 JAR 添加到 Keycloak Docker 映像中。

    1. 添加一个验证给定访问令牌、查找用户、获取用户会话并在响应中设置 cookie 的方法(为简洁起见,省略了大多数错误处理):

      @GET
      @Produces(MediaType.APPLICATION_JSON)
      @Path("sso")
      public Response sso(@Context final HttpRequest request) {
          final HttpHeaders headers = request.getHttpHeaders();
          final String authorization = headers.getHeaderString(HttpHeaders.AUTHORIZATION);
          final String[] value = authorization.split(" ");
          final String accessToken = value[1];
          final AccessToken token = Tokens.getAccessToken(accessToken, keycloakSession);
      
          if (token == null) {
              throw new ErrorResponseException(Errors.INVALID_TOKEN, "Invalid access token", Status.UNAUTHORIZED);
          }
      
          final RealmModel realm = keycloakSession.getContext().getRealm();
          final UriInfo uriInfo = keycloakSession.getContext().getUri();
          final ClientConnection clientConnection = keycloakSession.getContext().getConnection();
      
          final UserModel user = keycloakSession.users().getUserById(token.getSubject(), realm);
      
          final UserSessionModel userSession = keycloakSession.sessions().getUserSession(realm, token.getSessionState());
      
          AuthenticationManager.createLoginCookie(keycloakSession, realm, user, userSession, uriInfo, clientConnection);
      
          return Response.noContent().build();
      }
      

    免责声明:我不完全确定这个实现并不意味着任何安全问题,但由于Tokens.getAccessToken(accessToken, keycloakSession) 对访问令牌进行了全面验证,因此只能使用有效的访问令牌设置 cookie。

    对于 CORS,添加:

    @OPTIONS
    @Produces(MediaType.APPLICATION_JSON)
    @Path("sso")
    public Response preflight(@Context final HttpRequest request) {
        return Cors.add(request, Response.ok("", MediaType.APPLICATION_JSON))
                .auth()
                .preflight()
                .allowedMethods("GET", "OPTIONS")
                .build();
    }
    

    sso():

        return Cors.add(request, Response.ok("", MediaType.APPLICATION_JSON))
                .auth()
                .allowedMethods("GET")
                .allowedOrigins(token)
                .build();
    

    我不确定的是为什么 Firefox 会预检 GET 请求,因此有必要处理它。

    【讨论】:

      猜你喜欢
      • 2019-11-11
      • 2021-02-03
      • 2014-05-12
      • 2013-08-17
      • 2018-01-25
      • 1970-01-01
      • 2016-06-26
      • 2017-10-11
      • 1970-01-01
      相关资源
      最近更新 更多