Git Product home page Git Product logo

keycloak-multi-tenancy's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

keycloak-multi-tenancy's Issues

Unable to remove membership

I get "Internal Server Error" when using the DELETE /tenants/${tenantId}/memberships/${memberId} endpoint on a fresh member.

Keycloak version 22.0.1
Keycloak-multi-tenancy version 22.0.0

Steps to reproduce:

  1. Create new tenant
  2. Invite new user
  3. User accepts invitation and login to the app
  4. Delete user

The keycloak logs shows error log:

Detail: Key (id)=(df2c5d55-5361-4b6a-85c7-42d624acc4c1) is still referenced from table "user_role_mapping".] [delete from USER_ENTITY where ID=?]
2023-08-30T09:35:26.906617491+02:00 	at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:95)
2023-08-30T09:35:26.906633630+02:00 	at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:56)
2023-08-30T09:35:26.906647820+02:00 	at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:108)
2023-08-30T09:35:26.906659930+02:00 	at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:278)
2023-08-30T09:35:26.906672940+02:00 	at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.performNonBatchedMutation(AbstractMutationExecutor.java:108)
2023-08-30T09:35:26.906686583+02:00 	at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleNonBatched.performNonBatchedOperations(MutationExecutorSingleNonBatched.java:40)
	at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:53)
2023-08-30T09:35:26.906714353+02:00 	at org.hibernate.persister.entity.mutation.DeleteCoordinator.doStaticDelete(DeleteCoordinator.java:300)
	at org.hibernate.persister.entity.mutation.DeleteCoordinator.coordinateDelete(DeleteCoordinator.java:87)
	at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2867)
	at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:131)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:606)
2023-08-30T09:35:26.906801047+02:00 	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
2023-08-30T09:35:26.906807420+02:00 	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:358)
2023-08-30T09:35:26.906813900+02:00 	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
2023-08-30T09:35:26.906820329+02:00 	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
2023-08-30T09:35:26.906832786+02:00 	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1412)
2023-08-30T09:35:26.906839187+02:00 	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:485)
2023-08-30T09:35:26.906845574+02:00 	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2301)
2023-08-30T09:35:26.906851874+02:00 	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1966)
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439)
2023-08-30T09:35:26.906864606+02:00 	at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.beforeCompletion(JtaTransactionCoordinatorImpl.java:336)
	at org.hibernate.resource.transaction.backend.jta.internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47)
2023-08-30T09:35:26.906877791+02:00 	at org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)
2023-08-30T09:35:26.906884098+02:00 	at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:76)
	at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:360)
	at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:91)
	at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162)
	at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1295)
2023-08-30T09:35:26.906921505+02:00 	at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:128)
2023-08-30T09:35:26.906929133+02:00 	at io.quarkus.narayana.jta.runtime.NotifyingTransactionManager.commit(NotifyingTransactionManager.java:70)
2023-08-30T09:35:26.907007242+02:00 	at org.keycloak.transaction.JtaTransactionWrapper.commit(JtaTransactionWrapper.java:90)
	at org.keycloak.services.DefaultKeycloakTransactionManager.commit(DefaultKeycloakTransactionManager.java:136)
2023-08-30T09:35:26.907046884+02:00 	at org.keycloak.services.DefaultKeycloakSession.closeTransactionManager(DefaultKeycloakSession.java:407)
2023-08-30T09:35:26.907061449+02:00 	at org.keycloak.services.DefaultKeycloakSession.close(DefaultKeycloakSession.java:372)
2023-08-30T09:35:26.907081949+02:00 	at org.keycloak.quarkus.runtime.transaction.TransactionalSessionHandler.close(TransactionalSessionHandler.java:56)
	at org.keycloak.quarkus.runtime.integration.jaxrs.TransactionalResponseFilter.filter(TransactionalResponseFilter.java:48)
2023-08-30T09:35:26.907144683+02:00 	at org.jboss.resteasy.core.interception.jaxrs.ContainerResponseContextImpl.filter(ContainerResponseContextImpl.java:329)
2023-08-30T09:35:26.907155941+02:00 	at org.jboss.resteasy.core.ServerResponseWriter.executeFilters(ServerResponseWriter.java:243)
	at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:100)
