diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml
index 5b1d35d5eb1738b9c8b5a543d1385ad31ed2e39d..6311add8b60aefd47f3777317c119da138d64771 100644
--- a/dbrepo-metadata-service/pom.xml
+++ b/dbrepo-metadata-service/pom.xml
@@ -65,6 +65,7 @@
         <springdoc-openapi.version>2.1.0</springdoc-openapi.version>
         <testcontainers.version>1.18.3</testcontainers.version>
         <opensearch-testcontainer.version>2.0.0</opensearch-testcontainer.version>
+        <keycloak-testcontainer.version>2.5.0</keycloak-testcontainer.version>
         <opensearch-client.version>1.1.0</opensearch-client.version>
         <opensearch-rest-client.version>2.8.0</opensearch-rest-client.version>
         <jackson.version>2.15.2</jackson.version>
@@ -289,6 +290,12 @@
             <version>${testcontainers.version}</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.github.dasniko</groupId>
+            <artifactId>testcontainers-keycloak</artifactId>
+            <version>${keycloak-testcontainer.version}</version>
+            <scope>test</scope>
+        </dependency>
         <dependency>
             <groupId>org.opensearch</groupId>
             <artifactId>opensearch-testcontainers</artifactId>
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/KeycloakContainerConfig.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/KeycloakContainerConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a8e08d4a0beb469da50a3997a643f96ba279524
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/config/KeycloakContainerConfig.java
@@ -0,0 +1,71 @@
+package at.tuwien.config;
+
+import at.tuwien.test.BaseTest;
+import dasniko.testcontainers.keycloak.KeycloakContainer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.testcontainers.containers.MariaDBContainer;
+import org.testcontainers.images.PullPolicy;
+
+/**
+ * This class configures the MariaDB container for the integration tests.
+ */
+@Configuration
+public class KeycloakContainerConfig {
+
+    public static CustomKeycloakContainer getContainer() {
+        return CustomKeycloakContainer.getInstance();
+    }
+
+    @Bean
+    public CustomKeycloakContainer keycloakContainer() {
+        return getContainer();
+    }
+
+    /**
+     * This class represents the customized MariaDB container. It is a singleton to avoid the recreation of containers
+     * which can be very time-consuming.
+     */
+    public static class CustomKeycloakContainer extends KeycloakContainer {
+
+        private static CustomKeycloakContainer instance;
+
+        private boolean started = false;
+
+        public static synchronized CustomKeycloakContainer getInstance() {
+            if(instance == null) {
+                instance = new CustomKeycloakContainer("quay.io/keycloak/keycloak:21.0");
+                instance.withImagePullPolicy(PullPolicy.alwaysPull());
+                instance.addFixedExposedPort(BaseTest.CONTAINER_1_PORT, BaseTest.IMAGE_1_PORT);
+                instance.withAdminUsername("fda");
+                instance.withAdminPassword("fda");
+                instance.addFixedExposedPort(8080, 8080);
+                instance.withRealmImportFile("./dbrepo-realm.json");
+            }
+            return instance;
+        }
+
+        private CustomKeycloakContainer(String dockerImageName) {
+            super(dockerImageName);
+        }
+
+        @Override
+        protected void configure() {
+            super.configure();
+            this.addEnv("KC_HOSTNAME_STRICT_HTTPS", "false");
+        }
+
+        @Override
+        public synchronized void start() {
+            if(!started) {
+                super.start();
+                started = true;
+            }
+        }
+
+        @Override
+        public void stop() {
+            // do nothing, JVM handles shut down
+        }
+    }
+}
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java
index fbff73859ad900c4696cd2cd9376626ab0b0a7ee..d9ae17223957d0014fb074fac4c20784bb53d4dc 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java
@@ -13,6 +13,7 @@ import at.tuwien.exception.*;
 import at.tuwien.gateway.KeycloakGateway;
 import at.tuwien.repository.mdb.DatabaseAccessRepository;
 import at.tuwien.repository.mdb.IdentifierRepository;
+import at.tuwien.repository.mdb.UserRepository;
 import at.tuwien.repository.sdb.DatabaseIdxRepository;
 import at.tuwien.service.AccessService;
 import at.tuwien.service.ContainerService;
@@ -34,6 +35,7 @@ import org.springframework.test.context.junit.jupiter.SpringExtension;
 
 import java.security.Principal;
 import java.util.List;
+import java.util.Optional;
 
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.any;
@@ -73,6 +75,9 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
     @MockBean
     private IdentifierRepository identifierRepository;
 
+    @MockBean
+    private UserRepository userRepository;
+
     @Autowired
     private DatabaseEndpoint databaseEndpoint;
 
@@ -86,7 +91,7 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
                 .build();
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             create_generic(DATABASE_1_ID, null, request, null, null);
         });
     }
@@ -101,7 +106,7 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
                 .build();
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             create_generic(DATABASE_3_ID, null, request, USER_4, USER_4_PRINCIPAL);
         });
     }
@@ -140,6 +145,8 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
                 .thenReturn(DATABASE_1_USER_1_WRITE_ALL_ACCESS);
         when(keycloakGateway.findByUsername(USER_1_USERNAME))
                 .thenReturn(USER_1_KEYCLOAK_DTO);
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
 
         /* test */
         create_generic(DATABASE_1_ID, null, request, USER_1, USER_1_PRINCIPAL);
@@ -186,7 +193,7 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
                 .build();
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             visibility_generic(DATABASE_1_ID, DATABASE_1, DATABASE_1_DTO, request, null);
         });
     }
@@ -202,6 +209,8 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
         /* mock */
         when(keycloakGateway.findByUsername(USER_1_USERNAME))
                 .thenReturn(USER_1_KEYCLOAK_DTO);
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
 
         /* test */
         visibility_generic(DATABASE_1_ID, DATABASE_1, DATABASE_1_DTO, request, USER_1_PRINCIPAL);
@@ -215,7 +224,7 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
                 .build();
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             visibility_generic(DATABASE_1_ID, DATABASE_1, DATABASE_1_DTO, request, USER_4_PRINCIPAL);
         });
     }
@@ -227,8 +236,12 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
                 .isPublic(true)
                 .build();
 
+        /* mock */
+        when(userRepository.findByUsername(USER_2_USERNAME))
+                .thenReturn(Optional.of(USER_2));
+
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(NotAllowedException.class, () -> {
             visibility_generic(DATABASE_1_ID, DATABASE_1, DATABASE_1_DTO, request, USER_2_PRINCIPAL);
         });
     }
@@ -241,7 +254,7 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
                 .build();
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             databaseEndpoint.transfer(DATABASE_3_ID, request, USER_4_PRINCIPAL);
         });
     }
@@ -256,9 +269,11 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
         /* mock */
         when(databaseService.findById(DATABASE_1_ID))
                 .thenReturn(DATABASE_1);
+        when(userRepository.findByUsername(USER_2_USERNAME))
+                .thenReturn(Optional.of(USER_2));
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(NotAllowedException.class, () -> {
             databaseEndpoint.transfer(DATABASE_1_ID, request, USER_2_PRINCIPAL);
         });
     }
@@ -276,6 +291,8 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
                 .thenReturn(DATABASE_1);
         when(keycloakGateway.findByUsername(USER_1_USERNAME))
                 .thenReturn(USER_1_KEYCLOAK_DTO);
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
 
         /* test */
         databaseEndpoint.transfer(DATABASE_1_ID, request, USER_1_PRINCIPAL);
@@ -362,7 +379,7 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
     public void delete_anonymous_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             delete_generic(DATABASE_1_ID, DATABASE_1, null);
         });
     }
@@ -372,7 +389,7 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
     public void delete_noRole_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             delete_generic(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL);
         });
     }
@@ -436,7 +453,7 @@ public class DatabaseEndpointUnitTest extends BaseUnitTest {
 
     public void visibility_generic(Long databaseId, Database database, DatabaseDto dto,
                                    DatabaseModifyVisibilityDto data, Principal principal) throws NotAllowedException,
-            DatabaseNotFoundException, UserNotFoundException, KeycloakRemoteException, AccessDeniedException {
+            DatabaseNotFoundException, UserNotFoundException {
 
         /* mock */
         if (database != null) {
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/PersistenceEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/PersistenceEndpointUnitTest.java
index 5ec031a117ac67762ce86735593d226591ad42b5..0f01a366fb69dd83d9512afe2336bdb6b0126262 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/PersistenceEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/PersistenceEndpointUnitTest.java
@@ -555,7 +555,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     public void update_anonymous_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO_UPDATE_REQUEST, null, null, null);
         });
     }
@@ -565,7 +565,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     public void update_noRole_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO_UPDATE_REQUEST, USER_4_USERNAME, USER_4, USER_4_PRINCIPAL);
         });
     }
@@ -600,7 +600,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     public void delete_anonymous_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             this.generic_delete(IDENTIFIER_1_ID, IDENTIFIER_1);
         });
     }
