Keycloak Backchannel Logout and CAS

81 views
Skip to first unread message

Maksim Kopeyka

unread,
Dec 4, 2019, 4:23:20 PM12/4/19
to CAS Community
Hi Guys,

I use CAS as IDP in keycloak.
IDP has option "Backchannel Logout". This is a description:
Backchannel logout is a background, out-of-band, REST invocation to the IDP to logout the user. Some IDPs can only perform logout through browser redirects as they may only be able to identity sessions via a browser cookie.

Does CAS support such way to logout? 

Ray Bon

unread,
Dec 4, 2019, 4:32:08 PM12/4/19
to cas-...@apereo.org
-- 
Ray Bon
Programmer Analyst
Development Services, University Systems

I respectfully acknowledge that my place of work is located within the ancestral, traditional and unceded territory of the Songhees, Esquimalt and WSÁNEĆ Nations.

Maksim Kopeyka

unread,
Dec 4, 2019, 4:36:08 PM12/4/19
to CAS Community
Hi Ray,

Your link about background call from CAS to Keycloak however my question about background call from Keycloak to CAS.

Maksim Kopeyka

unread,
Dec 5, 2019, 5:48:32 PM12/5/19
to CAS Community
I tried this functionality in keycloak. I see a POST request to CAS after logout from keycloak and I see this request in CAS access log but my CAS session still active.
Did I miss something? How to logout from CAS too?