2023-08-30T09:35:26.907172239+02:00 	at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:73)
	at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:518)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:458)
	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:240)
2023-08-30T09:35:26.907223528+02:00 	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:154)
2023-08-30T09:35:26.907237010+02:00 	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:321)
2023-08-30T09:35:26.907246066+02:00 	at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:157)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:229)
	at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:82)
2023-08-30T09:35:26.907265424+02:00 	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:147)
	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:84)
	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:44)
2023-08-30T09:35:26.907288254+02:00 	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
2023-08-30T09:35:26.907302823+02:00 	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
2023-08-30T09:35:26.907316462+02:00 	at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
	at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:58)
2023-08-30T09:35:26.907347717+02:00 	at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:36)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
2023-08-30T09:35:26.907362099+02:00 	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
2023-08-30T09:35:26.907368520+02:00 	at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
2023-08-30T09:35:26.907375185+02:00 	at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$0(QuarkusRequestFilter.java:82)
2023-08-30T09:35:26.907381602+02:00 	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
2023-08-30T09:35:26.907390737+02:00 	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
2023-08-30T09:35:26.907410302+02:00 	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
2023-08-30T09:35:26.907424069+02:00 	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
2023-08-30T09:35:26.907454306+02:00 	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
2023-08-30T09:35:26.907468905+02:00 	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:833)
2023-08-30T09:35:26.907484513+02:00 Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on table "user_entity" violates foreign key constraint "fk_c4fqv34p1mbylloxang7b1q3l" on table "user_role_mapping"
2023-08-30T09:35:26.907490814+02:00   Detail: Key (id)=(df2c5d55-5361-4b6a-85c7-42d624acc4c1) is still referenced from table "user_role_mapping".
	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2713)
2023-08-30T09:35:26.907503696+02:00 	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2401)
2023-08-30T09:35:26.907545680+02:00 	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:368)
2023-08-30T09:35:26.907564595+02:00 	at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:498)
	at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:415)
2023-08-30T09:35:26.907590673+02:00 	at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:190)
	at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:152)
	at jdk.internal.reflect.GeneratedMethodAccessor127.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.postgresql.ds.PGPooledConnection$StatementHandler.invoke(PGPooledConnection.java:441)
2023-08-30T09:35:26.907647045+02:00 	at jdk.proxy2/jdk.proxy2.$Proxy93.executeUpdate(Unknown Source)
	at io.agroal.pool.wrapper.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:88)
2023-08-30T09:35:26.907673292+02:00 	at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:275)
	... 64 more
2023-08-30T09:35:26.907686485+02:00 
2023-08-30T09:35:26.908045499+02:00 2023-08-30 07:35:26,907 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-127) Uncaught server error: org.keycloak.models.ModelException: org.postgresql.util.PSQLException: ERROR: update or delete on table "user_entity" violates foreign key constraint "fk_c4fqv34p1mbylloxang7b1q3l" on table "user_role_mapping"
  Detail: Key (id)=(df2c5d55-5361-4b6a-85c7-42d624acc4c1) is still referenced from table "user_role_mapping".
	at org.keycloak.connections.jpa.PersistenceExceptionConverter.convert(PersistenceExceptionConverter.java:99)
	at org.keycloak.connections.jpa.JpaExceptionConverter.convert(JpaExceptionConverter.java:33)
2023-08-30T09:35:26.908088993+02:00 	at org.keycloak.transaction.JtaTransactionWrapper.lambda$handleException$0(JtaTransactionWrapper.java:65)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.HashMap$ValueSpliterator.forEachRemaining(HashMap.java:1779)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
2023-08-30T09:35:26.908135216+02:00 	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
2023-08-30T09:35:26.908142729+02:00 	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596)
	at org.keycloak.transaction.JtaTransactionWrapper.handleException(JtaTransactionWrapper.java:67)
	at org.keycloak.transaction.JtaTransactionWrapper.commit(JtaTransactionWrapper.java:92)
