Spring Security OpenID Connect 1.0 注销导致 CORS 错误
我无法获取 OpenID 1.0 连接注销即可工作。我已经配置了 OidcClientInitiatedLogoutSuccessHandler,如图所示。
我正在使用 Spring Security 5.2、Keycloak v12、Angular v10 和 Kubernetes。
Spring OAuth2Login 工作正常。用户点击 baseUrl,使用 Keycloak 进行身份验证并路由到 Angular 代码。 csrf 已启用,因此从 Angular 注销是 POST。
从日志中,Spring security 使会话无效并创建一个到 Keycloak 的redirectUri:
022-03-03 20:32:52.887 DEBUG 1 --- [nio-8080-exec-5] o.s.s.w.a.logout.LogoutFilter : Logging out [OAuth2AuthenticationToken [Principal=Name: [acme_user], Granted Authorities: [[ROLE_USER, ROLE_default-roles-acmeRealm, ROLE_offline_access, ROLE_uma_authorization, SCOPE_email, SCOPE_openid, SCOPE_profile]], User Attributes: [{at_hash=_yB9W1nuLmAQ9j_9js9XJg, sub=b8afecd5-b6f9-4016-b91f-0c206bc08801, email_verified=false, iss=http://XXX.XXX.X.XX:31131/auth/realms/acmeRealm, typ=ID, preferred_username=acme_user, nonce=MblUOo3QAYowxGbJo-t8HHLZpFphHhEWlLWkpfrwosY, aud=[acme-grid], acr=1, azp=acme-grid, auth_time=2022-03-03T20:32:01Z, exp=2022-03-03T20:37:02Z, session_state=ea33c7d3-e71f-41f9-b9af-1f947390adc3, iat=2022-03-03T20:32:02Z, jti=48944a4b-25f1-4be0-a531-f9753018f7d5}], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=ZZZ.ZZZ.ZZ.Z, SessionId=5826f702-ed97-425a-a3a4-c1098481f65b], Granted Authorities=[ROLE_USER, ROLE_default-roles-acmeRealm, ROLE_offline_access, ROLE_uma_authorization, SCOPE_email, SCOPE_openid, SCOPE_profile]]]
2022-03-03 20:32:53.008 DEBUG 1 --- [nio-8080-exec-5] o.s.s.w.a.l.SecurityContextLogoutHandler : Invalidated session 49ff75f4-0745-4f52-8263-ac35e9200b46
2022-03-03 20:32:53.011 DEBUG 1 --- [nio-8080-exec-5] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://XXX.XXX.X.XX:31131/auth/realms/acmeRealm/protocol/openid-connect/logout?id_token_hint=blahblahblah
2022
从 keycloak 的日志中,我看到用户的会话已结束。
20:32:53,161 DEBUG [org.keycloak.services.util.CookieHelper] (default task-47) Could not find cookie KEYCLOAK_IDENTITY, trying KEYCLOAK_IDENTITY_LEGACY
20:32:53,161 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) Could not find cookie: KEYCLOAK_IDENTITY
20:32:53,161 DEBUG [org.keycloak.services.util.CookieHelper] (default task-47) Could not find cookie KEYCLOAK_SESSION, trying KEYCLOAK_SESSION_LEGACY
20:32:53,181 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) Could not find cookie: KEYCLOAK_SESSION
20:32:53,182 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) Logging out: acme_user (ea33c7d3-e71f-41f9-b9af-1f947390adc3) offline: false
20:32:53,182 DEBUG [org.keycloak.services.util.CookieHelper] (default task-47) Could not find cookie KEYCLOAK_IDENTITY, trying KEYCLOAK_IDENTITY_LEGACY
20:32:53,183 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) backchannel logout to: acme-grid
20:32:53,185 DEBUG [org.keycloak.services.managers.ResourceAdminManager] (default task-47) Cant logout {0}: no management url
20:32:53,186 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) All clients have been logged out for user acme_user in acmeRealm realm, session ea33c7d3-e71f-41f9-b9af-1f947390adc3
20:32:53,188 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-47) JtaTransactionWrapper commit
20:32:53,201 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-47) JtaTransactionWrapper end
20:32:53,201 DEBUG [org.keycloak.events] (default task-47) type=LOGOUT, realmId=196bd891-7d6d-4aa9-b422-9181f69d31c1, clientId=null, userId=b8afecd5-b6f9-4016-b91f-0c206bc08801, ipAddress=ZZZ.ZZZ.ZZ.Z, authSessionParentId=ea33c7d3-e71f-41f9-b9af-1f947390adc3, authSessionTabId=tJAewwAZxfA
前端错误没有重定向回 baseUrl,而是违反了 CORS:
Access to XMLHttpRequest at 'http://XXX.XXX.X.XX:31131/auth/realms/acmeRealm/protocol/openid-connect/logout?id_token_hint=blahblahblah&post_logout_redirect_uri=http://YYY.YYY.Y.YY:30001' (redirected from 'http://YYY.YYY.Y.YY:30001/logout') from origin 'http://YYY.YYY.Y.YY:30001' has been blocked by CORS policy: Request header field x-xsrf-token is not allowed by Access-Control-Allow-Headers in preflight response.
我更新了 Angular 代码以使用 _csrf 参数而不是 X-XSRF-TOKEN,但得到了不同的 CORS 错误:
/#/:1 Access to XMLHttpRequest at 'http://XXX.XXX.X.XX:31131/auth/realms/acmeRealm/protocol/openid-connect/logout?id_token_hint=blahblahblah&post_logout_redirect_uri=http://YYY.YYY.Y.YY:30001' (redirected from 'http://YYY.YYY.Y.YY:30001/logout?_csrf=748c7b1a-a634-4ce5-8728-c4f97d41820d') from origin 'http://YYY.YYY.Y.YY:30001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Keycloak 配置为允许 Web 来源现在的“*”。 我想知道这些 CORS 错误是否是虚假的 - 由于登录重定向有效,我不清楚为什么注销重定向会导致这些 CORS 违规。
如果我将 antMatcher 添加到注销配置以关闭“/logout”的 csrf,然后使用 GET 从 Angular 调用注销,那么 CORS 违规就会消失并且注销有效:
http.logout(logout -> logout.logoutSuccessHandler(_oidcLogoutSuccessHandler())
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")));
感谢阅读。
I can't get OpenID 1.0 Connect Logout to work. I have configured an OidcClientInitiatedLogoutSuccessHandler as shown.
I am using Spring Security 5.2, Keycloak v12, Angular v10 and Kubernetes.
Spring OAuth2Login works fine. The user hits the baseUrl, authenticates with Keycloak and is routed to the Angular code.
csrf is enabled so the logout from Angular is a POST.
From the logs, Spring security invalidates the session and creates a redirectUri to Keycloak:
022-03-03 20:32:52.887 DEBUG 1 --- [nio-8080-exec-5] o.s.s.w.a.logout.LogoutFilter : Logging out [OAuth2AuthenticationToken [Principal=Name: [acme_user], Granted Authorities: [[ROLE_USER, ROLE_default-roles-acmeRealm, ROLE_offline_access, ROLE_uma_authorization, SCOPE_email, SCOPE_openid, SCOPE_profile]], User Attributes: [{at_hash=_yB9W1nuLmAQ9j_9js9XJg, sub=b8afecd5-b6f9-4016-b91f-0c206bc08801, email_verified=false, iss=http://XXX.XXX.X.XX:31131/auth/realms/acmeRealm, typ=ID, preferred_username=acme_user, nonce=MblUOo3QAYowxGbJo-t8HHLZpFphHhEWlLWkpfrwosY, aud=[acme-grid], acr=1, azp=acme-grid, auth_time=2022-03-03T20:32:01Z, exp=2022-03-03T20:37:02Z, session_state=ea33c7d3-e71f-41f9-b9af-1f947390adc3, iat=2022-03-03T20:32:02Z, jti=48944a4b-25f1-4be0-a531-f9753018f7d5}], Credentials=[PROTECTED], Authenticated=true, Details=WebAuthenticationDetails [RemoteIpAddress=ZZZ.ZZZ.ZZ.Z, SessionId=5826f702-ed97-425a-a3a4-c1098481f65b], Granted Authorities=[ROLE_USER, ROLE_default-roles-acmeRealm, ROLE_offline_access, ROLE_uma_authorization, SCOPE_email, SCOPE_openid, SCOPE_profile]]]
2022-03-03 20:32:53.008 DEBUG 1 --- [nio-8080-exec-5] o.s.s.w.a.l.SecurityContextLogoutHandler : Invalidated session 49ff75f4-0745-4f52-8263-ac35e9200b46
2022-03-03 20:32:53.011 DEBUG 1 --- [nio-8080-exec-5] o.s.s.web.DefaultRedirectStrategy : Redirecting to http://XXX.XXX.X.XX:31131/auth/realms/acmeRealm/protocol/openid-connect/logout?id_token_hint=blahblahblah
2022
From keycloak's logs, I see the session is ended for the user.
20:32:53,161 DEBUG [org.keycloak.services.util.CookieHelper] (default task-47) Could not find cookie KEYCLOAK_IDENTITY, trying KEYCLOAK_IDENTITY_LEGACY
20:32:53,161 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) Could not find cookie: KEYCLOAK_IDENTITY
20:32:53,161 DEBUG [org.keycloak.services.util.CookieHelper] (default task-47) Could not find cookie KEYCLOAK_SESSION, trying KEYCLOAK_SESSION_LEGACY
20:32:53,181 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) Could not find cookie: KEYCLOAK_SESSION
20:32:53,182 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) Logging out: acme_user (ea33c7d3-e71f-41f9-b9af-1f947390adc3) offline: false
20:32:53,182 DEBUG [org.keycloak.services.util.CookieHelper] (default task-47) Could not find cookie KEYCLOAK_IDENTITY, trying KEYCLOAK_IDENTITY_LEGACY
20:32:53,183 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) backchannel logout to: acme-grid
20:32:53,185 DEBUG [org.keycloak.services.managers.ResourceAdminManager] (default task-47) Cant logout {0}: no management url
20:32:53,186 DEBUG [org.keycloak.services.managers.AuthenticationManager] (default task-47) All clients have been logged out for user acme_user in acmeRealm realm, session ea33c7d3-e71f-41f9-b9af-1f947390adc3
20:32:53,188 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-47) JtaTransactionWrapper commit
20:32:53,201 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-47) JtaTransactionWrapper end
20:32:53,201 DEBUG [org.keycloak.events] (default task-47) type=LOGOUT, realmId=196bd891-7d6d-4aa9-b422-9181f69d31c1, clientId=null, userId=b8afecd5-b6f9-4016-b91f-0c206bc08801, ipAddress=ZZZ.ZZZ.ZZ.Z, authSessionParentId=ea33c7d3-e71f-41f9-b9af-1f947390adc3, authSessionTabId=tJAewwAZxfA
Instead of redirecting back to the baseUrl, the front end errors with a CORS violation:
Access to XMLHttpRequest at 'http://XXX.XXX.X.XX:31131/auth/realms/acmeRealm/protocol/openid-connect/logout?id_token_hint=blahblahblah&post_logout_redirect_uri=http://YYY.YYY.Y.YY:30001' (redirected from 'http://YYY.YYY.Y.YY:30001/logout') from origin 'http://YYY.YYY.Y.YY:30001' has been blocked by CORS policy: Request header field x-xsrf-token is not allowed by Access-Control-Allow-Headers in preflight response.
I updated the Angular code to use a _csrf param instead of an X-XSRF-TOKEN, but got a different CORS error:
/#/:1 Access to XMLHttpRequest at 'http://XXX.XXX.X.XX:31131/auth/realms/acmeRealm/protocol/openid-connect/logout?id_token_hint=blahblahblah&post_logout_redirect_uri=http://YYY.YYY.Y.YY:30001' (redirected from 'http://YYY.YYY.Y.YY:30001/logout?_csrf=748c7b1a-a634-4ce5-8728-c4f97d41820d') from origin 'http://YYY.YYY.Y.YY:30001' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
Keycloak is configured to allow web origins of "*' right now.
I am wondering if these CORS errors are spurious - since login redirects work, it's unclear to me why logout redirects would cause these CORS violations.
If I add an antMatcher to the logout config to turn off csrf for "/logout" and then call logout from Angular with a GET, then the CORS violations disapper and logout works:
http.logout(logout -> logout.logoutSuccessHandler(_oidcLogoutSuccessHandler())
.logoutRequestMatcher(new AntPathRequestMatcher("/logout")));
Thanks for reading..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论