[英]Logout at Spring Authorization Server doesn’t terminate user session in Keycloak
I am trying to implement an end-user initiated logout
mechanism.我正在尝试实施最终用户启动的
logout
机制。
I have 4 main entities involved.我有4 个主要实体参与。
Angular
app registered as a public OIDC
client on KeycloakAngular
上注册为公共OIDC
客户端的 Angular 应用程序Spring Boot
application with a secure REST
endpointREST
的Spring Boot
应用程序When the end-user initiates a logout
, a call is made by the Angular
application to Keycloak's end_session_endpoint
.当最终用户发起
logout
时, Angular
应用程序将调用 Keycloak 的end_session_endpoint
。 I have configured the logout
URL for my identity provider ( Spring Authorization Server
) in Keycloak as http://localhost:9000/logout which is the default Spring Security
logout endpoint.我在 Keycloak 中为我的身份提供者(
Spring Authorization Server
)配置了logout
URL 作为http://localhost:9000/logout这是默认的Spring Security
注销端点。
FYI: I haven't enabled BackChannel
or FrontChannel
logout.仅供参考:我没有启用
BackChannel
或FrontChannel
注销。
In the Network
tab of Developer Console
, the sequence of calls happen as below:在
Developer Console
的Network
选项卡中,调用顺序如下:
While inspecting the DEBUG
logs in the Spring Authorization Server
, I am able to see the logout
happen for that particular end-user including invalidating the JSESSIONID
, however the session doesn't terminate in Keycloak which causes the user to stay logged in and access the secure REST
endpoint.在检查
Spring Authorization Server
中的DEBUG
日志时,我能够看到该特定最终用户发生logout
,包括使JSESSIONID
无效,但是 session 不会在 Keycloak 中终止,这会导致用户保持登录状态并访问安全REST
端点。
Is the Spring Authorization Server
expected to return a specific response back to Keycloak to convey that the logout
process is complete at it's end and that Keycloak can end the session now? Spring Authorization Server
是否期望将特定响应返回给 Keycloak,以传达logout
过程在其结束时完成并且 Keycloak 现在可以结束 session?
This is my logic for logout
at Spring Authorization Server
.这是我在
Spring Authorization Server
logout
的逻辑。
@Bean
@Order(Ordered.LOWEST_PRECEDENCE)
public SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(
authorize -> authorize.mvcMatchers("/hello/**").permitAll().anyRequest().authenticated())
.formLogin(form -> form.loginPage("/login").permitAll())
.addFilterAfter(cookieFilter, ChannelProcessingFilter.class)
.logout().logoutSuccessUrl("http://localhost:4200");
return http.build();
}
I am totally clueless about what I am missing to make Keycloak end the session at it's end.我完全不知道让 Keycloak 在结束时结束 session 所缺少的东西。 Any leads will be greatly appreciated.
任何线索将不胜感激。
Thank you!谢谢!
Update: A post_logout_redirect_uri
parameter is sent in the logout
request to the Spring Authorization Server
.更新:在
logout
请求post_logout_redirect_uri
参数发送到Spring Authorization Server
。 I am not able to see a redirection happen to this URI which may be the reason that Keycloak session doesn't terminate.我无法看到此 URI 发生重定向,这可能是 Keycloak session 未终止的原因。
post_logout_redirect_uri=http://127.0.0.1:8080/auth/realms/SpringBootKeycloak/broker/oidc/endpoint/logout_response
Got this to work finally!终于让这个工作了!
The logoutSuccessUrl("http://localhost:4200")
is incorrect. logoutSuccessUrl("http://localhost:4200")
不正确。
As I mentioned in the Update part of my question that Keycloak sends a post_logout_redirect_uri
parameter (inspected the logout
endpoint in the Network
calls in Chrome Developer Console
), the logoutSuccessUrl
or the redirectUri
should be set to正如我在问题的更新部分提到的那样,Keycloak 发送了一个
post_logout_redirect_uri
参数(在 Chrome Developer Console
的Network
调用中检查了logout
端点), logoutSuccessUrl
或redirectUri
应该设置为
http://127.0.0.1:8080/auth/realms/SpringBootKeycloak/broker/oidc/endpoint/logout_response
http://127.0.0.1:8080/auth/realms/SpringBootKeycloak/broker/oidc/endpoint/logout_response
Also, note that the above URL takes in state
as a request parameter.另外,请注意上面的 URL 将
state
作为请求参数。 Initially, it gave me a 400 Bad Request
as I didn't send the state
.最初,它给了我一个
400 Bad Request
因为我没有发送state
。
Since I was required to intercept the state
parameter when logout
is initiated at the Spring Authorization Server
, I added a custom logout handler to do the job.由于在
Spring Authorization Server
启动logout
时我需要拦截state
参数,因此我添加了一个自定义注销处理程序来完成这项工作。
@Component
public class IdpLogoutHandler implements LogoutHandler {
private static final String STATE = "state";
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
String state = request.getParameter(STATE);
try {
response.sendRedirect(
"http://127.0.0.1:8080/auth/realms/SpringBootKeycloak/broker/oidc/endpoint/logout_response?state="
+ state);
} catch (IOException e) {
e.printStackTrace();
}
}
}
Updated WebSecurityConfig
:更新
WebSecurityConfig
:
http.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(
authorize -> authorize.mvcMatchers("/hello/**").permitAll().anyRequest().authenticated())
.formLogin(form -> form.loginPage("/login").permitAll())
.addFilterAfter(cookieFilter, ChannelProcessingFilter.class).logout()
.addLogoutHandler(customLogoutHandler);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.