2023-08-30T09:35:26.908180667+02:00 	at org.keycloak.services.DefaultKeycloakTransactionManager.commit(DefaultKeycloakTransactionManager.java:136)
	at org.keycloak.services.DefaultKeycloakSession.closeTransactionManager(DefaultKeycloakSession.java:407)
	at org.keycloak.services.DefaultKeycloakSession.close(DefaultKeycloakSession.java:372)
	at org.keycloak.quarkus.runtime.transaction.TransactionalSessionHandler.close(TransactionalSessionHandler.java:56)
	at org.keycloak.quarkus.runtime.integration.jaxrs.TransactionalResponseFilter.filter(TransactionalResponseFilter.java:48)
2023-08-30T09:35:26.908212169+02:00 	at org.jboss.resteasy.core.interception.jaxrs.ContainerResponseContextImpl.filter(ContainerResponseContextImpl.java:329)
2023-08-30T09:35:26.908218676+02:00 	at org.jboss.resteasy.core.ServerResponseWriter.executeFilters(ServerResponseWriter.java:243)
2023-08-30T09:35:26.908224840+02:00 	at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:100)
2023-08-30T09:35:26.908231177+02:00 	at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:73)
	at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:518)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:458)
2023-08-30T09:35:26.908249803+02:00 	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:240)
2023-08-30T09:35:26.908256127+02:00 	at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:154)
2023-08-30T09:35:26.908262423+02:00 	at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:321)
2023-08-30T09:35:26.908292255+02:00 	at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:157)
	at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:229)
	at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:82)
2023-08-30T09:35:26.908311775+02:00 	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:147)
2023-08-30T09:35:26.908318071+02:00 	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:84)
2023-08-30T09:35:26.908324394+02:00 	at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:44)
2023-08-30T09:35:26.908331087+02:00 	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
	at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
	at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:58)
2023-08-30T09:35:26.908396442+02:00 	at io.quarkus.vertx.http.runtime.options.HttpServerCommonHandlers$1.handle(HttpServerCommonHandlers.java:36)
	at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1284)
	at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:177)
2023-08-30T09:35:26.908422719+02:00 	at io.vertx.ext.web.impl.RoutingContextWrapper.next(RoutingContextWrapper.java:200)
2023-08-30T09:35:26.908429966+02:00 	at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$0(QuarkusRequestFilter.java:82)
	at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
2023-08-30T09:35:26.908443252+02:00 	at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
2023-08-30T09:35:26.908449809+02:00 	at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
2023-08-30T09:35:26.908456034+02:00 	at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
2023-08-30T09:35:26.908462350+02:00 	at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
2023-08-30T09:35:26.908468669+02:00 	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
2023-08-30T09:35:26.908475370+02:00 	at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: org.postgresql.util.PSQLException: ERROR: update or delete on table "user_entity" violates foreign key constraint "fk_c4fqv34p1mbylloxang7b1q3l" on table "user_role_mapping"
2023-08-30T09:35:26.908488516+02:00   Detail: Key (id)=(df2c5d55-5361-4b6a-85c7-42d624acc4c1) is still referenced from table "user_role_mapping".
2023-08-30T09:35:26.908494729+02:00 	at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2713)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2401)
2023-08-30T09:35:26.908511510+02:00 	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:368)
	at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:498)
2023-08-30T09:35:26.908525196+02:00 	at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:415)
2023-08-30T09:35:26.908531506+02:00 	at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:190)
2023-08-30T09:35:26.908537825+02:00 	at org.postgresql.jdbc.PgPreparedStatement.executeUpdate(PgPreparedStatement.java:152)
2023-08-30T09:35:26.908544101+02:00 	at jdk.internal.reflect.GeneratedMethodAccessor127.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2023-08-30T09:35:26.908557113+02:00 	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.postgresql.ds.PGPooledConnection$StatementHandler.invoke(PGPooledConnection.java:441)
2023-08-30T09:35:26.908569895+02:00 	at jdk.proxy2/jdk.proxy2.$Proxy93.executeUpdate(Unknown Source)
	at io.agroal.pool.wrapper.PreparedStatementWrapper.executeUpdate(PreparedStatementWrapper.java:88)
2023-08-30T09:35:26.908582587+02:00 	at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:275)
	at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.performNonBatchedMutation(AbstractMutationExecutor.java:108)
	at org.hibernate.engine.jdbc.mutation.internal.MutationExecutorSingleNonBatched.performNonBatchedOperations(MutationExecutorSingleNonBatched.java:40)