@@ -610,7 +610,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
     public void delete_noRole_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             this.generic_delete(IDENTIFIER_1_ID, IDENTIFIER_1);
         });
     }
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableDataEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableDataEndpointUnitTest.java
index 28d17f856881a7d7b55c338b930eb50e195c50bc..801aec38422b9e10d082a799736e742b0d760894 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableDataEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableDataEndpointUnitTest.java
@@ -65,7 +65,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void import_publicAnonymous_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_import(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, null, null, null);
         });
     }
@@ -75,7 +75,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void import_publicNoRoleRead_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_import(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_2_ID,
                     DATABASE_1_USER_1_READ_ACCESS, USER_2_PRINCIPAL);
         });
@@ -86,7 +86,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void import_publicNoRoleWriteOwn_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_import(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_2_ID,
                     DATABASE_1_USER_1_WRITE_OWN_ACCESS, USER_2_PRINCIPAL);
         });
@@ -97,7 +97,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void import_privateAnonymous_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_import(DATABASE_2_ID, DATABASE_2, TABLE_1_ID, TABLE_1, null, null, null);
         });
     }
@@ -107,7 +107,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void import_privateNoRoleRead_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_import(DATABASE_2_ID, DATABASE_2, TABLE_1_ID, TABLE_1, USER_2_ID,
                     DATABASE_2_USER_1_READ_ACCESS, USER_2_PRINCIPAL);
         });
@@ -118,7 +118,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void import_privateNoRoleWriteOwn_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_import(DATABASE_2_ID, DATABASE_2, TABLE_1_ID, TABLE_1, USER_2_ID,
                     DATABASE_2_USER_1_WRITE_OWN_ACCESS, USER_2_PRINCIPAL);
         });
@@ -129,7 +129,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void import_publicAnonymous_succeeds() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_import(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, null, null, null);
         });
     }
@@ -138,7 +138,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
     public void import_publicWriteAll_succeeds() throws UserNotFoundException, TableNotFoundException, NotAllowedException,
             TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, at.tuwien.exception.AccessDeniedException {
+            ImageNotSupportedException, AccessDeniedException {
 
         /* test */
         generic_import(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_1_ID,
@@ -149,7 +149,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
     public void import_privateWriteAll_succeeds() throws UserNotFoundException, TableNotFoundException, NotAllowedException,
             TableMalformedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, at.tuwien.exception.AccessDeniedException {
+            ImageNotSupportedException, AccessDeniedException {
 
         /* test */
         generic_import(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_1_ID,
@@ -161,7 +161,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void insert_publicAnonymous_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_insert(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_2_ID, null,
                     TABLE_1_CSV_DTO, null);
         });
@@ -172,7 +172,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void insert_publicNoRoleRead_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_insert(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_2_ID,
                     DATABASE_1_USER_1_READ_ACCESS, TABLE_1_CSV_DTO, USER_2_PRINCIPAL);
         });
@@ -183,7 +183,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void insert_publicNoRoleWriteOwn_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_insert(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_2_ID,
                     DATABASE_1_USER_1_WRITE_OWN_ACCESS, TABLE_1_CSV_DTO, USER_2_PRINCIPAL);
         });
@@ -194,7 +194,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void insert_privateAnonymous_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_insert(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, TABLE_1, USER_2_ID, null,
                     TABLE_1_CSV_DTO, null);
         });
@@ -205,7 +205,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void insert_privateNoRoleRead_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_insert(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, TABLE_1, USER_2_ID,
                     DATABASE_2_USER_1_READ_ACCESS, TABLE_1_CSV_DTO, USER_2_PRINCIPAL);
         });
@@ -216,7 +216,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     public void insert_privateNoRoleWriteOwn_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             generic_insert(DATABASE_2_ID, TABLE_1_ID, DATABASE_2, TABLE_1, USER_2_ID,
                     DATABASE_2_USER_1_WRITE_OWN_ACCESS, TABLE_1_CSV_DTO, USER_2_PRINCIPAL);
         });
@@ -226,7 +226,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
     public void insert_publicWriteAll_succeeds() throws UserNotFoundException, TableNotFoundException,
             NotAllowedException, TableMalformedException, DatabaseConnectionException, DatabaseNotFoundException,
-            ImageNotSupportedException, ContainerNotFoundException, at.tuwien.exception.AccessDeniedException {
+            ImageNotSupportedException, ContainerNotFoundException, AccessDeniedException {
 
         /* test */
         generic_insert(DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_8, USER_1_ID,
@@ -237,7 +237,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
     public void insert_privateWriteAll_succeeds() throws UserNotFoundException, TableNotFoundException,
             NotAllowedException, TableMalformedException, DatabaseConnectionException, DatabaseNotFoundException,
-            ImageNotSupportedException, ContainerNotFoundException, at.tuwien.exception.AccessDeniedException {
+            ImageNotSupportedException, ContainerNotFoundException, AccessDeniedException {
 
         /* test */
         generic_insert(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_1_ID, DATABASE_1_USER_1_WRITE_ALL_ACCESS, TABLE_1_CSV_DTO, USER_1_PRINCIPAL);
@@ -247,7 +247,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
     @WithMockUser(username = USER_1_USERNAME, authorities = {"insert-table-data"})
     public void insert_privateDataNull_fails() throws UserNotFoundException, TableNotFoundException,
             NotAllowedException, TableMalformedException, DatabaseConnectionException, DatabaseNotFoundException,
-            ImageNotSupportedException, ContainerNotFoundException, at.tuwien.exception.AccessDeniedException {
+            ImageNotSupportedException, ContainerNotFoundException, AccessDeniedException {
 
         /* test */
         generic_insert(DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_1_ID, DATABASE_1_USER_1_WRITE_ALL_ACCESS, null, USER_1_PRINCIPAL);
@@ -344,22 +344,22 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
                         TABLE_8, null, null, null,
                         null, null, null, null, null),
                 Arguments.arguments("public read", DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_8,
-                        USER_1_USERNAME,
+                        USER_1_ID,
                         DATABASE_3_USER_1_READ_ACCESS, USER_1_PRINCIPAL, null, null, null, null, null),
                 Arguments.arguments("public write-own", DATABASE_3_ID, TABLE_8_ID, DATABASE_3,
-                        TABLE_8, USER_1_USERNAME,
+                        TABLE_8, USER_1_ID,
                         DATABASE_3_USER_1_WRITE_OWN_ACCESS, USER_1_PRINCIPAL, null, null, null, null, null),
                 Arguments.arguments("public write-all", DATABASE_3_ID, TABLE_8_ID, DATABASE_3,
-                        TABLE_8, USER_1_USERNAME,
+                        TABLE_8, USER_1_ID,
                         DATABASE_3_USER_1_WRITE_ALL_ACCESS, USER_1_PRINCIPAL, null, null, null, null, null),
                 Arguments.arguments("private read", DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1,
-                        USER_1_USERNAME,
+                        USER_1_ID,
                         DATABASE_1_USER_1_READ_ACCESS, USER_1_PRINCIPAL, null, null, null, null, null),
                 Arguments.arguments("private write-own", DATABASE_1_ID, TABLE_1_ID, DATABASE_1,
-                        TABLE_1, USER_1_USERNAME,
+                        TABLE_1, USER_1_ID,
                         DATABASE_1_USER_1_WRITE_OWN_ACCESS, USER_1_PRINCIPAL, null, null, null, null, null),
                 Arguments.arguments("private write-all", DATABASE_1_ID, TABLE_1_ID, DATABASE_1,
-                        TABLE_1, USER_1_USERNAME,
+                        TABLE_1, USER_1_ID,
                         DATABASE_1_USER_1_WRITE_ALL_ACCESS, USER_1_PRINCIPAL, null, null, null, null, null)
         );
     }
@@ -372,7 +372,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
                                 SortType sortDirection, String sortColumn) throws UserNotFoundException,
             TableNotFoundException, SortException, TableMalformedException, NotAllowedException,
             DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
-            PaginationException, at.tuwien.exception.AccessDeniedException {
+            PaginationException, AccessDeniedException {
 
         /* test */
         generic_getAll(databaseId, tableId, database, table, userId, access, principal, timestamp,
@@ -411,7 +411,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
                                   UUID userId, DatabaseAccess access, Principal principal, Instant timestamp)
             throws UserNotFoundException, TableNotFoundException, QueryStoreException, TableMalformedException,
             NotAllowedException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, at.tuwien.exception.AccessDeniedException {
+            ImageNotSupportedException, AccessDeniedException {
 
         /* test */
         generic_getCount(databaseId, tableId, database, table, userId, access, principal, timestamp);
@@ -426,7 +426,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
                                DatabaseAccess access, Principal principal) throws DatabaseNotFoundException,
             TableNotFoundException, NotAllowedException, UserNotFoundException, TableMalformedException,
             DatabaseConnectionException, QueryMalformedException, ImageNotSupportedException,
-            at.tuwien.exception.AccessDeniedException {
+            AccessDeniedException {
         final ImportDto request = ImportDto.builder().location("test:csv/csv_01.csv").build();
 
         /* mock */
@@ -444,7 +444,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
                                DatabaseAccess access, TableCsvDto data, Principal principal)
             throws DatabaseNotFoundException, TableNotFoundException, NotAllowedException, UserNotFoundException,
             TableMalformedException, DatabaseConnectionException, ImageNotSupportedException,
-            ContainerNotFoundException, at.tuwien.exception.AccessDeniedException {
+            ContainerNotFoundException, AccessDeniedException {
 
         /* mock */
         when(databaseService.find(databaseId)).thenReturn(database);
@@ -462,7 +462,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
                                SortType sortDirection, String sortColumn) throws UserNotFoundException,
             TableMalformedException, NotAllowedException, PaginationException, TableNotFoundException, SortException,
             DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException,
-            at.tuwien.exception.AccessDeniedException {
+            AccessDeniedException {
 
         /* mock */
         when(databaseService.find(databaseId)).thenReturn(database);
@@ -484,7 +484,7 @@ public class TableDataEndpointUnitTest extends BaseUnitTest {
                                  DatabaseAccess access, Principal principal, Instant timestamp)
             throws UserNotFoundException, TableMalformedException, NotAllowedException, TableNotFoundException,
             QueryStoreException, DatabaseConnectionException, QueryMalformedException, DatabaseNotFoundException,
-            ImageNotSupportedException, at.tuwien.exception.AccessDeniedException {
+            ImageNotSupportedException, AccessDeniedException {
 
         /* mock */
         when(databaseService.find(databaseId)).thenReturn(database);
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java
index 9f1d45eed84a134be84f77b58d62694803149e42..d74bc927205c692b940a238d4dfb9b8b2210b5bc 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java
@@ -95,7 +95,7 @@ public class ViewEndpointUnitTest extends BaseUnitTest {
     public void create_publicAnonymous_succeeds() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             create_generic(DATABASE_3_ID, DATABASE_3, null, null, null);
         });
     }
@@ -125,7 +125,7 @@ public class ViewEndpointUnitTest extends BaseUnitTest {
     public void create_publicNoRole_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             create_generic(DATABASE_3_ID, DATABASE_3, USER_2_ID, USER_2_PRINCIPAL, null);
         });
     }
@@ -171,7 +171,7 @@ public class ViewEndpointUnitTest extends BaseUnitTest {
     public void delete_publicAnonymous_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             delete_generic(DATABASE_3_ID, VIEW_1_ID, DATABASE_3, null, null, null);
         });
     }
@@ -191,7 +191,7 @@ public class ViewEndpointUnitTest extends BaseUnitTest {
     public void delete_publicNoRole_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             delete_generic(DATABASE_3_ID, VIEW_1_ID, DATABASE_3, USER_2_ID, USER_2_PRINCIPAL, DATABASE_2_USER_1_READ_ACCESS);
         });
     }
@@ -291,7 +291,7 @@ public class ViewEndpointUnitTest extends BaseUnitTest {
     public void create_privateAnonymous_succeeds() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             create_generic(DATABASE_1_ID, DATABASE_1, null, null, null);
         });
     }
@@ -321,7 +321,7 @@ public class ViewEndpointUnitTest extends BaseUnitTest {
     public void create_privateNoRole_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             create_generic(DATABASE_1_ID, DATABASE_1, USER_2_ID, USER_2_PRINCIPAL, null);
         });
     }
