Custom user storage provider with Entra ID group mapping - Duplicate key violation
#35 797 ouverte le 11 déc. 2024
Métriques du dépôt
- Stars
- (34 398 stars)
- Métriques de merge PR
- (Merge moyen 6j 19h) (384 PRs mergées en 30 j)
Description
Before reporting an issue
- I have read and understood the above terms for submitting issues, and I understand that my issue may be closed without action if I do not follow them.
Area
storage
Describe the bug
My setup:
I have a keycloak instance (latest version) with a custom user storage provider (AbstractUserAdapterFederatedStorage). Created based on https://github.com/keycloak/keycloak-quickstarts/tree/main/extension/user-storage-jpa. I went for a read-only
provider (implementing UserStorageProvider, UserLookupProvider, CredentialInputValidator and UserQueryProvider) . Groups are not saved in the custom provider but are saved in keycloak. Thats atleast how i understood it works.
I also configured a OIDC Identity provider with a mapping for groups.
The first login trough Entra ID works without any issue. The login is succesfull, and i see that the mapped group now contains 1 user. (I started from an empty group)
But when i logout and do the exact same login again i'm getting issues. With in the logging the error:
Exception executing batch [java.sql.BatchUpdateException: Violation of PRIMARY KEY constraint 'CONSTR_FED_USER_GROUP'. Cannot insert duplicate key in object 'dbo.FED_USER_GROUP_MEMBERSHIP'.
GUI screen:
Full logging:
2024-12-11 09:12:26,050 ERROR [org.hibernate.orm.jdbc.batch] (executor-thread-125) HHH100501: Exception executing batch [java.sql.BatchUpdateException: Violation of PRIMARY KEY constraint 'CONSTR_FED_USER_GROUP'. Cannot insert duplicate key in object 'dbo.FED_USER_GROUP_MEMBERSHIP'. The duplicate key value is (f648210a-a6a2-469d-9495-fe691bafb38e, f:f17e3959-2dde-42bf-afe8-4aef840c4589:68605FD7-3AB4-4E2D-B1EF-2F98E46343DD).], SQL: insert into FED_USER_GROUP_MEMBERSHIP (REALM_ID,STORAGE_PROVIDER_ID,GROUP_ID,USER_ID) values (?,?,?,?)
2024-12-11 09:12:26,050 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (executor-thread-125) SQL Error: 2627, SQLState: 23000
2024-12-11 09:12:26,050 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (executor-thread-125) Violation of PRIMARY KEY constraint 'CONSTR_FED_USER_GROUP'. Cannot insert duplicate key in object 'dbo.FED_USER_GROUP_MEMBERSHIP'. The duplicate key value is (f648210a-a6a2-469d-9495-fe691bafb38e, f:f17e3959-2dde-42bf-afe8-4aef840c4589:68605FD7-3AB4-4E2D-B1EF-2F98E46343DD).
2024-12-11 09:12:26,051 ERROR [org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider] (executor-thread-125) Failed to make identity provider oauth callback: org.keycloak.models.ModelDuplicateException: Duplicate resource error
at org.keycloak.connections.jpa.PersistenceExceptionConverter.convert(PersistenceExceptionConverter.java:103)
at org.keycloak.connections.jpa.PersistenceExceptionConverter.invoke(PersistenceExceptionConverter.java:68)
at jdk.proxy2/jdk.proxy2.$Proxy68.flush(Unknown Source)
at org.keycloak.storage.jpa.JpaUserFederatedStorageProvider.removeRequiredAction(JpaUserFederatedStorageProvider.java:528)
at org.keycloak.storage.adapter.AbstractUserAdapterFederatedStorage.removeRequiredAction(AbstractUserAdapterFederatedStorage.java:88)
at org.keycloak.authentication.requiredactions.VerifyUserProfile.evaluateTriggers(VerifyUserProfile.java:66)
at org.keycloak.services.managers.AuthenticationManager.evaluateRequiredAction(AuthenticationManager.java:1452)
at org.keycloak.services.managers.AuthenticationManager.lambda$evaluateRequiredActionTriggers$19(AuthenticationManager.java:1423)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1708)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151)
at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.base/java.util.stream.ReferencePipeline.forEachOrdered(ReferencePipeline.java:601)
at org.keycloak.services.managers.AuthenticationManager.evaluateRequiredActionTriggers(AuthenticationManager.java:1423)
at org.keycloak.services.managers.AuthenticationManager.nextRequiredAction(AuthenticationManager.java:1066)
at org.keycloak.services.resources.IdentityBrokerService.finishBrokerAuthentication(IdentityBrokerService.java:891)
at org.keycloak.services.resources.IdentityBrokerService.afterPostBrokerLoginFlowSuccess(IdentityBrokerService.java:866)
at org.keycloak.services.resources.IdentityBrokerService.finishOrRedirectToPostBrokerLogin(IdentityBrokerService.java:790)
at org.keycloak.services.resources.IdentityBrokerService.authenticated(IdentityBrokerService.java:643)
at org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider$Endpoint.authResponse(AbstractOAuth2IdentityProvider.java:568)
at org.keycloak.broker.oidc.AbstractOAuth2IdentityProvider$Endpoint$quarkusrestinvoker$authResponse_ab908fbdd086ee82e140d8a818c077362a2d04b4.invoke(Unknown Source)
at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:147)
at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:635)
at org.jboss.threads.EnhancedQueueExecutor$Task.doRunWith(EnhancedQueueExecutor.java:2516)
at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2495)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1521)
at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:11)
at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:11)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.sql.BatchUpdateException: Violation of PRIMARY KEY constraint 'CONSTR_FED_USER_GROUP'. Cannot insert duplicate key in object 'dbo.FED_USER_GROUP_MEMBERSHIP'. The duplicate key value is (f648210a-a6a2-469d-9495-fe691bafb38e, f:f17e3959-2dde-42bf-afe8-4aef840c4589:68605FD7-3AB4-4E2D-B1EF-2F98E46343DD).
at com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement.executeBatch(SQLServerPreparedStatement.java:2273)
at io.agroal.pool.wrapper.StatementWrapper.executeBatch(StatementWrapper.java:340)
at org.hibernate.engine.jdbc.batch.internal.BatchImpl.lambda$performExecution$2(BatchImpl.java:279)
at org.hibernate.engine.jdbc.mutation.internal.PreparedStatementGroupSingleTable.forEachStatement(PreparedStatementGroupSingleTable.java:67)
at org.hibernate.engine.jdbc.batch.internal.BatchImpl.performExecution(BatchImpl.java:264)
at org.hibernate.engine.jdbc.batch.internal.BatchImpl.execute(BatchImpl.java:242)
at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.executeBatch(JdbcCoordinatorImpl.java:188)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:674)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:511)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:414)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:41)
at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:127)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1429)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1415)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.keycloak.connections.jpa.PersistenceExceptionConverter.invoke(PersistenceExceptionConverter.java:66)
... 37 more
Seeing that the first login and adding the user to the group works without issue i think this is a bug in the federated storage in Keycloak.
Edit:
Extra info:
If i remove my Entra ID group, then i'm able to login again AND i'm also no longer a member of the mapped keycloak group.
So removing groups is also working correctly. The issue only seems to appear is i'm already a member of the group and still need to be a member.
Version
26.0.7
Regression
- The issue is a regression
Expected behavior
When logging in (first or after) trough a OIDC provider with group mapping the groups get assigned/removed correctly in a federated user storage setup.
Actual behavior
After the first login, logging in is not longer possible.
How to Reproduce?
Setup a keycloak instance with a custom OIDC provider with group mapping.
Setup a custom user storage provider (fe the quickstart example).
Try to login/logout multiple times with the OIDC provider.
Anything else?
No response