通过Keycloak REST API注销用户不起作用

Man*_* Ha 13 keycloak

从(移动)应用程序调用Keycloak的注销端点时遇到问题.

支持此方案的文档中所述:

/境界/ {领域名} /协议/ OpenID的连接/注销

注销端点注销经过身份验证的用户.

可以将用户代理重定向到端点,在这种情况下,将注销活动用户会话.之后,用户代理将重定向回应用程序.

端点也可以由应用程序直接调用.要直接调用此端点,需要包含刷新令牌以及验证客户端所需的凭据.

我的请求有以下格式:

POST http://localhost:8080/auth/realms/<my_realm>/protocol/openid-connect/logout
Authorization: Bearer <access_token>
Content-Type: application/x-www-form-urlencoded

refresh_token=<refresh_token>
Run Code Online (Sandbox Code Playgroud)

但总是会出现此错误:

HTTP/1.1 400 Bad Request
Connection: keep-alive
X-Powered-By: Undertow/1
Server: WildFly/10
Content-Type: application/json
Content-Length: 123
Date: Wed, 11 Oct 2017 12:47:08 GMT

{
  "error": "unauthorized_client",
  "error_description": "UNKNOWN_CLIENT: Client was not identified by any client authenticator"
}
Run Code Online (Sandbox Code Playgroud)

如果我提供了access_token,Keycloak似乎无法检测到当前客户端的身份事件.我使用相同的access_token来访问其他Keycloak的API而没有任何问题,例如userinfo (/ auth/realms // protocol/openid-connect/userinfo).

我的请求是基于这个Keycloak的问题.该问题的作者得到了它的工作,但这不是我的情况.

我正在使用Keycloak 3.2.1.Final.

你有同样的问题吗?你知道如何解决它吗?

Man*_* Ha 20

最后,我通过查看Keycloak的源代码找到了解决方案:https://github.com/keycloak/keycloak/blob/9cbc335b68718443704854b1e758f8335b06c242/services/src/main/java/org/keycloak/protocol/oidc/endpoints/ LogoutEndpoint.java#L169.它说:

如果客户端是公共客户端,则必须包含"client_id"表单参数.

所以我缺少的是client_id表单参数.我的要求应该是:

POST http://localhost:8080/auth/realms/<my_realm>/protocol/openid-connect/logout
Authorization: Bearer <access_token>
Content-Type: application/x-www-form-urlencoded

client_id=<my_client_id>&refresh_token=<refresh_token>
Run Code Online (Sandbox Code Playgroud)

会话应该被正确销毁.

  • 事实上,不需要“access token”,只需“client_id”和“refresh_token”就足够了。 (8认同)

小智 15

最后。这对我有用。我进行了 REST 调用,如下所示:

标题

{
 "Authorization" : "Bearer <access_token>",
 "Content-Type" : "application/x-www-form-urlencoded"
}
Run Code Online (Sandbox Code Playgroud)

请求正文

{
    "client_id" : "<client_id>",
    "client_secret" : "<client_secret>",
    "refresh_token" : "<refresh_token>"
}
Run Code Online (Sandbox Code Playgroud)

方法

POST
Run Code Online (Sandbox Code Playgroud)

网址

<scheme>://<host>:<port>/auth/realms/<realmName>/protocol/openid-connect/logout
Run Code Online (Sandbox Code Playgroud)

我收到 200 作为响应...如果您做错任何事情,您将收到 401 或 400 错误。调试这个问题非常困难。顺便说一句,我的钥匙斗篷版本是12.0.4

如果帖子不清楚或者您需要更多信息,请告诉我。


Dmi*_*zin 12

适用于 Keycloak 6.0。

只是为了清楚起见:我们确实使 refreshToken 过期,但 accessToken 在“访问令牌寿命”时间内仍然有效。下次用户尝试通过刷新令牌更新访问令牌时,Keycloak 返回 400 Bad request,应该捕获什么并将其作为 401 Unauthorized 响应发送。

public void logout(String refreshToken) {
    try {
        MultiValueMap<String, String> requestParams = new LinkedMultiValueMap<>();
        requestParams.add("client_id", "my-client-id");
        requestParams.add("client_secret", "my-client-id-secret");
        requestParams.add("refresh_token", refreshToken);

        logoutUserSession(requestParams);

    } catch (Exception e) {
        log.info(e.getMessage(), e);
        throw e;
    }
}

private void logoutUserSession(MultiValueMap<String, String> requestParams) {
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

    HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(requestParams, headers);

    String url = "/auth/realms/my-realm/protocol/openid-connect/logout";

    restTemplate.postForEntity(url, request, Object.class);
    // got response 204, no content
}
Run Code Online (Sandbox Code Playgroud)


小智 7

在 3.4 版本中,您需要x-www-form-urlencodedclient_idclient_secret和 refresh_token 作为正文密钥。