使用Keycloak的刷新令牌,我能够注销,但我的访问令牌没有失效。

huangapple go评论99阅读模式
英文:

using keycloak refresh token i am able to logout but my access token is not invalidating

问题

以下是您的源代码的翻译:

@PostMapping(value = "/logout", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseDTO usingRefreshTokenLogout(@RequestBody LogoutRequestDTO logoutRequestDTO) throws ServletException {
    log.info("即将注销用户");
    return keycloakService.logoutFromSSO(logoutRequestDTO);
}

@Override
public ResponseDTO logoutFromSSO(LogoutRequestDTO logoutRequestDTO) throws ServletException {
    logoutRequestDTO.setClient_id(clientId);
    logoutRequestDTO.setClient_secret(clientSecret);
    ResponseEntity<String> response = loginClient.logout(logoutRequestDTO);
    if (response.getStatusCode() == HttpStatus.NO_CONTENT) {
        log.info("响应:{}", response.getBody());
        return new SuccessResponseDTO("注销请求成功");
    } else {
        log.info("响应:{}", response.getBody());
        return new SuccessResponseDTO("注销请求失败,状态码:" + response.getStatusCode());
    }
}

import com.tcg.admin.dto.LogoutRequestDTO;
import feign.Headers;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

@FeignClient(name = "sessionFeignClient", url = "${client.post.base.url}")
public interface LoginClient {

    @PostMapping(value = "/logout",
            consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    ResponseEntity<String> logout(@RequestBody LogoutRequestDTO logoutRequestDTO);
}

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LogoutRequestDTO {
    private String refresh_token;
    private String client_id;
    private String client_secret;
}

注销URL如下:

http://base-url/realms/my-realm-name/protocol/openid-connect/logout

我正在尝试实现注销功能,使用刷新令牌,然后我能够注销,但在注销后,我的访问令牌没有失效。使用该访问令牌,我可以访问其他资源。如果按照Keycloak文档中的说明进行操作,我在Postman中收到注销确认的响应。如果有人可以帮助我解决这个问题,我提前表示感谢。我的Keycloak版本是15.0.2。

英文:

Below is my source code

    @PostMapping(value = &quot;/logout&quot;, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseDTO usingRefreshTokenLogout(@RequestBody LogoutRequestDTO logoutRequestDTO) throws ServletException {
log.info(&quot;going to logout user&quot;);
return keycloakService.logoutFromSSO(logoutRequestDTO);
}
@Override
public ResponseDTO logoutFromSSO(LogoutRequestDTO logoutRequestDTO) throws ServletException {
logoutRequestDTO.setClient_id(clientId);
logoutRequestDTO.setClient_secret(clientSecret);
ResponseEntity&lt;String&gt; response =  loginClient.logout(logoutRequestDTO);
if(response.getStatusCode() == HttpStatus.NO_CONTENT) {
log.info(&quot;response : {}&quot;, response.getBody());
return new SuccessResponseDTO(&quot;Logout request successful&quot;);
}else {
log.info(&quot;response : {}&quot;, response.getBody());
return new SuccessResponseDTO(&quot;Logout request failed with status code: &quot; +  
response.getStatusCode());
}
}
import com.tcg.admin.dto.LogoutRequestDTO;
import feign.Headers;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@FeignClient(name = &quot;sessionFeignClient&quot;, url = &quot;${client.post.base.url}&quot;)
public interface LoginClient {
@PostMapping(value = &quot;/logout&quot;,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
ResponseEntity&lt;String&gt; logout(@RequestBody LogoutRequestDTO logoutRequestDTO);
}
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class LogoutRequestDTO {
private String refresh_token;
private String client_id;
private String client_secret;
}

and below is my logout url

http://base-url/realms/my-realm-name/protocol/openid-connect/logout

I am trying to implement logout functionality. using refresh token then i am able to logout but after logout my access token is not invalidating. and using that access token i can access other resource. and if i go through according to keycloak docs. https://www.keycloak.org/docs/latest/securing_apps/index.html#logout then i am getting in the postman response for logout confirmation. if someone help me for resolving this issue.
and my keycloak version is 15.0.2

and thanks in advance

答案1

得分: 1

JWT访问令牌是无状态的,在用户登出时不会失效。API将继续接受它们。

您可以随时撤销刷新令牌,包括在注销时。下次某方试图使用刷新令牌获取访问令牌时,它将失败。

通常,如果您正在编写一个Web客户端,最常见且最简单的最佳实践如下:

  • 保持访问令牌的生命周期短,例如15分钟,以便在注销后不久失效。

  • 根据最佳实践,在Web应用程序中使用安全的Cookie层,这也有助于确保在注销后立即拒绝所有后端访问。

  • 客户端被信任在注销时丢弃所有令牌(正如下面的评论中ch4mp指出的那样)。

高级控制

还可以使用引用令牌格式的访问令牌。这些令牌需要在授权服务器上进行内省,并可以立即检测到吊销事件。

内省通常在API网关中执行,然后将结果缓存以供将来使用相同令牌的请求。

在吊销事件发生后,授权服务器可以通知API网关,后者可以从其缓存中删除该客户端+用户组合的令牌。

英文:

JWT access tokens are stateless and do not become invalidated when a user logs out. An API will continue to accept them.

You can revoke a refresh token at any time, including upon logout. The next time a party attempts to use the refresh token to get an access token, it will fail.

The two usual, and simplest, best practices, assuming you are writing a web client, are as follows:

  • Keep access tokens short lived, eg 15 minutes, so that they are not valid for long after logout

  • Use a secure cookie layer in the web app, according to best practices, which also helps to ensure that all back end access is immediately denied upon logout

  • The client is trusted to discard all tokens upon logout (as pointed out by ch4mp in the comments below)

ADVANCED CONTROL

It is also possible to use access tokens in a reference token format. Such tokens require introspection at the authorization server, and can immediately detect revocation events.

Introspection is typically done in an API gateway, which then caches results for future requests with the same token.

After a revocation event, the authorization server can notify the API gateway, which can remove tokens for that client + user combination from its cache.

答案2

得分: 0

我知道这个“解决方案”是一个权宜之计,但可能会对你有所帮助。

你可以将令牌和激活标志持久化到数据库中。
当你登出用户时,你可以更改特定令牌的标志,如果令牌处于非激活状态,用户就不应该访问API。

附注:在Keycloak API中,我曾经找到过.invalidate(token) 方法:

Keycloak keycloak = KeycloakBuilder.builder()
        .realm(realm)
        .serverUrl(serverURL)
        ...
        .build();

keycloak.tokenManager()
        .invalidate(token);
英文:

I know this 'solution' is a hack but may help you as workaround.

You can persist token, and is_activate flag to database.
When you logout user then you can change flag of particular token, if token is inactive, user shouldnt' get access to API.

PS: in keycloak API once I found .invalidate(token) method:

    Keycloak keycloak = KeycloakBuilder.builder()
.realm(realm)
.serverUrl(serverURL)
...
.build();
keycloak.tokenManager()
.invalidate(token);

答案3

得分: 0

这是关于使用JWT的大部分批评的要点。请参考像“停止使用JWT进行会话”这样的文章,以及它的续篇和一堆其他指南。你需要一个会话数据库,正如Kafarson所示,否则你将不得不依赖于超时,这对于你的安全性姿态来说是一个相当大的问题。

英文:

This is the essence of large amount of the criticism around use of JWTs. See articles like "Stop using JWT for sessions", its sequel, and a bunch of other guidance. You need a session db, as Kafarson hinted at, or you live with the frustrating need to rely on timeout which is a pretty big issue for your security posture.

huangapple
  • 本文由 发表于 2023年7月6日 14:29:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/76626060.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定