2023-08-30T09:35:26.908614467+02:00 	at org.hibernate.engine.jdbc.mutation.internal.AbstractMutationExecutor.execute(AbstractMutationExecutor.java:53)
2023-08-30T09:35:26.908620777+02:00 	at org.hibernate.persister.entity.mutation.DeleteCoordinator.doStaticDelete(DeleteCoordinator.java:300)
2023-08-30T09:35:26.908627084+02:00 	at org.hibernate.persister.entity.mutation.DeleteCoordinator.coordinateDelete(DeleteCoordinator.java:87)
	at org.hibernate.persister.entity.AbstractEntityPersister.delete(AbstractEntityPersister.java:2867)
	at org.hibernate.action.internal.EntityDeleteAction.execute(EntityDeleteAction.java:131)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:606)
	at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475)
	at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:358)
	at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
	at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
2023-08-30T09:35:26.908677110+02:00 	at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1412)
2023-08-30T09:35:26.908683432+02:00 	at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:485)
	at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2301)
2023-08-30T09:35:26.908719397+02:00 	at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:1966)
	at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:439)
2023-08-30T09:35:26.908740284+02:00 	at org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorImpl.beforeCompletion(JtaTransactionCoordinatorImpl.java:336)
2023-08-30T09:35:26.908747329+02:00 	at org.hibernate.resource.transaction.backend.jta.internal.synchronization.SynchronizationCallbackCoordinatorNonTrackingImpl.beforeCompletion(SynchronizationCallbackCoordinatorNonTrackingImpl.java:47)
2023-08-30T09:35:26.908753716+02:00 	at org.hibernate.resource.transaction.backend.jta.internal.synchronization.RegisteredSynchronization.beforeCompletion(RegisteredSynchronization.java:37)
2023-08-30T09:35:26.908759948+02:00 	at com.arjuna.ats.internal.jta.resources.arjunacore.SynchronizationImple.beforeCompletion(SynchronizationImple.java:76)
	at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.beforeCompletion(TwoPhaseCoordinator.java:360)
	at com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator.end(TwoPhaseCoordinator.java:91)
2023-08-30T09:35:26.908778714+02:00 	at com.arjuna.ats.arjuna.AtomicAction.commit(AtomicAction.java:162)
2023-08-30T09:35:26.908784937+02:00 	at com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionImple.commitAndDisassociate(TransactionImple.java:1295)
2023-08-30T09:35:26.908791171+02:00 	at com.arjuna.ats.internal.jta.transaction.arjunacore.BaseTransaction.commit(BaseTransaction.java:128)
	at io.quarkus.narayana.jta.runtime.NotifyingTransactionManager.commit(NotifyingTransactionManager.java:70)
2023-08-30T09:35:26.908831433+02:00 	at org.keycloak.transaction.JtaTransactionWrapper.commit(JtaTransactionWrapper.java:90)

Problem trying to remove tenant

Hi @anarsultanov, I am having problems when I try to delete a created tenant. The error seems to be caused by the existing relationships between the tables, and when trying to delete a tenant it tells me that there are relationships with other tables on the record that I am trying to delete due to the foreign key constraint.

I attach an image where you can see the error it is giving me.
image

Do you know if I'm doing something wrong?

Thank you very much in advance

Error when calling membership endpoint with search query