DEBUG [org.apache.http.impl.execchain.MainClientExec] (default task-17) Executing request POST /cas/idp/profile/SAML2/POST/SLO HTTP/1.1
DEBUG [org.apache.http.impl.execchain.MainClientExec] (default task-17) Target auth state: UNCHALLENGED
DEBUG [org.apache.http.impl.execchain.MainClientExec] (default task-17) Proxy auth state: UNCHALLENGED
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 >> POST /cas/idp/profile/SAML2/POST/SLO HTTP/1.1
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 >> Content-Length: 4596
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 >> Content-Type: application/x-www-form-urlencoded
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 >> Host: dev-cas-idp.myhost.com
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 >> Connection: Keep-Alive
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 >> User-Agent: Apache-HttpClient/4.5.4 (Java/1.8.0_212)
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 >> Accept-Encoding: gzip,deflate
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 >> "POST /cas/idp/profile/SAML2/POST/SLO HTTP/1.1[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 >> "Content-Length: 4596[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 >> "Content-Type: application/x-www-form-urlencoded[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 >> "Host: dev-cas-idp.myhost.com[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 >> "Connection: Keep-Alive[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 >> "User-Agent: Apache-HttpClient/4.5.4 (Java/1.8.0_212)[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 >> "Accept-Encoding: gzip,deflate[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 >> "[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 >> "SAMLRequest=PHNhbWxwOkxvZ291dFJlcXVlc3QgeG1sbnM6c2FtbHA9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpwcm90b2NvbCIgeG1sbnM9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iIERlc3RpbmF0aW9uPSJodHRwczovL2Rldi1hZmZpbGlhdGUtaWRwLnByaXZhdGUubGlua3N5bmVyZ3kuY29tL2Nhcy9pZHAvcHJvZmlsZS9TQU1MMi9QT1NUL1NMTyIgSUQ9IklEX2MyZjVjZjhkLWQyZjQtNGRmZi1hYTkxLTFlOTM5Y2Y1MDljZCIgSXNzdWVJbnN0YW50PSIyMDE5LTEyLTA1VDIyOjM2OjQ2LjIzOVoiIFZlcnNpb249IjIuMCI%2BPHNhbWw6SXNzdWVyIHhtbG5zOnNhbWw9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDphc3NlcnRpb24iPmh0dHBzOi8vYXV0aC1kZXYubG9jYWwucmFrdXRlbm1hcmtldGluZy5jb20vYXV0aC9yZWFsbXMvcmFrdXRlbi1tYXJrZXRpbmc8L3NhbWw6SXNzdWVyPjxkc2lnOlNpZ25hdHVyZSB4bWxuczpkc2lnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjIj48ZHNpZzpTaWduZWRJbmZvPjxkc2lnOkNhbm9uaWNhbGl6YXRpb25NZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzEwL3htbC1leGMtYzE0biMiLz48ZHNpZzpTaWduYXR1cmVNZXRob2QgQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxLzA0L3htbGRzaWctbW9yZSNyc2Etc2hhMjU2Ii8%2BPGRzaWc6UmVmZXJlbmNlIFVSST0iI0lEX2MyZjVjZjhkLWQyZjQtNGRmZi1hYTkxLTFlOTM5Y2Y1MDljZCI%2BPGRzaWc6VHJhbnNmb3Jtcz48ZHNpZzpUcmFuc2Zvcm0gQWxnb3JpdGhtPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwLzA5L3htbGRzaWcjZW52ZWxvcGVkLXNpZ25hdHVyZSIvPjxkc2lnOlRyYW5zZm9ybSBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMTAveG1sLWV4Yy1jMTRuIyIvPjwvZHNpZzpUcmFuc2Zvcm1zPjxkc2lnOkRpZ2VzdE1ldGhvZCBBbGdvcml0aG09Imh0dHA6Ly93d3cudzMub3JnLzIwMDEvMDQveG1sZW5jI3NoYTI1NiIvPjxkc2lnOkRpZ2VzdFZhbHVlPm1KYU5kTGdEcGk3RmNFYnFFcGN0amJ5RU5xM0REa1NtUG9ybnhDWnE0Vmc9PC9kc2lnOkRpZ2VzdFZhbHVlPjwvZHNpZzpSZWZlcmVuY2U%2BPC9kc2lnOlNpZ25lZEluZm8%2BPGRzaWc6U2lnbmF0dXJlVmFsdWU%2BcmRINHAyUHNhNEczcEU0a09sVkpZOXN5QVhlbzd1R2hkK1FjaDdRZGpsSENEd05zNVJjTE1WSmtNcnduUGJBUjl1SjRjSEhhRUlOc0JWMjhvWHUybzlrVlJrRTdJMVpyMFlrd1hLRGRLd01UZjh4dTk5aUpGby9EWUUzbmF3NktPbHJpeG03aTc1T2ZlR0xmTE9ZTnRQdWhocHBNM2JFS2QvMXUweFovRVBXTTZ1LzdLU1RZb1hYNEtPcHRoWEJpWHAySjI2a0hZamR5TnhldnRVN2Y0cHlSbGF5S3ltU3lEbFRTMVVDOGdhaXRwM2ZBMExoY0tqcTdLQUtFRG9zcHYzZC8xRVYyS1ozczd0QmNDLzZrcWJiS3FuaGF6MkZHQzZhVTV3ZWF6R2lCZjc1VzcwVk1GVkxCUC9FRnR5cVZjNllqemt0WksvTVI2SXdlTndSS0VBPT08L2RzaWc6U2lnbmF0dXJlVmFsdWU%2BPGRzaWc6S2V5SW5mbz48ZHNpZzpLZXlOYW1lPnJiLXo4Zy14al9IVXlQMFg5aGViLWlyRXpGYWZKZTFRS3NoSDRwU3lsNzQ8L2RzaWc6S2V5TmFtZT48ZHNpZzpYNTA5RGF0YT48ZHNpZzpYNTA5Q2VydGlmaWNhdGU%2BTUlJQ3NUQ0NBWmtDQmdGcU5uQjQ5akFOQmdrcWhraUc5dzBCQVFzRkFEQWNNUm93R0FZRFZRUUREQkZ5WVd0MWRHVnVMVzFoY210bGRHbHVaekFlRncweE9UQTBNVGt4TmpNd01ERmFGdzB5T1RBME1Ua3hOak14TkRGYU1Cd3hHakFZQmdOVkJBTU1FWEpoYTNWMFpXNHRiV0Z5YTJWMGFXNW5NSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXJ5N0RVOW9MVEV6R2ZMdFVBZGxKZDhZNXNzaHFnR3NROHE1dko5aHlVaHE0SS92TlMwRkV3VW0wTlFTdysxWXQ2cGUwZmFhSU50T2pJOW5MTUhva0laQk01cmhTMHhFS1ZJb0xIREIyUEtncmM5d05aNEtrNkhmQTJxWkF1YktYVkhiMXpZcStkUHRiRGliN0JOb1g1cm9SMnVIWG01MEk2ZDN2NXovbWNvaUQvcHRpbmJtclhBMXF5VHpNc0U3Q21PcHA5eE1MS2UzMlQxVzliMTZLaUV0aXZwSXFQMHNQY3pDbmo5Mzl6a2lFVXB5dW0xTnJ2NDFwSndUYTIvaGF3MjNNcTdKeUVrN2JiTUZmcXJkVFFhaG5hak5qZzA3cTRRQUNJdUgzQUp4RmFLbHZnQmdzcERZeXRyNU51STVScFNyYTJFUUZPYXBidGxCdTY4QWtWd0lEQVFBQk1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ1M1QktYWFlRUzRLMVBKb295MUozd1NzOHJYWE0zM0crN1Rhb29EWFROY1F0NWQ5ZHFCTXMvNlBBenZKODBZTG00MXdtbFkvbzhiUCtQU3QyL0x1MC9BRUp5WEVEVE5iNDcybTBDYi9ESGxHYXpCTWwwZTNLbUo5YmlPU3FOT09qRlhsTTlRRjNhd1BxTVBWa1NCTHk5SkNWN3QrTU9PVDhIWHJDOVRGYS9NejgyeGVBb1JHMlRaRlN3bHQ2cnVIMVZ3dnQxR29wYldyeU1KaDREOVROd2hsd1RGeUtpaUY2TlBOaUdSVDhWeXhMeDNUQ2liMlJkV2J4UVBZYW1OOFFreXBWWjVnTC9KZ0VRc09OQjZDTHI0bElQcDVKMWJveVF1YnJhb2JsSjR6ZHdJdzY1azZRR2RJVUlmYWloZFRWZEQ5MEJxNTVJeXhVK2JLdmFGNWsyPC9kc2lnOlg1MDlDZXJ0aWZpY2F0ZT48L2RzaWc6WDUwOURhdGE%2BPGRzaWc6S2V5VmFsdWU%2BPGRzaWc6UlNBS2V5VmFsdWU%2BPGRzaWc6TW9kdWx1cz5yeTdEVTlvTFRFekdmTHRVQWRsSmQ4WTVzc2hxZ0dzUThxNXZKOWh5VWhxNEkvdk5TMEZFd1VtME5RU3crMVl0NnBlMGZhYUlOdE9qSTluTE1Ib2tJWkJNNXJoUzB4RUtWSW9MSERCMlBLZ3JjOXdOWjRLazZIZkEycVpBdWJLWFZIYjF6WXErZFB0YkRpYjdCTm9YNXJvUjJ1SFhtNTBJNmQzdjV6L21jb2lEL3B0aW5ibXJYQTFxeVR6TXNFN0NtT3BwOXhNTEtlMzJUMVc5YjE2S2lFdGl2cElxUDBzUGN6Q25qOTM5emtpRVVweXVtMU5ydjQxcEp3VGEyL2hhdzIzTXE3SnlFazdiYk1GZnFyZFRRYWhuYWpOamcwN3E0UUFDSXVIM0FKeEZhS2x2Z0Jnc3BEWXl0cjVOdUk1UnBTcmEyRVFGT2FwYnRsQnU2OEFrVnc9PTwvZHNpZzpNb2R1bHVzPjxkc2lnOkV4cG9uZW50PkFRQUI8L2RzaWc6RXhwb25lbnQ%2BPC9kc2lnOlJTQUtleVZhbHVlPjwvZHNpZzpLZXlWYWx1ZT48L2RzaWc6S2V5SW5mbz48L2RzaWc6U2lnbmF0dXJlPjxzYW1sOk5hbWVJRCB4bWxuczpzYW1sPSJ1cm46b2FzaXM6bmFtZXM6dGM6U0FNTDoyLjA6YXNzZXJ0aW9uIiBGb3JtYXQ9InVybjpvYXNpczpuYW1lczp0YzpTQU1MOjIuMDpuYW1laWQtZm9ybWF0OnBlcnNpc3RlbnQiPmdzaTwvc2FtbDpOYW1lSUQ%2BPHNhbWxwOlNlc3Npb25JbmRleD5TVC04LXN6Y0haZHBhTVVXVTdvbGdkbG9OSG16R1BMVTk4MDMzNGNkMmYyZTwvc2FtbHA6U2Vzc2lvbkluZGV4Pjwvc2FtbHA6TG9nb3V0UmVxdWVzdD4%3D&RelayState=87085dac-1519-4b1f-b1da-abb7775cae77"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "HTTP/1.1 302 [\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "Cache-Control: no-cache, no-store, max-age=0, must-revalidate[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "Pragma: no-cache[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "Expires: 0[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "X-Content-Type-Options: nosniff[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "X-Frame-Options: DENY[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "X-XSS-Protection: 1; mode=block[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "Location: https://dev-cas-idp.myhost.com/cas/logout[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "Content-Length: 0[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "Date: Thu, 05 Dec 2019 22:36:47 GMT[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "Server: Apereo CAS[\r][\n]"
DEBUG [org.apache.http.wire] (default task-17) http-outgoing-0 << "[\r][\n]"
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << HTTP/1.1 302
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << Cache-Control: no-cache, no-store, max-age=0, must-revalidate
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << Pragma: no-cache
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << Expires: 0
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << X-Content-Type-Options: nosniff
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << X-Frame-Options: DENY
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << X-XSS-Protection: 1; mode=block
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << Location: https://dev-cas-idp.myhost.com/cas/logout
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << Content-Length: 0
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << Date: Thu, 05 Dec 2019 22:36:47 GMT
DEBUG [org.apache.http.headers] (default task-17) http-outgoing-0 << Server: Apereo CAS
DEBUG [org.apache.http.impl.execchain.MainClientExec] (default task-17) Connection can be kept alive indefinitely



Maksim Kopeyka

unread,
Mar 16, 2020, 7:46:39 PM3/16/20
to CAS Community
That's interesting. Backchannel logout works in case load balancer of CAS (nginx) doesn't use SSL however backchannel doesn't work in case nginx uses SSL.
I see the same output in console of CAS server in both cases (with SSL and without SSL)

Ray Bon

unread,
Mar 17, 2020, 11:44:35 AM3/17/20
to cas-...@apereo.org
Maksim,

Could this be a certificate issue?

If this is self signed certificate, you will need to add it to the java keystore (trust store). https://www.digitalocean.com/community/tutorials/java-keytool-essentials-working-with-java-keystores

Ray

On Mon, 2020-03-16 at 16:46 -0700, 'Maksim Kopeyka' via CAS Community wrote:
That's interesting. Backchannel logout works in case load balancer of CAS (nginx) doesn't use SSL however backchannel doesn't work in case nginx uses SSL.
I see the same output in console of CAS server in both cases (with SSL and without SSL)

-- 

Maksim Kopeyka

unread,
Mar 17, 2020, 5:49:34 PM3/17/20
to CAS Community
Ray,

I have had some issues related to self-signed certificate on my local env. CAS and Keycloak produced exception related to certificate and flow didn't work at all.
I regenerated certificate for domain instead of 127.0.0.1 and all exceptions were gone. So it's not an issue with certificate.
Also I have the same problem on real environment with real certificate. It also works fine without SSL but with SSL CAS session stay alive after logout in keycloak.

Maksim Kopeyka

unread,
Mar 18, 2020, 11:29:09 AM3/18/20
to CAS Community
I excluded nginx from my local env so I have only executable CAS.war and keycloak.
I configured CAS to use SSL in this way:

server.ssl.enabled=true
server
.ssl.key-store-type=JKS
server
.ssl.key-store=C:/Environment/jdk-11.0.5/bin/caskeystore.jks
server
.ssl.key-store-password=changeit
server
.ssl.key-alias=my.cas.com

Backchannel logout doesn't work. Looks like SSL causes this issue, doesn't matter it's nginx or embedded tomcat.

Maksim Kopeyka

unread,
Mar 24, 2020, 12:53:59 PM3/24/20
to CAS Community
I debugged CAS and found strange behavior
  1. Keycloak sends correct request to "/idp/profile/SAML2/POST/SLO" endpoint
  2. CAS sends redirect to "/cas/logout" in both cases (http and https) however session will be invalidated in http mode only
  3. Java code related to "/cas/logout" doesn't triggered however it triggers in case I call "/cas/logout" in browser
Why code related to "/cas/logout" doesn't triggered?
Reply all
Reply to author
Forward
0 new messages