b2b and b2c users best practices
by Adrian Matei
Hi guys,
Our requirements are the following:
- login one must decide if it is business or normal user
- at registration business users might have extra attributes
- users are persisted in AD, different OUs
I guess the cleanest solution would be to have different realms for each
category of users, but our constraint is that our CMS, that is the client
for the realm can define only one Identity Provider (via SAML)...
Would like to hear your thoughts.
Thanks,
Adrian
8 years, 8 months
Server fails to start with java.lang.StackOverflowError on infinispan.initializer.InfinispanUserSessionInitializer]
by Gerard Laissard
Team,
Keycloak server 1.9.0 fails to start.
Yesterday, I did try to play with client/role : Scope Param Required without any success.
I got server java.lang.StackOverflowError.
I stopped the server
Today when I start server, I have :
10:51:50,948 ERROR [org.keycloak.models.sessions.infinispan.initializer.InfinispanUserSessionInitializer] (ServerService Thread Pool -- 52) ExecutionException when computed future. Errors: 1: java.util.concurrent.ExecutionException: java.lang.StackOverflowError
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at org.keycloak.models.sessions.infinispan.initializer.InfinispanUserSessionInitializer.startLoading(InfinispanUserSessionInitializer.java:197)
at org.keycloak.models.sessions.infinispan.initializer.InfinispanUserSessionInitializer.loadPersistentSessions(InfinispanUserSessionInitializer.java:88)
at org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory$2.run(InfinispanUserSessionProviderFactory.java:91)
at org.keycloak.models.utils.KeycloakModelUtils.runJobInTransaction(KeycloakModelUtils.java:280)
at org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory.loadPersistentSessions(InfinispanUserSessionProviderFactory.java:82)
at org.keycloak.models.sessions.infinispan.InfinispanUserSessionProviderFactory$1.onEvent(InfinispanUserSessionProviderFactory.java:71)
at org.keycloak.services.DefaultKeycloakSessionFactory.publish(DefaultKeycloakSessionFactory.java:63)
at org.keycloak.services.resources.KeycloakApplication.<init>(KeycloakApplication.java:141)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.jboss.resteasy.core.ConstructorInjectorImpl.construct(ConstructorInjectorImpl.java:150)
at org.jboss.resteasy.spi.ResteasyProviderFactory.createProviderInstance(ResteasyProviderFactory.java:2209)
at org.jboss.resteasy.spi.ResteasyDeployment.createApplication(ResteasyDeployment.java:299)
at org.jboss.resteasy.spi.ResteasyDeployment.start(ResteasyDeployment.java:240)
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.init(ServletContainerDispatcher.java:113)
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.init(HttpServletDispatcher.java:36)
at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:117)
at org.wildfly.extension.undertow.security.RunAsLifecycleInterceptor.init(RunAsLifecycleInterceptor.java:78)
at io.undertow.servlet.core.LifecyleInterceptorInvocation.proceed(LifecyleInterceptorInvocation.java:103)
at io.undertow.servlet.core.ManagedServlet$DefaultInstanceStrategy.start(ManagedServlet.java:231)
at io.undertow.servlet.core.ManagedServlet.createServlet(ManagedServlet.java:132)
at io.undertow.servlet.core.DeploymentManagerImpl.start(DeploymentManagerImpl.java:526)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:101)
at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:82)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
at org.jboss.threads.JBossThread.run(JBossThread.java:320)
Caused by: java.lang.StackOverflowError
at org.jboss.jca.adapters.jdbc.WrappedConnection.checkException(WrappedConnection.java:1958)
at org.jboss.jca.adapters.jdbc.WrappedStatement.checkException(WrappedStatement.java:1446)
at org.jboss.jca.adapters.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:509)
at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70)
at org.hibernate.loader.Loader.getResultSet(Loader.java:2116)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1899)
at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1875)
at org.hibernate.loader.Loader.doQuery(Loader.java:919)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:336)
at org.hibernate.loader.Loader.doList(Loader.java:2611)
at org.hibernate.loader.Loader.doList(Loader.java:2594)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2423)
at org.hibernate.loader.Loader.list(Loader.java:2418)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:501)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:371)
at org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:216)
at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1326)
at org.hibernate.internal.QueryImpl.list(QueryImpl.java:87)
at org.hibernate.jpa.internal.QueryImpl.list(QueryImpl.java:606)
at org.hibernate.jpa.internal.QueryImpl.getResultList(QueryImpl.java:483)
at org.keycloak.models.jpa.ClientAdapter.getScopeMappings(ClientAdapter.java:246)
at org.keycloak.models.cache.entities.CachedClient.<init>(CachedClient.java:98)
at org.keycloak.models.cache.infinispan.locking.entities.RevisionedCachedClient.<init>(RevisionedCachedClient.java:18)
at org.keycloak.models.cache.infinispan.locking.LockingCacheRealmProvider.getClientById(LockingCacheRealmProvider.java:456)
at org.keycloak.models.cache.infinispan.RealmAdapter.getClientById(RealmAdapter.java:631)
at org.keycloak.models.jpa.RoleAdapter.getContainer(RoleAdapter.java:135)
at org.keycloak.models.cache.infinispan.locking.LockingCacheRealmProvider.getRoleById(LockingCacheRealmProvider.java:397)
at org.keycloak.models.cache.infinispan.RealmAdapter.getRoleById(RealmAdapter.java:543)
at org.keycloak.models.jpa.ClientAdapter.getScopeMappings(ClientAdapter.java:249)
at org.keycloak.models.cache.entities.CachedClient.<init>(CachedClient.java:98)
at org.keycloak.models.cache.infinispan.locking.entities.RevisionedCachedClient.<init>(RevisionedCachedClient.java:18)
at org.keycloak.models.cache.infinispan.locking.LockingCacheRealmProvider.getClientById(LockingCacheRealmProvider.java:456)
at org.keycloak.models.cache.infinispan.RealmAdapter.getClientById(RealmAdapter.java:631)
at org.keycloak.models.jpa.RoleAdapter.getContainer(RoleAdapter.java:135)
at org.keycloak.models.cache.infinispan.locking.LockingCacheRealmProvider.getRoleById(LockingCacheRealmProvider.java:397)
at org.keycloak.models.cache.infinispan.RealmAdapter.getRoleById(RealmAdapter.java:543)
at org.keycloak.models.jpa.ClientAdapter.getScopeMappings(ClientAdapter.java:249)
at org.keycloak.models.cache.entities.CachedClient.<init>(CachedClient.java:98)
at org.keycloak.models.cache.infinispan.locking.entities.RevisionedCachedClient.<init>(RevisionedCachedClient.java:18)
at org.keycloak.models.cache.infinispan.locking.LockingCacheRealmProvider.getClientById(LockingCacheRealmProvider.java:456)
at org.keycloak.models.cache.infinispan.RealmAdapter.getClientById(RealmAdapter.java:631)
at org.keycloak.models.jpa.RoleAdapter.getContainer(RoleAdapter.java:135)
at org.keycloak.models.cache.infinispan.locking.LockingCacheRealmProvider.getRoleById(LockingCacheRealmProvider.java:397)
at org.keycloak.models.cache.infinispan.RealmAdapter.getRoleById(RealmAdapter.java:543)
at org.keycloak.models.jpa.ClientAdapter.getScopeMappings(ClientAdapter.java:249)
at org.keycloak.models.cache.entities.CachedClient.<init>(CachedClient.java:98)
at org.keycloak.models.cache.infinispan.locking.entities.RevisionedCachedClient.<init>(RevisionedCachedClient.java:18)
at org.keycloak.models.cache.infinispan.locking.LockingCacheRealmProvider.getClientById(LockingCacheRealmProvider.java:456)
at org.keycloak.models.cache.infinispan.RealmAdapter.getClientById(RealmAdapter.java:631)
at org.keycloak.models.jpa.RoleAdapter.getContainer(RoleAdapter.java:135)
at org.keycloak.models.cache.infinispan.locking.LockingCacheRealmProvider.getRoleById(LockingCacheRealmProvider.java:397)
at org.keycloak.models.cache.infinispan.RealmAdapter.getRoleById(RealmAdapter.java:543)
at org.keycloak.models.jpa.ClientAdapter.getScopeMappings(ClientAdapter.java:249)
at org.keycloak.models.cache.entities.CachedClient.<init>(CachedClient.java:98)
...
What should I do ?
Thanks
Gerard
8 years, 8 months
Logouts / how to disable keycloak "user session" cache?
by Christian Schwarz
Hi!
I'm trying to setup a keycloak cluster on AWS, which does not support UDP multicast. IP addresses of the nodes are also not known in advance (I'm using docker-cloud), so Infinispan/JGroups ("keycloak-ha-posgres" docker image) for user session replication will not work (seems that it requires either UDP multicast or IP addresses known in advance).
The main problem I have is that logout is not working propertly. I only get logged out from one of the two keycloak nodes.
I have tried to disable the user cache (by setting userCache.default.enabled = false) and to disable infinispan (by using “keycloak-postgres” docker image), but to no avail. The “other” keycloak node still thinks that the user is logged in, it’s not refreshing the user session from the database even if user cache and infinispan cluster cache is disbled.
=> Is there a possibility of using the database as a synchronization point between keycloak nodes? (i.e. each node always checks logout status in the database)
Or is there another way of getting a keycloak cluster up and running on AWS when IP addresses are not known in advance?
I hope there is a way… :)
Kind regards,
Christian
8 years, 8 months
syncing users in database with keycloak user
by Juan Diego
Hi,
This is the first time I am using my users in another database, using
keycloak. And I am not sure what is the best approach. I have my app that
has a table users and other tables that depend on users.
When i did my trials I was thinking on using keycloak interface, but that
got me thinking that I should manually add the users to my database in
order for them to work, at least the ID of the user and then matched to
cookies once i loaded.
So the best approach I can think of is to create a login module or
something in my app and when I create users through my app they connect via
rest to my keycloak server and "duplicate" the needed data on keycloak and
my database. So If I need to delete something both databases would be on
sync. right? So if I want to add users to my app I shouldnt use the
keycloak interface, I should use mine right?
The other way I was thinking is that if it is the first time my users log
in, my app triggers some functions that recreate what you have on keycloak
Thanks
Juan Diego
8 years, 8 months
Realm Export in Clustered Environment
by Josh Cain
Hi All,
We're looking to take nightly realm backups of a clustered Keycloak
deployment via the realm export feature. However, in reading through the
docs
<http://keycloak.github.io/docs/userguide/keycloak-server/html/export-impo...>,
I came across this statement:
The fact it's done at server startup means that no-one can access Keycloak
UI or REST endpoints and edit Keycloak database on the fly when export or
import is in progress. Otherwise it could lead to inconsistent results.
What are the implications for this in a clustered environment? We were
planning to take a single server down and use it for realm export. Will
this operation be reliable with other servers running?
Josh Cain | Software Applications Engineer
*Identity and Access Management*
*Red Hat*
+1 843-737-1735
8 years, 8 months
Keycloak Integration with WSO2
by Jon Rathbone
Hi there,
I’m trying to understand if it is possible to integrate KeyCloak with WSO2.
The context is that I have one suite of applications with SSO using KeyCloak, and I have a requirement to integrate that suite of applications with another, which is using WSO2 as an identity provider for SSO. At this stage I don’t need to achieve SSO across both app suites with this solution, although that might be required in the future.
I’d like to understand if it is possible to use Keycloak to federate out to WSO2 for IDP. I think the answer is yes, based on what I’ve read, but my searching hasn’t turned up any concrete examples.
Has anyone done this, or have enough experience with the respective products to be confident that it would or wouldn’t work?
If yes, what would be a good integration approach.
Sincere thanks.
Jon
8 years, 8 months
Admin REST API Get Users (and search) returns enabled user ("enabled":true) after "Max Login Failures" exceeded
by Juraj Janosik
Hi,
is the following issue known in the community? (see description below)
*Prerequisities:*
1. Keycloak 1.9.1.Final, CentOS7, Oracle12c
2. User disabled after "Max Login Failure" attempts.
*Observed behavior:*
1. User displayed correctly as disabled ("enabled":false) via Get
Representation of the user
GET /admin/realms/{realm}/users/{id}
2. User displayed correctly as disabled ("disabled":true) via
GET /admin/realms/{realm}/attack-detection/brute-force/usernames/{username}
3. User displayed not correctly ("enabled":true) via Get users (list of all
users and search)
GET /admin/realms/{realm}/users
GET /admin/realms/{realm}/users?search={string}
Thanks a lot.
Best Regards,
Juraj
8 years, 8 months
SSO amongst two realms
by Sarp Kaya
Hi,
I want to know whether it is possible to have SSO amongst two realms. Ie User 1 logins to an app1 that auths against realm1, then user 1 tries to use app2 which auths against realm2 which should work fine as user 1 logged into realm1 before and it should SSO into app2 fine.
If this is possible then what would be the setup like?
Kind Regards,
Sarp
8 years, 8 months
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
by Juan Diego
I installed a keycloak server on amazon and bought a cert from Komodo. And
I was testing my app from my localhost, so my webapp in jsf is supposed to
log against that server and it seems to work. I modified my web.xml so the
loign-config uses keycloak.
I thought my localserver ssl was the problem but I disabled
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
But I got the same error.
17:49:20,443 ERROR [org.keycloak.adapters.OAuthRequestAuthenticator]
(default task-49) failed to turn code into token:
javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find
valid certification path to requested target
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
at
sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
at
sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
at
sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
at
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
at
sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
at
org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:543)
at
org.keycloak.adapters.SniSSLSocketFactory.connectSocket(SniSSLSocketFactory.java:109)
at
org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:409)
at
org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:177)
at
org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:144)
at
org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:131)
at
org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:611)
at
org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:446)
at
org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:882)
at
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
at
org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
at
org.keycloak.adapters.ServerRequest.invokeAccessCodeToToken(ServerRequest.java:107)
at
org.keycloak.adapters.OAuthRequestAuthenticator.resolveCode(OAuthRequestAuthenticator.java:314)
at
org.keycloak.adapters.OAuthRequestAuthenticator.authenticate(OAuthRequestAuthenticator.java:260)
at
org.keycloak.adapters.RequestAuthenticator.authenticate(RequestAuthenticator.java:112)
at
org.keycloak.adapters.undertow.AbstractUndertowKeycloakAuthMech.keycloakAuthenticate(AbstractUndertowKeycloakAuthMech.java:110)
at
org.keycloak.adapters.undertow.ServletKeycloakAuthMech.authenticate(ServletKeycloakAuthMech.java:92)
at
io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:233)
at
io.undertow.security.impl.SecurityContextImpl$AuthAttempter.transition(SecurityContextImpl.java:250)
at
io.undertow.security.impl.SecurityContextImpl$AuthAttempter.access$100(SecurityContextImpl.java:219)
at
io.undertow.security.impl.SecurityContextImpl.attemptAuthentication(SecurityContextImpl.java:121)
at
io.undertow.security.impl.SecurityContextImpl.authTransition(SecurityContextImpl.java:96)
at
io.undertow.security.impl.SecurityContextImpl.authenticate(SecurityContextImpl.java:89)
at
io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:55)
at
io.undertow.server.handlers.DisableCacheHandler.handleRequest(DisableCacheHandler.java:33)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51)
at
io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at
io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at
io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56)
at
io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at
io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at
io.undertow.security.handlers.NotificationReceiverHandler.handleRequest(NotificationReceiverHandler.java:50)
at
io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
org.keycloak.adapters.undertow.ServletPreAuthActionsHandler.handleRequest(ServletPreAuthActionsHandler.java:69)
at
io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at
io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:284)
at
io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:263)
at
io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:81)
at
io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:174)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:202)
at
io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:793)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: sun.security.validator.ValidatorException: PKIX path building
failed: sun.security.provider.certpath.SunCertPathBuilderException: unable
to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
at
sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
at sun.security.validator.Validator.validate(Validator.java:260)
at
sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
at
sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
at
sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
at
sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
... 56 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
at
sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
at
sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
... 62 more
For what I understand it is because my java doesnt perceives my Cert as a
proper CA signed cert.
Thanks,
Juan diego
8 years, 8 months
Re: [keycloak-user] spring security adapter and single log out
by Brose, Sascha
Hi Anthony,
we noticed the same issue and your report helped a lot. Thank you very much!
I perceived that logout will not work correctly when you have multiple active sessions and an user logs out. In that case, HttpSessionManager::logoutHttpSessions is called which clears the references to all known sessions with sessions.clear(). Additionally, destroyed sessions weren't removed from ServiceRegistryImpl. This seems to be because ServiceRegistryImpl created in WebSecurityConfig is no Spring Bean. Therefore, I did two adjustments to the code you provided:
1) HttpSessionManager: Removed sessions.clear() at the end of logoutHttpSessions(List<String>)
2) WebSecurityConfig: Replaced
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
}
with
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new RegisterSessionAuthenticationStrategy(buildSessionRegistry());
}
@Bean
protected SessionRegistry buildSessionRegistry() {
return new SessionRegistryImpl();
}
Best, Sascha
-----Ursprüngliche Nachricht-----
Von: keycloak-user-bounces(a)lists.jboss.org [mailto:keycloak-user-bounces@lists.jboss.org] Im Auftrag von keycloak-user-request(a)lists.jboss.org
Gesendet: Dienstag, 22. März 2016 18:35
An: keycloak-user(a)lists.jboss.org
Betreff: keycloak-user Digest, Vol 27, Issue 98
Send keycloak-user mailing list submissions to
keycloak-user(a)lists.jboss.org
To subscribe or unsubscribe via the World Wide Web, visit
https://lists.jboss.org/mailman/listinfo/keycloak-user
or, via email, send a message with subject or body 'help' to
keycloak-user-request(a)lists.jboss.org
You can reach the person managing the list at
keycloak-user-owner(a)lists.jboss.org
When replying, please edit your Subject line so it is more specific than "Re: Contents of keycloak-user digest..."
Today's Topics:
1. Re: spring security adapter and single log out (Scott Rossillo)
----------------------------------------------------------------------
Message: 1
Date: Tue, 22 Mar 2016 13:34:41 -0400
From: Scott Rossillo <srossillo(a)smartling.com>
Subject: Re: [keycloak-user] spring security adapter and single log
out
To: Anthony Fryer <Anthony.Fryer(a)virginaustralia.com>
Cc: Niels Bertram <Niels.Bertram(a)virginaustralia.com>, "keycloak-user
\(keycloak-user(a)lists.jboss.org\)" <keycloak-user(a)lists.jboss.org>
Message-ID: <6E696A99-A3D8-43C4-8D72-3BE00CB304CA(a)smartling.com>
Content-Type: text/plain; charset="utf-8"
Hi Anthony,
Thanks for the very descriptive bug report. I?ll have a look at fixing this shortly.
Scott Rossillo
Smartling | Senior Software Engineer
srossillo(a)smartling.com
> On Mar 21, 2016, at 7:26 PM, Anthony Fryer <Anthony.Fryer(a)virginaustralia.com> wrote:
>
> I?ve noticed some issues when testing single logout with the spring security adapter.
>
> I setup the admin url for the test application that used the spring security adapter in keycloak and tested logging out from keycloak and it didn?t invalidate the session. This is consistent with what I saw in other environments while testing. I did some digging and found that the spring adapter isn?t working correctly for single log out in my environments. We?re not using spring boot so not sure if that might be a reason why its not working out of the box.
>
> The issue is with the org.keycloak.adapters.springsecurity.management.HtttpSessionManager class. This implements javax.servlet.http.HttpSessionListener to receive events when sessions are created and stores the sessions in a hash map. When you do a logout from keycloak, it sends a POST request to <admin_url>/k_logout. This results in a call to the HttpSessionManager.logoutHttpSessions method with the session id passed in as an argument. This method attempts to lookup the session in the hashmap and call the invalidate() method.
>
> The problem is by default the HttpSessionManager class isn?t receiving the session create events. You need to configure it as a listener in web.xml to enable that. But even if you do that it still doesn?t work because the servlet container will create a instance of the class, but spring will also create another instance when creating the keycloak beans and this new instance is the one passed into the KeycloakPreAuthActionsFilter constructor. So the instance that is created by the servlet container is the one receiving the session create event and the one used by spring isn?t receiving any events but is the one used to do the logoutHttpSessions() call. The spring instance has no sessions in the hashmap, so logoutHttpSessions() does nothing.
>
> The fix is to make a new version of HttpSessionManager that implements org.keycloak.adapters.spi.UserSessionManagement andorg.springframework.context.ApplicationListener<ApplicationEvent>, which is a spring interface that receives session create/destroy events. In web.xml you need to register org.springframework.security.web.session.HttpSessionEventPublisher as a listener so spring will receive those events from the servlet container. Then in the spring config, you need the KeycloakPreAuthActionsFilter to be initialized with the new HttpSessionManager instead of the default one.
>
> The HttpSessionManager class that works for me is below?
>
> package my.keycloak;
>
> import java.util.List;
>
> import javax.servlet.http.HttpSession;
>
> import org.keycloak.adapters.spi.UserSessionManagement;
> import
> org.keycloak.adapters.springsecurity.management.LocalSessionManagement
> Strategy; import
> org.keycloak.adapters.springsecurity.management.SessionManagementStrat
> egy;
> import org.slf4j.Logger;
> import org.slf4j.LoggerFactory;
> import org.springframework.context.ApplicationEvent;
> import org.springframework.context.ApplicationListener;
> import
> org.springframework.security.web.session.HttpSessionCreatedEvent;
> import
> org.springframework.security.web.session.HttpSessionDestroyedEvent;
>
> public class HttpSessionManager implements UserSessionManagement,
> ApplicationListener<ApplicationEvent> {
>
> private static final Logger log = LoggerFactory.getLogger(HttpSessionManager.class);
> private SessionManagementStrategy sessions = new
> LocalSessionManagementStrategy();
>
> @Override
> public void logoutAll() {
> log <http://log.info/>.info <http://log.info/>("Received request to log out all users.");
> for (HttpSession session : sessions.getAll()) {
> session.invalidate();
> }
> sessions.clear();
> }
>
> @Override
> public void logoutHttpSessions(List<String> ids) {
> log <http://log.info/>.info <http://log.info/>("Received request to log out {} session(s): {}", ids.size(), ids);
> for (String id : ids) {
> HttpSession session = sessions.remove(id);
> if (session != null) {
> session.invalidate();
> }
> }
> sessions.clear();
> }
>
> @Override
> public void onApplicationEvent(ApplicationEvent event) {
> if (event instanceof HttpSessionCreatedEvent) {
> HttpSessionCreatedEvent e = (HttpSessionCreatedEvent)event;
> HttpSession session = e.getSession();
> log.debug("Session created: {}", session.getId());
> sessions.store(session);
> } else if (event instanceof HttpSessionDestroyedEvent) {
> HttpSessionDestroyedEvent e = (HttpSessionDestroyedEvent)event;
> HttpSession session = e.getSession();
> sessions.remove(session.getId());
> log.debug("Session destroyed: {}",
> session.getId());
>
> }
>
> }
>
> }
>
>
> The keycloak config changes are below?
>
> @Configuration
> @EnableWebSecurity
> @ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
> public class WebSecurityConfig extends
> KeycloakWebSecurityConfigurerAdapter {
>
> @Autowired
> public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
> auth.authenticationProvider(keycloakAuthenticationProvider());
> }
>
>
> @Override
> protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
> return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
> }
>
> @Bean
> protected KeycloakPreAuthActionsFilter keycloakPreAuthActionsFilter() {
> return new KeycloakPreAuthActionsFilter(springHttpSessionManager());
> }
>
>
> @Bean
> protected my.keycloak.HttpSessionManager springHttpSessionManager() {
> return new my.keycloak.HttpSessionManager();
> }
>
>
>
> @Override
> protected void configure(HttpSecurity http) throws Exception {
> super.configure(http);
>
>
> http
> .logout()
> .logoutRequestMatcher(new AntPathRequestMatcher("/sso/logout"))
> .and()
> .authorizeRequests()
> .antMatchers("/user*").authenticated()
> .anyRequest().permitAll();
> }
> }
>
> and web.xml needs this added to it?
>
> <listener>
> <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
> </listener>
>
> After making the above changes, log out from the keycloak admin console works as expected.
>
> Regards,
>
> Anthony Fryer
>
> The content of this e-mail, including any attachments, is a confidential communication between Virgin Australia Airlines Pty Ltd (Virgin Australia) or its related entities (or the sender if this email is a private communication) and the intended addressee and is for the sole use of that intended addressee. If you are not the intended addressee, any use, interference with, disclosure or copying of this material is unauthorized and prohibited. If you have received this e-mail in error please contact the sender immediately and then delete the message and any attachment(s). There is no warranty that this email is error, virus or defect free. This email is also subject to copyright. No part of it should be reproduced, adapted or communicated without the written consent of the copyright owner. If this is a private communication it does not represent the views of Virgin Australia or its related entities. Please be aware that the contents of any emails sent to or from Virgin Austr!
alia or its related entities may be periodically monitored and reviewed. Virgin Australia and its related entities respect your privacy. Our privacy policy can be accessed from our website: www.virginaustralia.com <http://www.virginaustralia.com/>_______________________________________________
> keycloak-user mailing list
> keycloak-user(a)lists.jboss.org <mailto:keycloak-user@lists.jboss.org>
> https://lists.jboss.org/mailman/listinfo/keycloak-user
> <https://lists.jboss.org/mailman/listinfo/keycloak-user>
8 years, 8 months