Duplicate key exception when adding a user to a group - keycloak

I've written an EventListenerProvider designed to automatically add a new user to a group after the user completes registration. The EventListenerProvider looks for the REGISTER event and invokes some code that gets the UserModel:
UserModel user = session.getContext().getAuthenticationSession().getAuthenticatedUser();
the group is created if it doesn't exist:
group = session.getContext().getRealm().createGroup(groupName);
and then the user is added to the group:
user.joinGroup(group);
The problem is that for some reason, joinGroup results in an INSERT on the user_entity table using the same id as the user that was supposedly created during registration. This results in a unique key violation with the following partial stack trace:
keycloak_1 | 22:44:17,992 WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-1) SQL Error: 0, SQLState: 23505
keycloak_1 | 22:44:17,992 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-1) ERROR: duplicate key value violates unique constraint "constraint_fb"
keycloak_1 | Detail: Key (id)=(3e707ca2-6311-4d0b-bd56-786746b172f0) already exists.
keycloak_1 | 22:44:17,993 ERROR [org.keycloak.events.EventBuilder] (default task-1) Failed to send type to com.abinitio.sso.keycloak.event.EventListener#4d6c5c44: org.keycloak.models.ModelDuplicateException: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
keycloak_1 | at org.keycloak.keycloak-model-jpa#10.0.1//org.keycloak.connections.jpa.PersistenceExceptionConverter.convert(PersistenceExceptionConverter.java:57)
keycloak_1 | at org.keycloak.keycloak-model-jpa#10.0.1//org.keycloak.connections.jpa.PersistenceExceptionConverter.invoke(PersistenceExceptionConverter.java:51)
keycloak_1 | at javax.persistence.api#2.2.3//com.sun.proxy.$Proxy95.flush(Unknown Source)
keycloak_1 | at org.keycloak.keycloak-model-jpa#10.0.1//org.keycloak.models.jpa.UserAdapter.joinGroupImpl(UserAdapter.java:389)
The Postgres log shows the following:
postgres_1 | 2020-05-20 22:44:17.991 UTC [34] ERROR: duplicate key value violates unique constraint "constraint_fb"
postgres_1 | 2020-05-20 22:44:17.991 UTC [34] DETAIL: Key (id)=(3e707ca2-6311-4d0b-bd56-786746b172f0) already exists.
postgres_1 | 2020-05-20 22:44:17.991 UTC [34] STATEMENT: insert into public.USER_ENTITY (CREATED_TIMESTAMP, EMAIL, EMAIL_CONSTRAINT, EMAIL_VERIFIED, ENABLED, FEDERATION_LINK, FIRST_NAME, LAST_NAME, NOT_BEFORE, REALM_ID, SERVICE_ACCOUNT_CLIENT_LINK, USERNAME, ID) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)
I'm not quite sure why the joinGroup call results in an INSERT on the user_entity table.
After this error, the user that was registering is not in the DB. So I'm assuming the user create resulting from registration was never committed. Perhaps this was still pending which is why the INSERT on the user_entity table happens when joinGroup tried to commit? I tried calling EntityManager.flush() just prior to call joinGroup(), but this didn't solve the problem.
Hopeful for some suggestions...

Related

Change user role in keycloke after update in existing db

