建立SSO/设置访问或ID令牌/令牌交换所需的cookie

8

我允许已通过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类型令牌的方式。

1个回答

11

实现这个目标的一种方法:

  1. 按照此示例实现自定义端点

请注意,该提供程序对我来说无需在standalone.xml中注册即可正常工作,我只是将JAR添加到Keycloak Docker镜像中。

  1. Add a method that validates a given access token, looks up the user, gets the user session and sets the cookies in the response (most error handling omitted for brevity):

    @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)请求,这使得我们需要处理它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接