@@ -367,7 +367,7 @@ public class ViewEndpointUnitTest extends BaseUnitTest {
     public void delete_privateAnonymous_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             delete_generic(DATABASE_1_ID, VIEW_1_ID, DATABASE_1, null, null, null);
         });
     }
@@ -387,7 +387,7 @@ public class ViewEndpointUnitTest extends BaseUnitTest {
     public void delete_privateNoRole_fails() {
 
         /* test */
-        assertThrows(AccessDeniedException.class, () -> {
+        assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
             delete_generic(DATABASE_1_ID, VIEW_1_ID, DATABASE_1, USER_1_ID, USER_2_PRINCIPAL, DATABASE_2_USER_1_READ_ACCESS);
         });
     }
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java
index 98f12a337b649ef0c3cb26b85078c5ace028376f..52cb521ff7c95b67e832469f05c2a16507ccdc13 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java
@@ -11,6 +11,7 @@ import at.tuwien.exception.AccessDeniedException;
 import at.tuwien.exception.NotAllowedException;
 import at.tuwien.repository.mdb.DatabaseAccessRepository;
 import at.tuwien.repository.mdb.DatabaseRepository;
+import at.tuwien.repository.mdb.UserRepository;
 import lombok.extern.log4j.Log4j2;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
@@ -39,6 +40,9 @@ public class AccessServiceUnitTest extends BaseUnitTest {
     @MockBean
     private DatabaseAccessRepository databaseAccessRepository;
 
+    @MockBean
+    private UserRepository userRepository;
+
     @Autowired
     private AccessService accessService;
 
@@ -100,6 +104,8 @@ public class AccessServiceUnitTest extends BaseUnitTest {
         /* mock */
         when(databaseRepository.findById(DATABASE_1_ID))
                 .thenReturn(Optional.of(DATABASE_1));
+        when(userRepository.findById(USER_1_ID))
+                .thenReturn(Optional.of(USER_1));
 
         /* test */
         assertThrows(NotAllowedException.class, () -> {
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceComponentTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceComponentTest.java
index dd6cf5370826ead3fe585033e413a9e60f2eb592..47318a596f24170ebb8b1aa5176b8ea6f8059567 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceComponentTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceComponentTest.java
@@ -9,6 +9,7 @@ import at.tuwien.config.MariaDbConfig;
 import at.tuwien.entities.database.Database;
 import at.tuwien.repository.mdb.ContainerRepository;
 import at.tuwien.repository.mdb.DatabaseRepository;
+import at.tuwien.repository.mdb.UserRepository;
 import at.tuwien.repository.sdb.DatabaseIdxRepository;
 import at.tuwien.service.impl.MariaDbServiceImpl;
 import lombok.extern.log4j.Log4j2;
@@ -48,6 +49,9 @@ public class DatabaseServiceComponentTest extends BaseUnitTest {
     @MockBean
     private DatabaseIdxRepository databaseIdxRepository;
 
+    @MockBean
+    private UserRepository userRepository;
+
     @Autowired
     private MariaDbServiceImpl databaseService;
 
@@ -61,11 +65,13 @@ public class DatabaseServiceComponentTest extends BaseUnitTest {
     }
 
     @Test
-    public void create_elasticSearch_succeeds() throws Exception {
+    public void create_openSearch_succeeds() throws Exception {
 
         /* mock */
         when(databaseIdxRepository.save(any(DatabaseDto.class)))
                 .thenReturn(DATABASE_3_DTO);
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
 
         /* test */
         generic_create(DATABASE_3_CREATE, DATABASE_3);
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
index c08785afeddff8e3768e06c7e7c03981da29ef52..58223493e3e697563418430416b4e38bfee702eb 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/QueryServiceIntegrationTest.java
@@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 import org.testcontainers.containers.MariaDBContainer;
@@ -34,12 +35,10 @@ import java.time.ZoneId;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeFormatterBuilder;
 import java.time.temporal.ChronoUnit;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
+import java.util.*;
 
 import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.when;
 
 @Log4j2
 @Testcontainers
@@ -51,6 +50,9 @@ import static org.junit.jupiter.api.Assertions.*;
 @MockOpensearch
 public class QueryServiceIntegrationTest extends BaseUnitTest {
 
+    @MockBean
+    private UserRepository userRepository;
+
     @Autowired
     private DatabaseRepository databaseRepository;
 
@@ -295,6 +297,10 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
                 .statement("SELECT n.`firstname`, n.`lastname`, n.`birth`, n.`reminder`, z.`animal_name`, z.`legs` FROM `likes` l JOIN `names` n ON l.`name_id` = n.`id` JOIN `mock_view` z ON z.`id` = l.`zoo_id`")
                 .build();
 
+        /* mock */
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
+
         /* test */
         Thread.sleep(1000) /* wait for test container some more */;
         final QueryResultDto response = queryService.execute(DATABASE_2_ID, request, USER_1_PRINCIPAL, 0L, 100L, null, null);
@@ -332,6 +338,10 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
                 .statement("SELECT `location`, `lng` FROM `weather_location` WHERE `lat` IS NULL")
                 .build();
 
+        /* mock */
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
+
         /* test */
         Thread.sleep(1000) /* wait for test container some more */;
         final QueryResultDto response = queryService.execute(DATABASE_1_ID, request, USER_1_PRINCIPAL,
@@ -352,6 +362,10 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
                 .statement("SELECT `location` FROM `weather_location` WHERE `lat` IS NULL")
                 .build();
 
+        /* mock */
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
+
         /* test */
         Thread.sleep(1000) /* wait for test container some more */;
         final QueryResultDto response = queryService.execute(DATABASE_1_ID, request, USER_1_PRINCIPAL,
@@ -373,6 +387,10 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
                 .statement("SELECT `lat`, `lng` FROM `weather_location` WHERE `lat` IS NULL")
                 .build();
 
+        /* mock */
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
+
         /* test */
         Thread.sleep(1000) /* wait for test container some more */;
         final QueryResultDto response = queryService.execute(DATABASE_1_ID, request, USER_1_PRINCIPAL,
@@ -389,6 +407,10 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
                 .statement("SELECT aus.location as a, loc.location from weather_aus aus, weather_location loc")
                 .build();
 
+        /* mock */
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
+
         /* test */
         Thread.sleep(1000) /* wait for test container some more */;
         final QueryResultDto response = queryService.execute(DATABASE_1_ID, request, USER_1_PRINCIPAL, 0L, 100L, null, null);
@@ -426,6 +448,8 @@ public class QueryServiceIntegrationTest extends BaseUnitTest {
 
         /* mock */
         Thread.sleep(1000) /* wait for test container some more */;
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
 
         /* test */
         final QueryResultDto response = queryService.execute(DATABASE_1_ID, request, USER_1_PRINCIPAL,
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java
index cd8763f03d29e05883982006e60044f2b80c5149..fd561cadd89ea07dfbe74aae84adf900047fc96b 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceIntegrationTest.java
@@ -7,23 +7,33 @@ import at.tuwien.api.auth.SignupRequestDto;
 import at.tuwien.api.user.*;
 import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
+import at.tuwien.repository.mdb.UserRepository;
+import dasniko.testcontainers.keycloak.KeycloakContainer;
 import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
 import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.dao.DataIntegrityViolationException;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 import org.springframework.transaction.annotation.Transactional;
+import org.testcontainers.containers.MariaDBContainer;
+import org.testcontainers.junit.jupiter.Container;
+import org.testcontainers.junit.jupiter.Testcontainers;
 
 import java.util.List;
+import java.util.Optional;
 
 import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.when;
 
 @Log4j2
+@Testcontainers
 @EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class)
 @DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
 @SpringBootTest
@@ -32,9 +42,21 @@ import static org.junit.jupiter.api.Assertions.*;
 @MockOpensearch
 public class UserServiceIntegrationTest extends BaseUnitTest {
 
+    @Autowired
+    private UserRepository userRepository;
+
     @Autowired
     private UserService userService;
 
+    @Container
+    @Autowired
+    private KeycloakContainer keycloakContainer;
+
+    @BeforeEach
+    public void beforeEach() {
+        userRepository.save(USER_1);
+    }
+
     @Test
     public void findByUsername_succeeds() throws UserNotFoundException {
 
@@ -84,7 +106,7 @@ public class UserServiceIntegrationTest extends BaseUnitTest {
                 .build();
 
         /* test */
-        assertThrows(DataIntegrityViolationException.class, () -> {
+        assertThrows(UserAlreadyExistsException.class, () -> {
             userService.create(request);
         });
     }
@@ -98,7 +120,7 @@ public class UserServiceIntegrationTest extends BaseUnitTest {
                 .build();
 
         /* test */
-        assertThrows(DataIntegrityViolationException.class, () -> {
+        assertThrows(UserAlreadyExistsException.class, () -> {
             userService.create(request);
         });
     }
@@ -138,13 +160,21 @@ public class UserServiceIntegrationTest extends BaseUnitTest {
     }
 
     @Test
-    public void updatePassword_succeeds() throws KeycloakRemoteException, AccessDeniedException {
+    public void updatePassword_succeeds() throws KeycloakRemoteException, AccessDeniedException, UserNotFoundException,
+            UserAlreadyExistsException {
         final UserPasswordDto request = UserPasswordDto.builder()
-                .password(USER_1_PASSWORD)
+                .password(USER_3_PASSWORD)
                 .build();
 
+        /* mock */
+        final User user = userService.create(SignupRequestDto.builder()
+                .username(USER_3_USERNAME)
+                .password(USER_3_PASSWORD)
+                .email(USER_3_EMAIL)
+                .build());
+
         /* test */
-        userService.updatePassword(USER_1_ID, request);
+        userService.updatePassword(user.getId(), request);
     }
 
     @Test
diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java
index 515795e3c068105c58d7f655d5ceb234fc456d07..3282718db00f35428046a9b1ff09f54b670482c2 100644
--- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java
+++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/UserServiceUnitTest.java
@@ -8,6 +8,7 @@ import at.tuwien.api.user.UserDto;
 import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
 import at.tuwien.gateway.KeycloakGateway;
+import at.tuwien.repository.mdb.UserRepository;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.extension.ExtendWith;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -16,6 +17,7 @@ import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
 
 import java.util.List;
+import java.util.Optional;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -30,12 +32,19 @@ public class UserServiceUnitTest extends BaseUnitTest {
     @MockBean
     private KeycloakGateway keycloakGateway;
 
+    @MockBean
+    private UserRepository userRepository;
+
     @Autowired
     private UserService userService;
 
     @Test
     public void findByUsername_succeeds() throws UserNotFoundException {
 
+        /* mock */
+        when(userRepository.findByUsername(USER_1_USERNAME))
+                .thenReturn(Optional.of(USER_1));
+
         /* test */
         final User response = userService.findByUsername(USER_1_USERNAME);
         assertEquals(USER_1_ID, response.getId());
@@ -45,6 +54,10 @@ public class UserServiceUnitTest extends BaseUnitTest {
     @Test
     public void find_succeeds() throws UserNotFoundException {
 
+        /* mock */
+        when(userRepository.findById(USER_1_ID))
+                .thenReturn(Optional.of(USER_1));
+
         /* test */
         final User response = userService.find(USER_1_ID);
         assertEquals(USER_1_ID, response.getId());
@@ -54,9 +67,13 @@ public class UserServiceUnitTest extends BaseUnitTest {
     @Test
     public void findAll_succeeds() throws UserNotFoundException {
 
+        /* mock */
+        when(userRepository.findAll())
+                .thenReturn(List.of(USER_1, USER_2));
+
         /* test */
         final List<User> response = userService.findAll();
-        assertEquals(1, response.size());
+        assertEquals(2, response.size());
     }
 
     @Test
@@ -64,6 +81,10 @@ public class UserServiceUnitTest extends BaseUnitTest {
             UserAlreadyExistsException {
 
         /* mock */
+        when(userRepository.findById(USER_1_ID))
+                .thenReturn(Optional.of(USER_1));
+        when(userRepository.save(any(User.class)))
+                .thenReturn(USER_1);
         doNothing()
                 .when(keycloakGateway)
                 .createUser(USER_1_KEYCLOAK_SIGNUP_REQUEST);
@@ -79,6 +100,12 @@ public class UserServiceUnitTest extends BaseUnitTest {
     @Test
     public void modify_succeeds() throws UserNotFoundException {
 
+        /* mock */
+        when(userRepository.findById(USER_1_ID))
+                .thenReturn(Optional.of(USER_1));
+        when(userRepository.save(any(User.class)))
+                .thenReturn(USER_1);
+
         /* test */
         final User response = userService.modify(USER_1_ID, USER_1_UPDATE_DTO);
         assertEquals(USER_1_ID, response.getId());
@@ -88,8 +115,12 @@ public class UserServiceUnitTest extends BaseUnitTest {
     @Test
     public void modify_notExists_succeeds() {
 
+        /* mock */
+        when(userRepository.findById(USER_1_ID))
+                .thenReturn(Optional.empty());
+
         /* test */
-        assertThrows(KeycloakRemoteException.class, () -> {
+        assertThrows(UserNotFoundException.class, () -> {
             userService.modify(USER_1_ID, USER_1_UPDATE_DTO);
         });
     }
@@ -97,6 +128,12 @@ public class UserServiceUnitTest extends BaseUnitTest {
     @Test
     public void toggleTheme_succeeds() throws UserNotFoundException {
 
+        /* mock */
+        when(userRepository.findById(USER_1_ID))
+                .thenReturn(Optional.of(USER_1));
+        when(userRepository.save(any(User.class)))
+                .thenReturn(USER_1);
+
         /* test */
         final User response = userService.toggleTheme(USER_1_ID, USER_1_THEME_SET_DTO);
         assertEquals(USER_1_ID, response.getId());
@@ -105,7 +142,7 @@ public class UserServiceUnitTest extends BaseUnitTest {
     }
 
     @Test
-    public void updatePassword_succeeds() throws KeycloakRemoteException, AccessDeniedException {
+    public void updatePassword_succeeds() throws KeycloakRemoteException, AccessDeniedException, UserNotFoundException {
 
         /* mock */
         doNothing()
diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties
index 72324c813e9a123babce15fdf742f814373ad06e..025a23176df6e0b655b927abf4a45fb9611870e7 100644
--- a/dbrepo-metadata-service/rest-service/src/test/resources/application.properties
+++ b/dbrepo-metadata-service/rest-service/src/test/resources/application.properties
@@ -33,5 +33,8 @@ fda.datacite.prefix: 10.12345
 fda.datacite.username: test-user
 fda.datacite.password: test-password
 
+# keycloak
+fda.keycloak.endpoint: http://localhost:8080/
+
 # consumers
 fda.consumers=2
\ No newline at end of file
diff --git a/dbrepo-metadata-service/rest-service/src/test/resources/dbrepo-realm.json b/dbrepo-metadata-service/rest-service/src/test/resources/dbrepo-realm.json
new file mode 100644
index 0000000000000000000000000000000000000000..639d73ea15fdba309347312286e71a7f0706268e
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/test/resources/dbrepo-realm.json
@@ -0,0 +1,1525 @@
+{
+  "id": "4ef53018-8322-40ed-a44a-a7c5292a07be",
+  "realm": "dbrepo",
+  "displayName": "",
+  "displayNameHtml": "",
+  "notBefore": 0,
+  "defaultSignatureAlgorithm": "RS256",
+  "revokeRefreshToken": false,
+  "refreshTokenMaxReuse": 0,
+  "accessTokenLifespan": 300,
+  "accessTokenLifespanForImplicitFlow": 900,
+  "ssoSessionIdleTimeout": 1800,
+  "ssoSessionMaxLifespan": 36000,
+  "ssoSessionIdleTimeoutRememberMe": 0,
+  "ssoSessionMaxLifespanRememberMe": 0,
+  "offlineSessionIdleTimeout": 2592000,
+  "offlineSessionMaxLifespanEnabled": false,
+  "offlineSessionMaxLifespan": 5184000,
+  "clientSessionIdleTimeout": 0,
+  "clientSessionMaxLifespan": 0,
+  "clientOfflineSessionIdleTimeout": 0,
+  "clientOfflineSessionMaxLifespan": 0,
+  "accessCodeLifespan": 60,
+  "accessCodeLifespanUserAction": 300,
+  "accessCodeLifespanLogin": 1800,
+  "actionTokenGeneratedByAdminLifespan": 43200,
+  "actionTokenGeneratedByUserLifespan": 300,
+  "oauth2DeviceCodeLifespan": 600,
+  "oauth2DevicePollingInterval": 5,
+  "enabled": true,
+  "sslRequired": "none",
+  "registrationAllowed": false,
+  "registrationEmailAsUsername": false,
+  "rememberMe": false,
+  "verifyEmail": false,
+  "loginWithEmailAllowed": true,
+  "duplicateEmailsAllowed": false,
+  "resetPasswordAllowed": false,
+  "editUsernameAllowed": false,
+  "bruteForceProtected": false,
+  "permanentLockout": false,
+  "maxFailureWaitSeconds": 900,
+  "minimumQuickLoginWaitSeconds": 60,
+  "waitIncrementSeconds": 60,
+  "quickLoginCheckMilliSeconds": 1000,
+  "maxDeltaTimeSeconds": 43200,
+  "failureFactor": 30,
+  "defaultRole": {
+    "id": "7a02acbe-09aa-4af7-8e79-fbb0cf5fd0d6",
+    "name": "default-roles-dbrepo",
+    "description": "${role_default-roles}",
+    "composite": true,
+    "clientRole": false,
+    "containerId": "4ef53018-8322-40ed-a44a-a7c5292a07be"
+  },
+  "requiredCredentials": [
+    "password"
+  ],
+  "otpPolicyType": "totp",
+  "otpPolicyAlgorithm": "HmacSHA1",
+  "otpPolicyInitialCounter": 0,
+  "otpPolicyDigits": 6,
+  "otpPolicyLookAheadWindow": 1,
+  "otpPolicyPeriod": 30,
+  "otpPolicyCodeReusable": false,
+  "otpSupportedApplications": [
+    "totpAppGoogleName",
+    "totpAppMicrosoftAuthenticatorName",
+    "totpAppFreeOTPName"
+  ],
+  "webAuthnPolicyRpEntityName": "keycloak",
+  "webAuthnPolicySignatureAlgorithms": [
+    "ES256"
+  ],
+  "webAuthnPolicyRpId": "",
+  "webAuthnPolicyAttestationConveyancePreference": "not specified",
+  "webAuthnPolicyAuthenticatorAttachment": "not specified",
+  "webAuthnPolicyRequireResidentKey": "not specified",
+  "webAuthnPolicyUserVerificationRequirement": "not specified",
+  "webAuthnPolicyCreateTimeout": 0,
+  "webAuthnPolicyAvoidSameAuthenticatorRegister": false,
+  "webAuthnPolicyAcceptableAaguids": [],
+  "webAuthnPolicyPasswordlessRpEntityName": "keycloak",
+  "webAuthnPolicyPasswordlessSignatureAlgorithms": [
+    "ES256"
+  ],
+  "webAuthnPolicyPasswordlessRpId": "",
+  "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
+  "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
+  "webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
+  "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
+  "webAuthnPolicyPasswordlessCreateTimeout": 0,
+  "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
+  "webAuthnPolicyPasswordlessAcceptableAaguids": [],
+  "scopeMappings": [
+    {
+      "clientScope": "offline_access",
+      "roles": [
+        "offline_access"
+      ]
+    }
+  ],
+  "clientScopes": [
+    {
+      "id": "4410371f-2840-458a-a496-375bd500f5fc",
+      "name": "email",
+      "description": "OpenID Connect built-in scope: email",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${emailScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "7001651a-7ded-4a0f-9cb7-816b058af730",
+          "name": "email",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "email",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "email",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "25e4ad82-8b9b-463d-8b35-02fae44ec64c",
+          "name": "email verified",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "emailVerified",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "email_verified",
+            "jsonType.label": "boolean"
+          }
+        }
+      ]
+    },
+    {
+      "id": "ebe0a886-5df1-48f3-9f00-a45d686b0b02",
+      "name": "address",
+      "description": "OpenID Connect built-in scope: address",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${addressScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "866be669-9799-45ad-abdd-23f5d1c82293",
+          "name": "address",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-address-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.attribute.formatted": "formatted",
+            "user.attribute.country": "country",
+            "user.attribute.postal_code": "postal_code",
+            "userinfo.token.claim": "true",
+            "user.attribute.street": "street",
+            "id.token.claim": "true",
+            "user.attribute.region": "region",
+            "access.token.claim": "true",
+            "user.attribute.locality": "locality"
+          }
+        }
+      ]
+    },
+    {
+      "id": "be0f3000-0106-4edd-a8f5-0618e3a3f7fe",
+      "name": "microprofile-jwt",
+      "description": "Microprofile - JWT built-in scope",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "false"
+      },
+      "protocolMappers": [
+        {
+          "id": "093f222d-cee9-495a-81b7-ddae4b730ab2",
+          "name": "groups",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-realm-role-mapper",
+          "consentRequired": false,
+          "config": {
+            "multivalued": "true",
+            "user.attribute": "foo",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "groups",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "2e21b9f5-c428-4a5b-9dd8-8a80bc6d9795",
+          "name": "upn",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "username",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "upn",
+            "jsonType.label": "String"
+          }
+        }
+      ]
+    },
+    {
+      "id": "2a95813e-053d-4c20-9f2b-f7e1ad1798f5",
+      "name": "role_list",
+      "description": "SAML role list",
+      "protocol": "saml",
+      "attributes": {
+        "consent.screen.text": "${samlRoleListScopeConsentText}",
+        "display.on.consent.screen": "true"
+      },
+      "protocolMappers": [
+        {
+          "id": "9c8a5628-af2a-4ba4-9cad-a8ae58c8526a",
+          "name": "role list",
+          "protocol": "saml",
+          "protocolMapper": "saml-role-list-mapper",
+          "consentRequired": false,
+          "config": {
+            "single": "false",
+            "attribute.nameformat": "Basic",
+            "attribute.name": "Role"
+          }
+        }
+      ]
+    },
+    {
+      "id": "c6375bbe-9820-4781-8828-99020210f5bd",
+      "name": "roles",
+      "description": "OpenID Connect scope for add user roles to the access token",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "false",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${rolesScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "a1db2464-4e12-4696-914d-d252263e4470",
+          "name": "audience resolve",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-audience-resolve-mapper",
+          "consentRequired": false,
+          "config": {}
+        },
+        {
+          "id": "c5513105-d577-4ba0-bff8-f96e9272f6fd",
+          "name": "client roles",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-client-role-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.attribute": "foo",
+            "access.token.claim": "true",
+            "claim.name": "resource_access.${client_id}.roles",
+            "jsonType.label": "String",
+            "multivalued": "true"
+          }
+        },
+        {
+          "id": "66901106-8ea3-4712-8bdf-bc67da4a9d2d",
+          "name": "realm roles",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-realm-role-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.attribute": "foo",
+            "access.token.claim": "true",
+            "claim.name": "realm_access.roles",
+            "jsonType.label": "String",
+            "multivalued": "true"
+          }
+        }
+      ]
+    },
+    {
+      "id": "f0ea8ba1-794d-4b89-9ad3-b7f390c5241e",
+      "name": "phone",
+      "description": "OpenID Connect built-in scope: phone",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${phoneScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "b3789148-8427-4af8-bc03-4dd3fae4b312",
+          "name": "phone number",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "phoneNumber",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "phone_number",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "552ac5e8-6e04-47d5-8ddf-89230ca31b43",
+          "name": "phone number verified",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "phoneNumberVerified",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "phone_number_verified",
+            "jsonType.label": "boolean"
+          }
+        }
+      ]
+    },
+    {
+      "id": "8ff9a2f3-582c-4cda-8ea8-d08850f8a394",
+      "name": "web-origins",
+      "description": "OpenID Connect scope for add allowed web origins to the access token",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "false",
+        "display.on.consent.screen": "false",
+        "consent.screen.text": ""
+      },
+      "protocolMappers": [
+        {
+          "id": "52af8bfd-44b1-4b69-bfd5-bc92cf1629aa",
+          "name": "allowed web origins",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-allowed-origins-mapper",
+          "consentRequired": false,
+          "config": {}
+        }
+      ]
+    },
+    {
+      "id": "b3ebaf28-e467-4c70-b993-d7b8459dfb5a",
+      "name": "profile",
+      "description": "OpenID Connect built-in scope: profile",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${profileScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "1025302a-104e-42e8-acf8-83579c21bfbb",
+          "name": "family name",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "lastName",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "family_name",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "70a9942e-85c1-4f15-9605-6408e0087b74",
+          "name": "given name",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "firstName",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "given_name",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "1e36c899-c472-427e-a024-c12a64d6084c",
+          "name": "website",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "website",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "website",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "b5e54114-79cb-488d-9e60-6a804ca3b22a",
+          "name": "profile",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "profile",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "profile",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "3e9406b9-a0ae-48d2-98b9-66ab7360b2a2",
+          "name": "gender",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "gender",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "gender",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "aec55dcc-59e7-4ea7-9eb5-55954d983fd0",
+          "name": "locale",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "locale",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "locale",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "11fd80da-8760-4fa6-9d1b-32da9df170bd",
+          "name": "picture",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "picture",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "picture",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "90f93a66-27d0-4890-846b-79d99e02ad76",
+          "name": "updated at",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "updatedAt",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "updated_at",
+            "jsonType.label": "long"
+          }
+        },
+        {
+          "id": "6c8aa1f6-3aa2-4e48-9f9c-44cffe71e7d2",
+          "name": "username",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "username",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "preferred_username",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "a861da8e-87e7-4b5d-92fa-4ca61671c77f",
+          "name": "birthdate",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "birthdate",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "birthdate",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "ae301563-61a7-413b-87a0-036e1af942bb",
+          "name": "middle name",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "middleName",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "middle_name",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "c39e0763-48a9-4f69-84f4-4e334365f99b",
+          "name": "full name",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-full-name-mapper",
+          "consentRequired": false,
+          "config": {
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "userinfo.token.claim": "true"
+          }
+        },
+        {
+          "id": "a54ae213-5854-4f77-8646-5cc7767fb914",
+          "name": "nickname",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "nickname",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "nickname",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "41824638-4a2f-4259-90fe-431a32371256",
+          "name": "zoneinfo",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "zoneinfo",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "zoneinfo",
+            "jsonType.label": "String"
+          }
+        }
+      ]
+    },
+    {
+      "id": "4c7c18fe-2aff-4df3-aeff-4dca9de93a79",
+      "name": "offline_access",
+      "description": "OpenID Connect built-in scope: offline_access",
+      "protocol": "openid-connect",
+      "attributes": {
+        "consent.screen.text": "${offlineAccessScopeConsentText}",
+        "display.on.consent.screen": "true"
+      }
+    },
+    {
+      "id": "30b249b2-c788-47ef-a8c7-daa0e3713b7c",
+      "name": "acr",
+      "description": "OpenID Connect scope for add acr (authentication context class reference) to the token",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "false",
+        "display.on.consent.screen": "false"
+      },
+      "protocolMappers": [
+        {
+          "id": "50cf075c-fdc9-43f4-ab85-1e32cafbbb26",
+          "name": "acr loa level",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-acr-mapper",
+          "consentRequired": false,
+          "config": {
+            "id.token.claim": "true",
+            "access.token.claim": "true"
+          }
+        }
+      ]
+    }
+  ],
+  "defaultDefaultClientScopes": [
+    "role_list",
+    "profile",
+    "email",
+    "roles",
+    "web-origins",
+    "acr"
+  ],
+  "defaultOptionalClientScopes": [
+    "offline_access",
+    "address",
+    "phone",
+    "microprofile-jwt"
+  ],
+  "browserSecurityHeaders": {
+    "contentSecurityPolicyReportOnly": "",
+    "xContentTypeOptions": "nosniff",
+    "xRobotsTag": "none",
+    "xFrameOptions": "SAMEORIGIN",
+    "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
+    "xXSSProtection": "1; mode=block",
+    "strictTransportSecurity": "max-age=31536000; includeSubDomains"
+  },
+  "smtpServer": {},
+  "eventsEnabled": false,
+  "eventsListeners": [
+    "jboss-logging"
+  ],
+  "enabledEventTypes": [],
+  "adminEventsEnabled": false,
+  "adminEventsDetailsEnabled": false,
+  "identityProviders": [],
+  "identityProviderMappers": [],
+  "components": {
+    "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
+      {
+        "id": "4489b316-ab01-42cf-a224-f853a310c7c5",
+        "name": "Allowed Protocol Mapper Types",
+        "providerId": "allowed-protocol-mappers",
+        "subType": "authenticated",
+        "subComponents": {},
+        "config": {
+          "allowed-protocol-mapper-types": [
+            "oidc-address-mapper",
+            "saml-user-property-mapper",
+            "oidc-usermodel-property-mapper",
+            "oidc-usermodel-attribute-mapper",
+            "saml-user-attribute-mapper",
+            "oidc-sha256-pairwise-sub-mapper",
+            "oidc-full-name-mapper",
+            "saml-role-list-mapper"
+          ]
+        }
+      },
+      {
+        "id": "d355f2ac-bd0d-4c5c-8e2d-52f14f332354",
+        "name": "Allowed Protocol Mapper Types",
+        "providerId": "allowed-protocol-mappers",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "allowed-protocol-mapper-types": [
+            "oidc-full-name-mapper",
+            "oidc-usermodel-attribute-mapper",
+            "oidc-address-mapper",
+            "oidc-sha256-pairwise-sub-mapper",
+            "saml-role-list-mapper",
+            "saml-user-property-mapper",
+            "saml-user-attribute-mapper",
+            "oidc-usermodel-property-mapper"
+          ]
+        }
+      },
+      {
+        "id": "cefbb851-d3bd-4b6d-b582-7fc4fa51d9b6",
+        "name": "Allowed Client Scopes",
+        "providerId": "allowed-client-templates",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "allow-default-scopes": [
+            "true"
+          ]
+        }
+      },
+      {
+        "id": "b7fe23c6-f82b-4920-8062-3d9fa6fb838f",
+        "name": "Full Scope Disabled",
+        "providerId": "scope",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {}
+      },
+      {
+        "id": "8332b5b7-5643-4c9f-afdb-4bda506bac55",
+        "name": "Allowed Client Scopes",
+        "providerId": "allowed-client-templates",
+        "subType": "authenticated",
+        "subComponents": {},
+        "config": {
+          "allow-default-scopes": [
+            "true"
+          ]
+        }
+      },
+      {
+        "id": "bb595923-ec43-4cbc-be3c-6d65c250956d",
+        "name": "Consent Required",
+        "providerId": "consent-required",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {}
+      },
+      {
+        "id": "4d9901ea-7d1e-484a-a5de-abb36d8a5cc8",
+        "name": "Trusted Hosts",
+        "providerId": "trusted-hosts",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "host-sending-registration-request-must-match": [
+            "true"
+          ],
+          "client-uris-must-match": [
+            "true"
+          ]
+        }
+      },
+      {
+        "id": "44bd2392-250b-4b4a-9772-7478fbd68f67",
+        "name": "Max Clients Limit",
+        "providerId": "max-clients",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "max-clients": [
+            "200"
+          ]
+        }
+      }
+    ],
+    "org.keycloak.userprofile.UserProfileProvider": [
+      {
+        "id": "0ffb33e9-2f5b-4e54-b188-19b3da816f0f",
+        "providerId": "declarative-user-profile",
+        "subComponents": {},
+        "config": {}
+      }
+    ],
+    "org.keycloak.keys.KeyProvider": [
+      {
+        "id": "d80cf13c-e402-49e5-b347-0175bdcac7b6",
+        "name": "rsa-generated",
+        "providerId": "rsa-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ]
+        }
+      },
+      {
+        "id": "03442c52-879c-4b3d-89c4-db02a0ad3c52",
+        "name": "aes-generated",
+        "providerId": "aes-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ]
+        }
+      },
+      {
+        "id": "30ce0596-cbce-4633-a422-15873bc363bf",
+        "name": "hmac-generated",
+        "providerId": "hmac-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ],
+          "algorithm": [
+            "HS256"
+          ]
+        }
+      },
+      {
+        "id": "012d037c-b22a-48f2-a80a-927424d75f00",
+        "name": "rsa-enc-generated",
+        "providerId": "rsa-enc-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ],
+          "algorithm": [
+            "RSA-OAEP"
+          ]
+        }
+      }
+    ]
+  },
+  "internationalizationEnabled": false,
+  "supportedLocales": [],
+  "authenticationFlows": [
+    {
+      "id": "865c209a-a080-4162-9b49-795345294601",
+      "alias": "Account verification options",
+      "description": "Method with which to verity the existing account",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "idp-email-verification",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "ALTERNATIVE",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Verify Existing Account by Re-authentication",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "85fc1de2-5b82-40ec-bda0-91a4fec38584",
+      "alias": "Authentication Options",
+      "description": "Authentication options.",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "basic-auth",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "basic-auth-otp",
+          "authenticatorFlow": false,
+          "requirement": "DISABLED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "auth-spnego",
+          "authenticatorFlow": false,
+          "requirement": "DISABLED",
+          "priority": 30,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "2476a340-9459-4541-9e61-226f06ec66c4",
+      "alias": "Browser - Conditional OTP",
+      "description": "Flow to determine if the OTP is required for the authentication",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "conditional-user-configured",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "auth-otp-form",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "2e424297-19dd-4c09-a06a-876ef5183ca6",
+      "alias": "Direct Grant - Conditional OTP",
+      "description": "Flow to determine if the OTP is required for the authentication",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "conditional-user-configured",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "direct-grant-validate-otp",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "3966485f-3455-47d2-86a2-d990b41c7953",
+      "alias": "First broker login - Conditional OTP",
+      "description": "Flow to determine if the OTP is required for the authentication",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "conditional-user-configured",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "auth-otp-form",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "29098fa4-d254-44cb-a6c5-63b36b8bfdc1",
+      "alias": "Handle Existing Account",
+      "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "idp-confirm-link",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Account verification options",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "03569e80-3083-4147-ad49-445466c191d8",
+      "alias": "Reset - Conditional OTP",
+      "description": "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "conditional-user-configured",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "reset-otp",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "7e660682-5eb3-4527-a5fa-53fc14a0f2f5",
+      "alias": "User creation or linking",
+      "description": "Flow for the existing/non-existing user alternatives",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticatorConfig": "create unique user config",
+          "authenticator": "idp-create-user-if-unique",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "ALTERNATIVE",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Handle Existing Account",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "4deed0f8-02f9-4581-9a91-05bc58fbffba",
+      "alias": "Verify Existing Account by Re-authentication",
+      "description": "Reauthentication of existing account",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "idp-username-password-form",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "CONDITIONAL",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "First broker login - Conditional OTP",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "3c101100-d2dc-4e0d-beea-7bb41ee08849",
+      "alias": "browser",
+      "description": "browser based authentication",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "auth-cookie",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "auth-spnego",
+          "authenticatorFlow": false,
+          "requirement": "DISABLED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "identity-provider-redirector",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 25,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "ALTERNATIVE",
+          "priority": 30,
+          "autheticatorFlow": true,
+          "flowAlias": "forms",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "f38f76db-5399-4231-82e0-bf31cf748d14",
+      "alias": "clients",
+      "description": "Base authentication for clients",
+      "providerId": "client-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "client-secret",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "client-jwt",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "client-secret-jwt",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 30,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "client-x509",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 40,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "ed29eed7-d490-4985-be20-2444da957182",
+      "alias": "direct grant",
+      "description": "OpenID Connect Resource Owner Grant",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "direct-grant-validate-username",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "direct-grant-validate-password",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "CONDITIONAL",
+          "priority": 30,
+          "autheticatorFlow": true,
+          "flowAlias": "Direct Grant - Conditional OTP",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "e41f4bae-aad9-4821-8597-514e6dc5796c",
+      "alias": "docker auth",
+      "description": "Used by Docker clients to authenticate against the IDP",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "docker-http-basic-authenticator",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "3149ebc7-481d-43bd-9d09-9e66bd9b2b7f",
+      "alias": "first broker login",
+      "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticatorConfig": "review profile config",
+          "authenticator": "idp-review-profile",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "User creation or linking",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "7aaab1d1-5357-4e71-8553-52d5613acf7d",
+      "alias": "forms",
+      "description": "Username, password, otp and other auth forms.",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "auth-username-password-form",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "CONDITIONAL",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Browser - Conditional OTP",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "c2ffc5bb-568a-4648-bc13-8e7d6a4a53b4",
+      "alias": "http challenge",
+      "description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "no-cookie-redirect",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Authentication Options",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "c6b78806-13ee-4010-b282-a6e527dda66c",
+      "alias": "registration",
+      "description": "registration flow",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "registration-page-form",
+          "authenticatorFlow": true,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": true,
+          "flowAlias": "registration form",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "b5f00ead-4f6f-4454-a925-154c1e9c2cc5",
+      "alias": "registration form",
+      "description": "registration form",
+      "providerId": "form-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "registration-user-creation",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "registration-profile-action",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 40,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "registration-password-action",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 50,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "registration-recaptcha-action",
+          "authenticatorFlow": false,
+          "requirement": "DISABLED",
+          "priority": 60,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "f8370f63-f996-4039-9fbf-86e87da675dd",
+      "alias": "reset credentials",
+      "description": "Reset credentials for a user if they forgot their password or something",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "reset-credentials-choose-user",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "reset-credential-email",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "reset-password",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 30,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "CONDITIONAL",
+          "priority": 40,
+          "autheticatorFlow": true,
+          "flowAlias": "Reset - Conditional OTP",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "7f156260-804d-4848-9ea0-347281aea644",
+      "alias": "saml ecp",
+      "description": "SAML ECP Profile Authentication Flow",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "http-basic-authenticator",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    }
+  ],
+  "authenticatorConfig": [
+    {
+      "id": "17f2c0cc-8dd8-4774-adcc-cd294cdadac8",
+      "alias": "create unique user config",
+      "config": {
+        "require.password.update.after.registration": "false"
+      }
+    },
+    {
+      "id": "d5be3f6c-d096-4232-88e8-b0f46e608cff",
+      "alias": "review profile config",
+      "config": {
+        "update.profile.on.first.login": "missing"
+      }
+    }
+  ],
+  "requiredActions": [
+    {
+      "alias": "CONFIGURE_TOTP",
+      "name": "Configure OTP",
+      "providerId": "CONFIGURE_TOTP",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 10,
+      "config": {}
+    },
+    {
+      "alias": "TERMS_AND_CONDITIONS",
+      "name": "Terms and Conditions",
+      "providerId": "TERMS_AND_CONDITIONS",
+      "enabled": false,
+      "defaultAction": false,
+      "priority": 20,
+      "config": {}
+    },
+    {
+      "alias": "UPDATE_PASSWORD",
+      "name": "Update Password",
+      "providerId": "UPDATE_PASSWORD",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 30,
+      "config": {}
+    },
+    {
+      "alias": "UPDATE_PROFILE",
+      "name": "Update Profile",
+      "providerId": "UPDATE_PROFILE",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 40,
+      "config": {}
+    },
+    {
+      "alias": "VERIFY_EMAIL",
+      "name": "Verify Email",
+      "providerId": "VERIFY_EMAIL",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 50,
+      "config": {}
+    },
+    {
+      "alias": "delete_account",
+      "name": "Delete Account",
+      "providerId": "delete_account",
+      "enabled": false,
+      "defaultAction": false,
+      "priority": 60,
+      "config": {}
+    },
+    {
+      "alias": "webauthn-register",
+      "name": "Webauthn Register",
+      "providerId": "webauthn-register",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 70,
+      "config": {}
+    },
+    {
+      "alias": "webauthn-register-passwordless",
+      "name": "Webauthn Register Passwordless",
+      "providerId": "webauthn-register-passwordless",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 80,
+      "config": {}
+    },
+    {
+      "alias": "update_user_locale",
+      "name": "Update User Locale",
+      "providerId": "update_user_locale",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 1000,
+      "config": {}
+    }
+  ],
+  "browserFlow": "browser",
+  "registrationFlow": "registration",
+  "directGrantFlow": "direct grant",
+  "resetCredentialsFlow": "reset credentials",
+  "clientAuthenticationFlow": "clients",
+  "dockerAuthenticationFlow": "docker auth",
+  "attributes": {
+    "cibaBackchannelTokenDeliveryMode": "poll",
+    "cibaAuthRequestedUserHint": "login_hint",
+    "oauth2DevicePollingInterval": "5",
+    "clientOfflineSessionMaxLifespan": "0",
+    "clientSessionIdleTimeout": "0",
+    "clientOfflineSessionIdleTimeout": "0",
+    "cibaInterval": "5",
+    "realmReusableOtpCode": "false",
+    "cibaExpiresIn": "120",
+    "oauth2DeviceCodeLifespan": "600",
+    "parRequestUriLifespan": "60",
+    "clientSessionMaxLifespan": "0",
+    "frontendUrl": "",
+    "acr.loa.map": "{}"
+  },
+  "keycloakVersion": "21.0.2",
+  "userManagedAccessAllowed": false,
+  "clientProfiles": {
+    "profiles": []
+  },
+  "clientPolicies": {
+    "policies": []
+  }
+}
\ No newline at end of file
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java
index 53216689d5486ffc821da61eec9dfc4d6e441728..a4823fe1247e0ffc5c3acda15715e27cdd437bf6 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/KeycloakGateway.java
@@ -5,13 +5,14 @@ import at.tuwien.api.keycloak.UserDto;
 import at.tuwien.api.user.UserPasswordDto;
 import at.tuwien.exception.AccessDeniedException;
 import at.tuwien.exception.KeycloakRemoteException;
+import at.tuwien.exception.UserAlreadyExistsException;
 import at.tuwien.exception.UserNotFoundException;
 
 import java.util.UUID;
 
 public interface KeycloakGateway {
 
-    void createUser(UserCreateDto data) throws AccessDeniedException, KeycloakRemoteException;
+    void createUser(UserCreateDto data) throws AccessDeniedException, KeycloakRemoteException, UserAlreadyExistsException;
 
     void updateUserCredentials(UUID id, UserPasswordDto password) throws AccessDeniedException,
             KeycloakRemoteException;
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java
index 6068f1e1064410552dfcf2adefe42e93cee74311..9fb667381844506d01b7b3fdbddd27827e04d3d8 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/KeycloakGatewayImpl.java
@@ -5,6 +5,7 @@ import at.tuwien.api.user.UserPasswordDto;
 import at.tuwien.config.KeycloakConfig;
 import at.tuwien.exception.AccessDeniedException;
 import at.tuwien.exception.KeycloakRemoteException;
+import at.tuwien.exception.UserAlreadyExistsException;
 import at.tuwien.exception.UserNotFoundException;
 import at.tuwien.gateway.KeycloakGateway;
 import at.tuwien.mapper.UserMapper;
@@ -14,6 +15,7 @@ import org.springframework.http.*;
 import org.springframework.stereotype.Service;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
+import org.springframework.web.client.HttpClientErrorException;
 import org.springframework.web.client.HttpServerErrorException;
 import org.springframework.web.client.ResourceAccessException;
 import org.springframework.web.client.RestTemplate;
@@ -44,7 +46,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway {
         payload.add("client_id", "admin-cli");
         final ResponseEntity<TokenDto> response;
         try {
-            response = restTemplate.exchange("/api/auth/realms/master/protocol/openid-connect/token",
+            response = restTemplate.exchange("/realms/master/protocol/openid-connect/token",
                     HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class);
         } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
             log.error("Failed to obtain admin token: {}", e.getMessage());
@@ -54,18 +56,22 @@ public class KeycloakGatewayImpl implements KeycloakGateway {
     }
 
     @Override
-    public void createUser(UserCreateDto data) throws AccessDeniedException, KeycloakRemoteException {
+    public void createUser(UserCreateDto data) throws AccessDeniedException, KeycloakRemoteException,
+            UserAlreadyExistsException {
         /* obtain admin token */
         final HttpHeaders headers = new HttpHeaders();
         headers.set("Accept", "application/json");
         headers.set("Authorization", "Bearer " + obtainToken().getAccessToken());
         final ResponseEntity<Void> response;
         try {
-            response = restTemplate.exchange("/api/auth/admin/realms/dbrepo/users", HttpMethod.POST,
+            response = restTemplate.exchange("/admin/realms/dbrepo/users", HttpMethod.POST,
                     new HttpEntity<>(data, headers), Void.class);
         } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
             log.error("Failed to create user: {}", e.getMessage());
             throw new KeycloakRemoteException("Failed to create user: " + e.getMessage());
+        } catch (HttpClientErrorException.Conflict e) {
+            log.error("Conflict when creating user: {}", e.getMessage());
+            throw new UserAlreadyExistsException("Conflict when creating user: " + e.getMessage());
         }
         if (!response.getStatusCode().equals(HttpStatus.CREATED)) {
             log.error("Failed to create user: status {} was not expected", response.getStatusCode().value());
@@ -83,13 +89,13 @@ public class KeycloakGatewayImpl implements KeycloakGateway {
         final UpdateCredentialsDto payload = userMapper.passwordToUpdateCredentialsDto(data.getPassword());
         final ResponseEntity<Void> response;
         try {
-            response = restTemplate.exchange("/api/auth/admin/realms/dbrepo/users/" + id, HttpMethod.PUT,
+            response = restTemplate.exchange("/admin/realms/dbrepo/users/" + id, HttpMethod.PUT,
                     new HttpEntity<>(payload, headers), Void.class);
         } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
             log.error("Failed to update user credentials: {}", e.getMessage());
             throw new KeycloakRemoteException("Failed to update user credentials: " + e.getMessage());
         }
-        if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) {
+        if (!response.getStatusCode().equals(HttpStatus.NO_CONTENT)) {
             log.error("Failed to update user credentials: status {} was not expected", response.getStatusCode().value());
             throw new KeycloakRemoteException("Failed to update user credentials: status " + response.getStatusCode().value() + "was not expected");
         }
@@ -104,7 +110,7 @@ public class KeycloakGatewayImpl implements KeycloakGateway {
         headers.set("Authorization", "Bearer " + obtainToken().getAccessToken());
         final ResponseEntity<UserDto[]> response;
         try {
-            response = restTemplate.exchange("/api/auth/admin/realms/dbrepo/users/?username=" + username,
+            response = restTemplate.exchange("/admin/realms/dbrepo/users/?username=" + username,
                     HttpMethod.GET, new HttpEntity<>(null, headers), UserDto[].class);
         } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
             log.error("Failed to find user: {}", e.getMessage());
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/interceptor/KeycloakInterceptor.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/interceptor/KeycloakInterceptor.java
index f9e9e1d69db037a8e0402b6bb2e6ec358862b7f5..8f5ff4f024cf789556f988d93428f52707cd9053 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/interceptor/KeycloakInterceptor.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/interceptor/KeycloakInterceptor.java
@@ -47,7 +47,7 @@ public class KeycloakInterceptor implements ClientHttpRequestInterceptor {
         payload.add("client_id", "admin-cli");
         final ResponseEntity<TokenDto> response;
         try {
-            response = restTemplate.exchange(keycloakEndpoint + "/api/auth/realms/master/protocol/openid-connect/token",
+            response = restTemplate.exchange(keycloakEndpoint + "/realms/master/protocol/openid-connect/token",
                     HttpMethod.POST, new HttpEntity<>(payload, headers), TokenDto.class);
         } catch (ResourceAccessException | HttpServerErrorException.ServiceUnavailable e) {
             log.error("Failed to obtain admin token: {}", e.getMessage());
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java
index 4b0b453617dcd5062825343fe226fc01f27a0dd2..6a35daf1c0861e32062d84afe4a149182b528da3 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java
@@ -61,7 +61,7 @@ public interface UserService {
      * @param id   The user id.
      * @param data The new password.
      */
-    void updatePassword(UUID id, UserPasswordDto data) throws KeycloakRemoteException, AccessDeniedException;
+    void updatePassword(UUID id, UserPasswordDto data) throws KeycloakRemoteException, AccessDeniedException, UserNotFoundException;
 
     /**
      * Updates the user theme for a user with given id.
diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java
index c29f1b7d01ca19e7805b63de2e5f33b1a68e06b1..a151801be3b08456734b6a8eecd351b9649ebf5e 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java
@@ -10,9 +10,11 @@ import at.tuwien.repository.mdb.UserRepository;
 import at.tuwien.repository.sdb.UserIdxRepository;
 import at.tuwien.service.UserService;
 import lombok.extern.log4j.Log4j2;
+import org.apache.commons.codec.digest.DigestUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.nio.charset.StandardCharsets;
 import java.util.List;
 import java.util.Optional;
 import java.util.UUID;
@@ -68,6 +70,7 @@ public class UserServiceImpl implements UserService {
                 .username(data.getUsername())
                 .email(data.getEmail())
                 .themeDark(true)
+                .mariadbPassword(getMariaDbPassword(data.getPassword()))
                 .build();
         keycloakGateway.createUser(userMapper.signupRequestDtoToUserCreateDto(data));
         /* create at metadata database */
@@ -93,8 +96,14 @@ public class UserServiceImpl implements UserService {
     }
 
     @Override
-    public void updatePassword(UUID id, UserPasswordDto data) throws KeycloakRemoteException, AccessDeniedException {
+    public void updatePassword(UUID id, UserPasswordDto data) throws KeycloakRemoteException, AccessDeniedException,
+            UserNotFoundException {
+        final User user = find(id);
+        user.setMariadbPassword(getMariaDbPassword(data.getPassword()));
+        userRepository.save(user);
+        log.debug("updated password in metadata database");
         keycloakGateway.updateUserCredentials(id, data);
+        log.debug("updated password in keycloak");
         log.info("Updated user password with id {}", id);
     }
 
@@ -122,4 +131,9 @@ public class UserServiceImpl implements UserService {
             throw new UserEmailAlreadyExistsException("User with email " + email + " already exists in metadata database");
         }
     }
+
+    protected String getMariaDbPassword(String password) {
+        final byte[] utf8 = password.getBytes(StandardCharsets.UTF_8);
+        return "*" + DigestUtils.sha1Hex(DigestUtils.sha1(utf8)).toUpperCase();
+    }
 }