I implemented User storage SPI to use keycloak with an existing user DB, but I ran into this problem: when updating roles in my DB, roles in keycloak are not updated and all my attempts to fix this lead to errors, for example i try do disable the cache for User Federation, an error after disabling the cache:
21:37:46,556 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-3) Uncaught server error: java.lang.NullPointerException
at org.keycloak.keycloak-server-spi-private#9.0.2//org.keycloak.models.utils.KeycloakModelUtils.resolveAttribute(KeycloakModelUtils.java:415)
at org.keycloak.keycloak-services#9.0.2//org.keycloak.protocol.oidc.mappers.UserAttributeMapper.setClaim(UserAttributeMapper.java:101)
at org.keycloak.keycloak-services#9.0.2//org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.setClaim(AbstractOIDCProtocolMapper.java:119)
at org.keycloak.keycloak-services#9.0.2//org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper.transformAccessToken(AbstractOIDCProtocolMapper.java:81)
at org.keycloak.keycloak-services#9.0.2//org.keycloak.protocol.oidc.TokenManager.transformAccessToken(TokenManager.java:556)
at org.keycloak.keycloak-services#9.0.2//org.keycloak.protocol.oidc.TokenManager.createClientAccessToken(TokenManager.java:415)
I found a workaround to solve this problem - override the getAttribute method from the UserModel interface: workaround and then got this error:
21:42:05,659 ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper] (default task-3) Unique index or primary key violation: "PRIMARY_KEY_41 ON PUBLIC.FED_USER_ROLE_MAPPING(ROLE_ID, USER_ID) VALUES ('3cc65575-ba9b-4248-8601-bf4a9413cb17', 'f:cbd0e1b7-c6ed-4bd2-a4eb-b47fd8201ca8:1', 1)"; SQL statement:
insert into FED_USER_ROLE_MAPPING (REALM_ID, STORAGE_PROVIDER_ID, ROLE_ID, USER_ID) values (?, ?, ?, ?) [23505-193]
21:42:05,661 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (default task-3) Uncaught server error: javax.persistence.PersistenceException: org.hibernate.exception.ConstraintViolationException: could not execute statement
at org.hibernate#5.3.13.Final//org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:154)
at org.hibernate#5.3.13.Final//org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1515)
if i enable the cache, then on the first request of the token I get the same error as above, and on all subsequent ones I just get the token, but the roles do not match mine from DB. What i can do with it? Thanks.

Executed create index concurrently statmt & it was disconnected session due to timeout error.but I do see in pg_stat_activity,it is in running state

I have executed create an index on a big table from pgAdmin, and in a while, I lost connection to the server, so the execution window closed in pgAdnin. Then I reconnected to the server, and when checked pg_stat_activity, I do see that the create index statement is running (active) state, I just wondering to know whether this index being creating or stuck somewhere?
client disconnected with error,
cancelling statement due to statement timeout
when I reconnected to the server, in pg_stat_activity.
31937 "edsadmin" "09:54:44.280176" "CREATE INDEX CONCURRENTLY idx_src_record_date
ON pcd_t.l_esd_detail_report USING btree
(src_record_date COLLATE pg_catalog."default")
TABLESPACE pg_default;"
I'm really confused here wheather it is createing or not.
Late answer, but relevant none-the-less.
Based on my anecdotal experience right now, the index creation persists beyond the lifetime of the client.
I did the following:
database=> CREATE INDEX CONCURRENTLY IX_myIndex on table(column, column2);
It paused for a few minutes, then:
SSL SYSCALL error: EOF detected
The connection to the server was lost. Attempting reset: Succeeded.
psql (14.2 (Debian 14.2-1.pgdg110+1), server 10.18)
Immediately after reconnecting, I ran:
database=> \d table
Table "public.table"
Column | Type | Collation | Nullable |
Default
-----------------+-----------------------------+-----------+----------+---------
... blah blah blah ...
Indexes:
"IX_myIndex" btree (column, column2) INVALID
I waited a few more minutes, then checked again:
database=> \d table
Table "public.table"
Column | Type | Collation | Nullable |
Default
-----------------+-----------------------------+-----------+----------+---------
... blah blah blah ...
Indexes:
"IX_myIndex" btree (column, column2)
So, your index is likely fine.

Keycloak not able to start --version 3.4.1.cR1