When calling /tenants/{tenant_id}/[memberships?search=email%40example.com keycloak returns HTTP 400 'unknown_error'

Without the search query the endpoints returns the values correctly.

Keycloak version : 23.0.6 - with MySQL
keycloak-multi-tenancy version : 23.1.0

Rename a tenant

This is more of a feature request. Is it possible to rename a tenant? Ideally this would be a PUT endpoint on the API. This would be useful for users who did not know what the purpose of entering the tenant name and may want to change it in the future as they start adding other members.

How to obtain an access token using the Resource Owner Password Grant for users belonging to two or more tenants

Hello,

We are examining how your logic works.

I'd like to ask you a question.

There are two users:

  • alice: she belongs to a tenant.
  • bob: he belongs to two tenants.

If I try to obtain an access token on behalf of alice from the /token endpoint using Resource Owner Password Grant, it works as expected.

image

But when I try to obtain an access token on behalf of bob, it returns an error as shown below:

image

It works well when I try to log in using Authorization Code Grant.

image

Could you please let me know how I can obtain an access token for bob?

OpenAPI/Swagger documentation

First off, thank you have having a swagger doc. It really helps with auto-generating client code to work with it. That being said. I have noticed some inconsistencies.

  • PUT: /tenants/{tenantId}
    • You have a response type of 200 in the docs, however the actual response if 204
  • GET: /tenants/{tenantId}/memberships
    • The user object in the response is not defined as a schema.

There are others as well. I guess the ask is a review of the request payloads, response models, and status codes to ensure the API docs match the actual results.

Feature request - Include resource ID in all API POST endpoints

When creating new resources through the API the response only contains http status 201 (Created)
I would like to suggest to add the new resource's ID to the response. When using the API in a chained process there is an extra call to Keycloak needed that in my opinion should not be necessary
Imagine the following scenario: (javascript)

const newTenantId = await kcClient.createTenant({ "name": "new Tenant" })
await someNewResourceCreationThatDependsOnTenantId({ tenantId: newTenantId })

This would be the preferred way to use the API but because the new Tenant ID is not present in the response we have to do an additional call to Keycloak to chain code that depends on the new tenantId

await kcClient.createTenant({ "name": "new Tenant" })
const tenantArray = await kcClient.getTenants({ first: 0, max: 10, string: "new Tenant" })
await someNewResourceCreationThatDependsOnTenantId({ tenantId: tenantArray[0].id })

When including the id in the response the calls to Keycloak gets reduces by 50%

Multi-Tenancy Unknown error on enabling Tenant creation in Authentication

When attempting to enable the creation of tenants in the authentication section of my Keycloak instance, I'm encountering an unknown error. This error prevents me from successfully configuring multi-tenancy for my application.

Steps followed to enable Create tenant:

  1. Keycloak Admin Console
  2. Navigate to the authentication section.
  3. Enable th option for creating tenant
  4. Show unknown error message when tried log with user assigned.

image

image

I expect to be able to enable the creation of tenants without encountering any errors. This would allow me to configure multi-tenancy for my application as needed. However, an unknown error is displayed when attempting to enable the creation of tenants. This prevents me from proceeding with the multi-tenancy configuration.

I am using keycloak version 22.0.1

I would greatly appreciate any assistance in resolving this issue. If there's any further information required from my side, please let me know.

Thank you for your help!

REALM_ID, USER_ID, TENANT_ID with wrong varchar length

Hello, on https://github.com/anarsultanov/keycloak-multi-tenancy/blob/main/src/main/resources/META-INF/keycloak-multi-tenancy-changelog-20221217-2113.xml the ids REALM_ID, USER_ID, TENANT_ID are varchar(255) on line 14, 26 and 29. They should be 36. Indeed, when start on sql server it break everything and the entiry keycloack doesn't start. I fixed in my pc, i cannot push a branch or a suggestion on your repo so i write here. Also the plugin you deployed are broken with sql server. i suggest to fix.

Kind Regards
Paolo

CORS issue when calling endpoints directly from my app

Hello,

I have CORS issue when trying to call the APIs from my local frontend app
image

image

while it is perfectly working with kcadm commands or directly with postman using the same user/brearer. I can't understand why it is not working directly inside my angular app (simple http get query with the bearer header)

I suspected something wrong with the "Web origins" config inside my client, because when I remove the host header in postman I got the same error
image

I tried multiple value in the "Web origins" config without success.

I even tried with the realm "multi-tenant" json on the test resources but got the same error.

Sorry, I may have missed something but can't figure out why I can't reach your endpoints. Have you any idea ?

  • Keycloak version : 22.0.3
  • keycloak-multi-tenancy version : 22.2.0

Enhancement Request: Implement Role-Based Access Control for Tenant Creation Endpoint

Currently, the POST endpoint for creating a tenant doesn't have specific restrictions. This setup could potentially allow any user with API access to create new tenants.

Suggested Enhancement:
I propose implementing a role-based access control for the tenant creation endpoint. This would align with how Keycloak handles API management in general. In my current setup, I issue API tokens to my customers by creating a Keycloak client with a service account, using a predefined Keycloak client (named api-cli). This client is not allowed to interact with the Keycloak API unless I assign a service account role of realm-management - manage-clients.

Proposed Implementation:
For the tenancy API, I suggest a similar approach where a service account role (e.g., realm-management - manage-tenants) is required to manage tenant creation. This role would only be assigned to my predefined api-cli client. By doing so, it ensures that API tokens held by my customers cannot create tenants unless I explicitly add this role to their service account, which I intend not to do. In my application, creating a new tenant is a paid feature, and this change would add an extra layer of control and security.

Additional Consideration:
This suggestion needs some careful thought, especially in relation to the feature where users are forced to create a tenant if not a member of one. I have this feature disabled in my application, but the proposed enhancement should ideally be compatible with both scenarios.

Thank you for considering this enhancement. I believe it would be a valuable addition to the API.

Dependency Dashboard

This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.

Open

These updates have all been created already. Click a checkbox below to force a retry/rebase of any.

Detected dependencies

github-actions
.github/workflows/codeql.yml
  • actions/setup-java v4
  • actions/checkout v4
  • github/codeql-action v3
  • github/codeql-action v3
  • github/codeql-action v3
.github/workflows/release.yml
  • actions/checkout v4
  • actions/setup-java v4
  • codacy/git-version 2.8.0
  • mikepenz/release-changelog-builder-action v4
  • actions/upload-artifact v4
  • stefanzweifel/git-auto-commit-action v5
  • softprops/action-gh-release v1
.github/workflows/stale.yml
  • actions/stale v9
maven
pom.xml
  • org.keycloak:keycloak-server-spi 24.0.1
  • org.keycloak:keycloak-server-spi-private 24.0.1
  • org.keycloak:keycloak-services 24.0.1
  • org.keycloak:keycloak-model-jpa 24.0.1
  • org.keycloak:keycloak-admin-client 24.0.1
  • org.projectlombok:lombok 1.18.30
  • io.smallrye:smallrye-open-api-jaxrs 3.10.0
  • com.microsoft.playwright:playwright 1.41.2
  • org.junit.jupiter:junit-jupiter 5.10.2
  • org.assertj:assertj-core 3.25.3
  • org.testcontainers:junit-jupiter 1.19.6
  • com.github.dasniko:testcontainers-keycloak 3.2.0
  • com.github.javafaker:javafaker 1.0.2
  • org.apache.maven.plugins:maven-compiler-plugin 3.12.1
  • org.apache.maven.plugins:maven-shade-plugin 3.5.2
  • org.apache.maven.plugins:maven-surefire-plugin 3.2.5
  • me.fabriciorby:maven-surefire-junit5-tree-reporter 1.2.1
  • org.apache.maven.plugins:maven-failsafe-plugin 3.2.5
  • me.fabriciorby:maven-surefire-junit5-tree-reporter 1.2.1
  • io.smallrye:smallrye-open-api-maven-plugin 3.10.0
  • org.codehaus.mojo:versions-maven-plugin 2.16.2

  • Check this box to trigger a request for Renovate to run again on this repository

Unique password policy for each tenant

Hello, I am planning to implement Keycloak in a project and I would like to have different password policies defined for each tenant, does this extension allow me to do it?

Thank you so much for your attention.

Enhancement Request: Use of Action Token for Invitation Evaluation Triggers

Issue Description

Encountered a ModelDuplicateException when issuing a tenant invitation due to non-unique email addresses because the setting "Duplicate Emails" is enabled. Error message received:
Caused by: org.keycloak.models.ModelDuplicateException: Multiple users with email '[email protected]' exist in Keycloak.

Suggested Enhancement

Replace the reliance on unique email addresses for user identification with subject identifiers (sub token claim). This would resolve issues arising from shared email addresses and align better with OIDC standards. Additionally, suggest incorporating actionTokens to enable invite distribution through various transports, including SMS.

Rationale

Reliability: Subject identifiers provide a more reliable and unique method for user identification.
Flexibility: Accommodates scenarios where multiple users share the same email address and account linking disabled/enabled.
Transport Flexibility: ActionTokens enable sending invites via alternative methods, such as SMS, broadening the scope of user outreach.
OIDC Alignment: Better conforms to OIDC practices by utilizing standard token claims for identification.

I appreciate your feedback on this suggestion, particularly regarding the feasibility and implications of integrating actionTokens in this context. This should allow OIDC logins where email is not registered

Authenticator flow setup with IdpTenantMembershipsCreatingAuthenticator

I just want to verify the right setup of the sub-flows when using IdpTenantMembershipsCreatingAuthenticator. Should it be added as 1st flow in first broker login or I should create a new one that only using the authenticator? My usecase is to bypass the Review profile flow but I also have to customize the username that will be created in Keycloak without using from the IDP token. Thank you.

Help Needed : Linking Tenant to IDP

Based on your readme file,

"To configure an IDP as tenant-specific, tenants' IDs should be added to the multi-tenancy.tenants configuration attribute of the IDP as a comma-separated list. This can be achieved using the standard Keycloak REST API."

I'm trying to figure out how to link tenant to IDP.

I successfully created 2 tenants by consuming {{keycloakUrl}}/auth/realms/{{realmName}}/tenants endpoint.

Then, I create new user, use the user email to for invitation for on of the client. From what I can see, the user will able to view the invitation when they login to Keycloak. Is there any way the user can view the invitation? like received an email?

I also created a Microsoftt IDP.

I'm strugling to to link created tenant to an IDP based on the description above. Can you please specify which endpoint from the Keycloak Rest API to use for this purpose and example of the payload?

API returns 401

Hi, first of all thank you for the extension.

I've been trying to use the API but it always returns 401 Unauthorized no matter what I try.
I'm sure it's a mistake on my side, here's the request I do on Postman:

GET http://{keycloak_host}/realms/{realm}/tenants
Authorization: Basic user:pass

or with body

GET http://{keycloak_host}/realms/{realm}/tenants
x-www-form-encoded
username=user
password=pass

Feature Request: Customizable Terminology for Multi-Tenancy in Keycloak

I've been utilizing Keycloak for managing multi-tenancy in my platform, and while it has been an excellent tool, I've noticed a usability issue regarding the default terminology used for tenant management. Specifically, the term "Tenant" might not align with the language and context of all user bases.

Many platforms, including mine, use alternative terminology such as "Organization" to refer to what Keycloak terms as "Tenant." This inconsistency in language can lead to confusion among users, particularly during account creation or when selecting which "Tenant" to log into.

To enhance user experience and streamline the integration of Keycloak into various platforms, I propose the addition of an environment variable that allows developers to customize the term used for multi-tenancy. This would enable us to align Keycloak's language with the terminology utilized within our respective platforms.

I envision this feature as a simple configuration option, perhaps in the form of an environment variable like KEYCLOAK_MULTI_TENANCY_TERM, where developers can specify their preferred term (e.g., "Organization", "Workspace", etc.).

By providing this customization option, Keycloak can better accommodate diverse user bases and integrate seamlessly into a wider range of platforms. This enhancement would ultimately contribute to a more intuitive and user-friendly experience for all Keycloak users.

Thank you for considering my suggestion. I believe that implementing this feature would significantly improve the usability and flexibility of Keycloak in multi-tenant environments. I'm happy to provide further clarification or assistance as needed.

Invitation link

Hi. Great project! I would like to change the link sent to invited users. How is this done?

Right now it points to: ${keycloak_url}/auth/realms/${realm}/account
I need it to point to my application.

My app will redirect the user to login and/or show a message before login.
After login the invite confirmation is displayed to the user (if the user logged in with an account with the same email. I only use IDPs)

One additional feature request would be to use a action token instead of matching the email to validate if invite should be displayed to the user. Example:

  1. I invite user with email: [email protected]
  2. User receives email and navigate to invite page using invite link in email (Link to application and not keycloak but with action token in params)
  3. Application will redirect to keycloak login page where user can choose IDP. Step 3 can be skipped if user already is logged in.
  4. After login the user might have chosen to log in with an IDP with a different email then [email protected]. If keycloak somehow evaluates if the redirect URL contains an actiontoken (instead of evaluation against email) then the invite confirmation page can show.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.