When Keycloak is trying to start, it is unable to start. The Following error is thrown in the logs :
ERROR
[org.keycloak.connections.jpa.updater.liquibase.conn.DefaultLiquibaseConnectionProvider]
(ServerService Thread Pool -- 53) Change Set
META-INF/jpa-changelog-1.5.0.xml::1.5.0::bburke#redhat.com failed.
Error: Column "USER_SETUP_ALLOWED" not found; SQL statement: ALTER
TABLE PUBLIC.AUTHENTICATION_EXECUTION ALTER COLUMN USER_SETUP_ALLOWED
SET DEFAULT NULL [42122-193] [Failed SQL: ALTER TABLE
PUBLIC.AUTHENTICATION_EXECUTION ALTER COLUMN USER_SETUP_ALLOWED SET
DEFAULT NULL]: liquibase.exception.DatabaseException: Column
"USER_SETUP_ALLOWED" not found; SQL statement: ALTER TABLE
PUBLIC.AUTHENTICATION_EXECUTION ALTER COLUMN USER_SETUP_ALLOWED SET
DEFAULT NULL [42122-193] [Failed SQL: ALTER TABLE
PUBLIC.AUTHENTICATION_EXECUTION ALTER COLUMN USER_SETUP_ALLOWED SET
DEFAULT NULL]
at liquibase.executor.jvm.JdbcExecutor$ExecuteStatementCallback.doInStatement(JdbcExecutor.java:316)
at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:55)
at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:122)
at liquibase.database.AbstractJdbcDatabase.execute(AbstractJdbcDatabase.java:1247

Duplicate key value violates unique constraint "pk_jhi_persistent_audit_event" with JHipster on Heroku

I recently upgraded a JHipster 2.x application to 4.x as part of writing the JHipster Mini-Book's sample application. Lately, I've been experiencing quite a few issues with login and registration. It seems to be caused by the sequence keys in some of the auditing tables:
ERROR: duplicate key value violates unique constraint "pk_jhi_persistent_audit_event"
Full log:
2017-12-19T02:44:25.564551+00:00 app[web.1]: 2017-12-19 02:44:25.564 WARN 4 --- [ XNIO-2 task-26] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: 23505
2017-12-19T02:44:25.564734+00:00 app[web.1]: 2017-12-19 02:44:25.564 ERROR 4 --- [ XNIO-2 task-26] o.h.engine.jdbc.spi.SqlExceptionHelper : ERROR: duplicate key value violates unique constraint "pk_jhi_persistent_audit_event"
2017-12-19T02:44:25.564737+00:00 app[web.1]: Detail: Key (event_id)=(42094) already exists.
2017-12-19T02:44:25.565215+00:00 app[web.1]: 2017-12-19 02:44:25.565 ERROR 4 --- [ XNIO-2 task-26] o.h.i.ExceptionMapperStandardImpl : HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
2017-12-19T02:44:25.567741+00:00 app[web.1]: 2017-12-19 02:44:25.567 ERROR 4 --- [ XNIO-2 task-26] o.j.h.w.rest.errors.ExceptionTranslator : An unexpected error occurred: could not execute statement; SQL [n/a]; constraint [pk_jhi_persistent_audit_event]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
2017-12-19T02:44:27.820781+00:00 heroku[web.1]: Process running mem=523M(102.1%)
2017-12-19T02:44:27.820897+00:00 heroku[web.1]: Error R14 (Memory quota exceeded)
2017-12-19T02:44:25.571359+00:00 heroku[router]: at=info method=POST path="/api/authenticate" host=www.21-points.com request_id=b54f7527-7479-42ee-acaa-d6794567c118 fwd="75.171.150.21" dyno=web.1 connect=0ms service=156ms status=500 bytes=550 protocol=https
Is it possible to reset the sequences for these tables, or move to a guid-based system that won't have collisions? I'm using PostgreSQL on Heroku.
The workaround I adopted was to set a rollbackFor=Exception.class in my CustomAuditEventRepository
It catch the exception and just rollback the transaction: so the login audit event will not be saved, but at least you are not going to have annoying exceptions that lock the app.
#Override
#Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor=Exception.class)
public void add(AuditEvent event) {
if (!AUTHORIZATION_FAILURE.equals(event.getType()) &&
!Constants.ANONYMOUS_USER.equals(event.getPrincipal())) {
PersistentAuditEvent persistentAuditEvent = new PersistentAuditEvent();
persistentAuditEvent.setPrincipal(event.getPrincipal());
persistentAuditEvent.setAuditEventType(event.getType());
persistentAuditEvent.setAuditEventDate(event.getTimestamp());
Map<String, String> eventData = auditEventConverter.convertDataToStrings(event.getData());
persistentAuditEvent.setData(truncate(eventData));
persistenceAuditEventRepository.save(persistentAuditEvent);
}
}
I experienced the same problem also with a 5.8.2 Jhipster microservice application (gateway + microservice) based on Postgres db. Especially after rebuilding the ms, I got the notorious:
ERROR: duplicate key value violates unique constraint "pk_jhi_persistent_audit_event"
I have observed that, when it happened, there was an overlapping of keys for hibernate_sequence as its next value retrieved with pgAdmin was different by the key that the application was trying to write in the audit table (curiously there was a difference of 50 or less...). I don't know in which way Hibernate deals with sequenceGenerator but this post gives me some tips (the fourth answer):
Liquibase + Postgresql + Spring Jpa : Id auto increment issue
I have not in my Postgres db a serial datatype for the id column, but indeed the behaviour is similar - Hibernate seems to send key values taken from some cache that survive also after a rebuilding. So I give up with Hibernate sequence and I created a new ordinary postgres sequence:
CREATE SEQUENCE public.id_persistent_audit_event_seq
AS bigint
MINVALUE 1 NO MAXVALUE
START WITH 1
CACHE 50;
On Java side (PersistentAuditEvent.java):
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "audit_event_generator")
#SequenceGenerator(name = "audit_event_generator", sequenceName="id_persistent_audit_event_seq", allocationSize=1)
#Column(name = "event_id")
private Long id;
Note the allocationSize=1 but CACHE 50 in Postgres. This should avoid performance issues on database side (look at jdubois' comment of 14 Sep 2018 in https://github.com/jhipster/generator-jhipster/issues/8029).
Hope it helps, now everything is working well for me!

Spring Boot fails to create database schema

I have the following entities in my Spring Boot web application all defined in the entities package:
AccessPath.java
Component.java
ComponentInstance.java
ComponentOrder.java
Customer.java
HardwareComponent.java
HardwareGraphicsComponent.java
HardwareProcessingComponent.java
HardwareRamComponent.java
HardwareStorageComponent.java
Invoice.java
Manager.java
Order.java
Product.java
Report.java
ScmManager.java
ScmStaff.java
SoftwareComponent.java
Staff.java
Supplier.java
User.java
WarehouseManager.java
I'm using a properly configured PostgreSQL instance as the database:
spring.thymeleaf.cache=false
#
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/foundationdb
spring.datasource.username=foundationdb
spring.datasource.password=
#
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=create-drop
When running the application with gradle bootRun I get a lot of error messages regarding invalid SQL statements. It seems like the framework is trying to create the tables in the wrong order and basically fails to create tables for any entity with some sort of relationship. For instance the SQL for creating the order tables fails with the following error most likely because the customer table to which order has a foreign key isn't created yet.
2017-06-09 10:51:35.737 ERROR 85908 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : HHH000389: Unsuccessful: create table order (id int8 not null, assembly_date date, confirmation_date date, creation_date date, shipping_date date, status varchar(255), customer_username varchar(255), product_id int8, primary key (id))
2017-06-09 10:51:35.737 ERROR 85908 --- [ main] org.hibernate.tool.hbm2ddl.SchemaExport : ERROR: syntax error at or near "order"
The only tables created at the end are these:
List of relations
Schema | Name | Type | Owner
--------+-----------------------------+-------+--------------
public | component | table | foundationdb
public | component_instance | table | foundationdb
public | component_order | table | foundationdb
public | invoice | table | foundationdb
public | product | table | foundationdb
public | product_software_components | table | foundationdb
public | report | table | foundationdb
public | supplier | table | foundationdb
My entities were scattered across different packages at first and I tried putting them all in a single package to streamline the process but that didn't help.
This is definitely a framework related issue as testing with in-memory h2 or HSQLDB instances results in similar errors.
The source code for all these classes is available here:
https://gist.github.com/Parsoa/f463fbef548f3a678c1e067e9aad5b21
Any help is appreciated.
order is a reserved SQL keyword (order by ...). Choose another name for your table.
As the error message shows, it has nothing to do with foreign keys:
ERROR: syntax error at or near "order"