diff --git a/alfa-client/apps/admin/src/app/app.component.spec.ts b/alfa-client/apps/admin/src/app/app.component.spec.ts
index f062db31f82f5052a760630ad38da8e7e52edbf5..7789cebe72549c662115feb3c1162c5346b5e4a0 100644
--- a/alfa-client/apps/admin/src/app/app.component.spec.ts
+++ b/alfa-client/apps/admin/src/app/app.component.spec.ts
@@ -22,6 +22,7 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { ConfigurationLinkRel, ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared';
+import { KeycloakTokenService } from '@admin/keycloak-shared';
 import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared';
 import { BuildInfoComponent } from '@alfa-client/common';
 import { HasLinkPipe, createEmptyStateResource, createStateResource } from '@alfa-client/tech-shared';
@@ -39,7 +40,6 @@ import {
 } from '@ods/system';
 import { createConfigurationResource } from 'libs/admin/configuration-shared/test/configuration';
 import { MenuContainerComponent } from 'libs/admin/configuration/src/lib/menu-container/menu-container.component';
-import { KeycloakTokenService } from 'libs/admin/shared/src/lib/keycloak/keycloak-token.service';
 import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent, MockDirective } from 'ng-mocks';
diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts
index 7959078d1e435db1870485a5da0430c0464fdfb1..a523590d12806227b1aad8f7b1fca8b4d0a996eb 100644
--- a/alfa-client/apps/admin/src/app/app.component.ts
+++ b/alfa-client/apps/admin/src/app/app.component.ts
@@ -24,6 +24,7 @@
 import { MenuContainerComponent } from '@admin-client/configuration';
 import { ConfigurationLinkRel, ConfigurationResource, ConfigurationService } from '@admin-client/configuration-shared';
 import { ROUTES } from '@admin-client/shared';
+import { KeycloakTokenService } from '@admin/keycloak-shared';
 import { ApiRootLinkRel, ApiRootResource, ApiRootService } from '@alfa-client/api-root-shared';
 import { BuildInfoComponent } from '@alfa-client/common';
 import { isLoaded, isNotUndefined, mapToResource, StateResource, TechSharedModule } from '@alfa-client/tech-shared';
@@ -40,7 +41,6 @@ import {
   UsersIconComponent,
 } from '@ods/system';
 import { filter, Observable, Subscription } from 'rxjs';
-import { KeycloakTokenService } from '../../../../libs/admin/shared/src/lib/keycloak/keycloak-token.service';
 import { UserProfileButtonContainerComponent } from '../common/user-profile-button-container/user-profile.button-container.component';
 import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component';
 
diff --git a/alfa-client/libs/admin/keycloak-shared/.eslintrc.json b/alfa-client/libs/admin/keycloak-shared/.eslintrc.json
new file mode 100644
index 0000000000000000000000000000000000000000..b10f9813a8f5c59432cf245301dc4d01a8031fd1
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/.eslintrc.json
@@ -0,0 +1,33 @@
+{
+  "extends": ["../../../.eslintrc.json"],
+  "ignorePatterns": ["!**/*"],
+  "overrides": [
+    {
+      "files": ["*.ts"],
+      "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"],
+      "rules": {
+        "@angular-eslint/directive-selector": [
+          "error",
+          {
+            "type": "attribute",
+            "prefix": "lib",
+            "style": "camelCase"
+          }
+        ],
+        "@angular-eslint/component-selector": [
+          "error",
+          {
+            "type": "element",
+            "prefix": "lib",
+            "style": "kebab-case"
+          }
+        ]
+      }
+    },
+    {
+      "files": ["*.html"],
+      "extends": ["plugin:@nx/angular-template"],
+      "rules": {}
+    }
+  ]
+}
diff --git a/alfa-client/libs/admin/keycloak-shared/README.md b/alfa-client/libs/admin/keycloak-shared/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..64e0f40f766db575830e3690582b8139409be0b8
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/README.md
@@ -0,0 +1,7 @@
+# admin-keycloak
+
+This library was generated with [Nx](https://nx.dev).
+
+## Running unit tests
+
+Run `nx test admin-keycloak` to execute the unit tests.
diff --git a/alfa-client/libs/admin/keycloak-shared/jest.config.ts b/alfa-client/libs/admin/keycloak-shared/jest.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..71e242bbaf2095da5c4bab0ce9af18f3bd7a3440
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/jest.config.ts
@@ -0,0 +1,22 @@
+const esModules = ['@keycloak/keycloak-admin-client', 'url-join', 'url-template', 'camelize-ts'];
+export default {
+  displayName: 'admin-keycloak-shared',
+  preset: '../../../jest.preset.js',
+  setupFilesAfterEnv: ['<rootDir>/src/test-setup.ts'],
+  coverageDirectory: '../../../coverage/libs/admin/keycloak',
+  transform: {
+    '^.+\\.(ts|mjs|js|html)$': [
+      'jest-preset-angular',
+      {
+        tsconfig: '<rootDir>/tsconfig.spec.json',
+        stringifyContentPathRegex: '\\.(html|svg)$',
+      },
+    ],
+  },
+  transformIgnorePatterns: [`node_modules/(?!.pnpm|.*\\.mjs$|${esModules.join('|')})`],
+  snapshotSerializers: [
+    'jest-preset-angular/build/serializers/no-ng-attributes',
+    'jest-preset-angular/build/serializers/ng-snapshot',
+    'jest-preset-angular/build/serializers/html-comment',
+  ],
+};
diff --git a/alfa-client/libs/admin/keycloak-shared/project.json b/alfa-client/libs/admin/keycloak-shared/project.json
new file mode 100644
index 0000000000000000000000000000000000000000..e3966576f9425d7599fad9a0bfb08f9fbc64697e
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/project.json
@@ -0,0 +1,20 @@
+{
+  "name": "admin-keycloak-shared",
+  "$schema": "../../../node_modules/nx/schemas/project-schema.json",
+  "sourceRoot": "libs/admin/keycloak-shared/src",
+  "prefix": "lib",
+  "projectType": "library",
+  "tags": [],
+  "targets": {
+    "test": {
+      "executor": "@nx/jest:jest",
+      "outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
+      "options": {
+        "jestConfig": "libs/admin/keycloak-shared/jest.config.ts"
+      }
+    },
+    "lint": {
+      "executor": "@nx/eslint:lint"
+    }
+  }
+}
diff --git a/alfa-client/libs/admin/keycloak-shared/src/index.ts b/alfa-client/libs/admin/keycloak-shared/src/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b0e24572b79fae2fa13d859fc348d5319e8229e1
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/src/index.ts
@@ -0,0 +1,3 @@
+export * from './lib/keycloak-token.service';
+export * from './lib/organisations-einheit.repository';
+export * from './lib/user.repository';
diff --git a/alfa-client/libs/admin/shared/src/lib/keycloak/keycloak-token.service.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.spec.ts
similarity index 100%
rename from alfa-client/libs/admin/shared/src/lib/keycloak/keycloak-token.service.spec.ts
rename to alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.spec.ts
diff --git a/alfa-client/libs/admin/shared/src/lib/keycloak/keycloak-token.service.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.ts
similarity index 100%
rename from alfa-client/libs/admin/shared/src/lib/keycloak/keycloak-token.service.ts
rename to alfa-client/libs/admin/keycloak-shared/src/lib/keycloak-token.service.ts
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts
similarity index 95%
rename from alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.spec.ts
rename to alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts
index d4b38346168e17dd3db1bb9f2ed2b2df1aed6c61..001f591f358f74c4fda4ea438e40e06268c6b162 100644
--- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.spec.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.spec.ts
@@ -3,7 +3,7 @@ import { mock, Mock } from '@alfa-client/test-utils';
 import { TestBed } from '@angular/core/testing';
 import KcAdminClient from '@keycloak/keycloak-admin-client';
 import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
-import { createGroupRep } from '../test/organisations-einheit';
+import { createGroupRep } from '../../../organisations-einheit-shared/src/test/organisations-einheit';
 import { AdminOrganisationsEinheitRepository } from './organisations-einheit.repository';
 
 describe('AdminOrganisationsEinheitRepository', () => {
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts
similarity index 100%
rename from alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.repository.ts
rename to alfa-client/libs/admin/keycloak-shared/src/lib/organisations-einheit.repository.ts
diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.repository.service.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts
similarity index 98%
rename from alfa-client/libs/admin/user-shared/src/lib/user.repository.service.spec.ts
rename to alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts
index 935fab4923c9e6d069b15768930a128de7c8c640..2c58c0f784361b21e27ca915453fb5b4748f632e 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/user.repository.service.spec.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts
@@ -21,6 +21,8 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { User } from '@admin-client/user-shared';
+import { UserRepository } from '@admin/keycloak-shared';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { TestBed, fakeAsync, tick } from '@angular/core/testing';
 import { faker } from '@faker-js/faker';
@@ -30,10 +32,8 @@ import MappingsRepresentation from '@keycloak/keycloak-admin-client/lib/defs/map
 import { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
 import { cold } from 'jest-marbles';
 import { throwError } from 'rxjs';
+import { createUser } from '../../../user-shared/test/user';
 import { UserAddFormservice } from '../../../user/src/lib/users-roles/user-add-form/user-add.formservice';
-import { createUser } from '../../test/user';
-import { User } from './user.model';
-import { UserRepository } from './user.repository.service';
 
 describe('UserRepository', () => {
   let repository: UserRepository;
diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.repository.service.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts
similarity index 98%
rename from alfa-client/libs/admin/user-shared/src/lib/user.repository.service.ts
rename to alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts
index 83c95617065be3fa8ff877abea0ae014758424b5..3cc644b06842127a2d4d62a79137b13a4957b22e 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/user.repository.service.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts
@@ -21,6 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ClientMapping, ClientRoles, User } from '@admin-client/user-shared';
 import { inject, Injectable } from '@angular/core';
 import KcAdminClient from '@keycloak/keycloak-admin-client';
 import ClientRepresentation from '@keycloak/keycloak-admin-client/lib/defs/clientRepresentation';
@@ -30,7 +31,6 @@ import RoleRepresentation, { RoleMappingPayload } from '@keycloak/keycloak-admin
 import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation';
 import { isNil } from 'lodash-es';
 import { catchError, concatMap, forkJoin, from, map, mergeMap, Observable, switchMap, tap, throwError } from 'rxjs';
-import { ClientMapping, ClientRoles, User } from './user.model';
 
 @Injectable({
   providedIn: 'root',
diff --git a/alfa-client/libs/admin/keycloak-shared/src/test-setup.ts b/alfa-client/libs/admin/keycloak-shared/src/test-setup.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c408668266d2fec3a9803c0ec044bc163fb987fe
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/src/test-setup.ts
@@ -0,0 +1,12 @@
+import '@testing-library/jest-dom';
+import 'jest-preset-angular/setup-jest';
+
+import { getTestBed } from '@angular/core/testing';
+import { BrowserDynamicTestingModule, platformBrowserDynamicTesting } from '@angular/platform-browser-dynamic/testing';
+
+getTestBed().resetTestEnvironment();
+getTestBed().initTestEnvironment(BrowserDynamicTestingModule, platformBrowserDynamicTesting(), {
+  teardown: { destroyAfterEach: false },
+  errorOnUnknownProperties: true,
+  errorOnUnknownElements: true,
+});
diff --git a/alfa-client/libs/admin/keycloak-shared/tsconfig.json b/alfa-client/libs/admin/keycloak-shared/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..8ca9ad312c2bd4dc364383853ddd91a2ed8f86fd
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/tsconfig.json
@@ -0,0 +1,16 @@
+{
+  "extends": "../../../tsconfig.base.json",
+  "files": [],
+  "include": [],
+  "references": [
+    {
+      "path": "./tsconfig.lib.json"
+    },
+    {
+      "path": "./tsconfig.spec.json"
+    }
+  ],
+  "compilerOptions": {
+    "target": "es2022"
+  }
+}
diff --git a/alfa-client/libs/admin/keycloak-shared/tsconfig.lib.json b/alfa-client/libs/admin/keycloak-shared/tsconfig.lib.json
new file mode 100644
index 0000000000000000000000000000000000000000..8441346f6e5858b2ef4235cb3c3160eda256f94a
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/tsconfig.lib.json
@@ -0,0 +1,12 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../../dist/out-tsc",
+    "declaration": true,
+    "declarationMap": true,
+    "inlineSources": true,
+    "types": []
+  },
+  "exclude": ["src/**/*.spec.ts", "src/test-setup.ts", "jest.config.ts", "src/**/*.test.ts"],
+  "include": ["src/**/*.ts"]
+}
diff --git a/alfa-client/libs/admin/keycloak-shared/tsconfig.spec.json b/alfa-client/libs/admin/keycloak-shared/tsconfig.spec.json
new file mode 100644
index 0000000000000000000000000000000000000000..723782fbd367969806c5992aea882773ab65af8b
--- /dev/null
+++ b/alfa-client/libs/admin/keycloak-shared/tsconfig.spec.json
@@ -0,0 +1,12 @@
+{
+  "extends": "./tsconfig.json",
+  "compilerOptions": {
+    "outDir": "../../../dist/out-tsc",
+    "module": "commonjs",
+    "types": ["jest", "node"],
+    "target": "ES2022",
+    "useDefineForClassFields": false
+  },
+  "files": ["src/test-setup.ts"],
+  "include": ["**/*.test.ts", "**/*.spec.ts", "**/*.d.ts", "jest.config.ts"]
+}
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts
index e1c23ad8873eda2ab82b28c8168ad8c0b575d16d..26aba0d2639fa0d8a0f629cf31ac1cd598b1e5bb 100644
--- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts
+++ b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.spec.ts
@@ -22,10 +22,10 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { AdminOrganisationsEinheit, AdminOrganisationsEinheitService } from '@admin-client/organisations-einheit-shared';
+import { AdminOrganisationsEinheitRepository } from '@admin/keycloak-shared';
 import { Mock, mock } from '@alfa-client/test-utils';
 import { TestBed } from '@angular/core/testing';
 import { createAdminOrganisationsEinheit } from '../test/organisations-einheit';
-import { AdminOrganisationsEinheitRepository } from './organisations-einheit.repository';
 
 describe('AdminOrganisationsEinheitService', () => {
   let service: AdminOrganisationsEinheitService;
@@ -43,7 +43,7 @@ describe('AdminOrganisationsEinheitService', () => {
 
   describe('getItemsFromKeycloak', () => {
     it('should call repository getList', () => {
-      service.getItemsFromKeycloak();
+      (service as any).getItemsFromKeycloak();
       expect(repository.getList).toHaveBeenCalled();
     });
   });
@@ -51,7 +51,7 @@ describe('AdminOrganisationsEinheitService', () => {
   describe('createInKeycloak', () => {
     const organisationsEiheit: AdminOrganisationsEinheit = createAdminOrganisationsEinheit();
     it('should call repository create', () => {
-      service.createInKeycloak(organisationsEiheit);
+      (service as any).createInKeycloak(organisationsEiheit);
       expect(repository.create).toHaveBeenCalledWith(organisationsEiheit);
     });
   });
diff --git a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts
index 0c6bacf0c2c4baad9e971df9ccb5afec13a2dcba..ad2e0009e9a52c4a8970a4cdbe3f5b53cfe1d175 100644
--- a/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts
+++ b/alfa-client/libs/admin/organisations-einheit-shared/src/lib/organisations-einheit.service.ts
@@ -21,34 +21,31 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Injectable } from '@angular/core';
+import { AdminOrganisationsEinheitRepository } from '@admin/keycloak-shared';
+import { inject, Injectable } from '@angular/core';
 import { Observable } from 'rxjs';
 import { KeycloakResourceService } from '../../../user-shared/src/lib/keycloak.resource.service';
 import { AdminOrganisationsEinheit } from './organisations-einheit.model';
-import { AdminOrganisationsEinheitRepository } from './organisations-einheit.repository';
 
 @Injectable({
   providedIn: 'root',
 })
 export class AdminOrganisationsEinheitService extends KeycloakResourceService<AdminOrganisationsEinheit> {
-  //todo: test inject
-  constructor(private repository: AdminOrganisationsEinheitRepository) {
-    super();
-  }
+  private readonly repository = inject(AdminOrganisationsEinheitRepository);
 
-  getItemsFromKeycloak(): Observable<AdminOrganisationsEinheit[]> {
+  protected getItemsFromKeycloak(): Observable<AdminOrganisationsEinheit[]> {
     return this.repository.getList();
   }
 
-  createInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<AdminOrganisationsEinheit> {
+  protected createInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<AdminOrganisationsEinheit> {
     return this.repository.create(organisationsEinheit);
   }
 
-  saveInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<void> {
+  protected saveInKeycloak(organisationsEinheit: AdminOrganisationsEinheit): Observable<void> {
     throw new Error('Method not implemented.');
   }
 
-  deleteInKeycloak(id: string): Observable<void> {
+  protected deleteInKeycloak(id: string): Observable<void> {
     throw new Error('Method not implemented.');
   }
 }
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts
index 51cfb933dad24881ca93c4f50ca0f7722b1c90a3..aa95754e2879568e6f4c893a2b59615b6aa06ecf 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-container.component.spec.ts
@@ -132,7 +132,7 @@ describe('OrganisationsEinheitContainerComponent', () => {
 
       it('should have organisationsEinheitResources', () => {
         const listComponent: OrganisationsEinheitListComponent = getMockComponent(fixture, OrganisationsEinheitListComponent);
-        expect(listComponent.organisationsEinheitListResource).toBeTruthy();
+        expect(listComponent.organisationsEinheitList).toBeTruthy();
       });
     });
   });
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html
index 04f00bf619eff4e2eb832fc04ddac06b7b2a184a..2b55de16de82452e9f9baacdee1754ee356df7a8 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.html
@@ -23,9 +23,9 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ods-list *ngIf="!isNil(organisationsEinheitListResource)" data-test-id="organisations-einheit-list">
+<ods-list *ngIf="!isNil(organisationsEinheitList)" data-test-id="organisations-einheit-list">
   <ods-list-item
-    *ngFor="let organisationsEinheitResource of organisationsEinheitListResource"
+    *ngFor="let organisationsEinheitResource of organisationsEinheitList"
     data-test-id="organisations-einheit-list-item"
   >
     <dl class="flex-1 basis-3/4 font-semibold">
@@ -34,3 +34,4 @@
     </dl>
   </ods-list-item>
 </ods-list>
+ssda
\ No newline at end of file
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts
index 7277b7aa52f9cfe72de727860ef905479679b69e..d80a3a54260b1f838767e1b54d127bfbad4106ff 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.spec.ts
@@ -81,7 +81,7 @@ describe('OrganisationsEinheitListComponent', () => {
           createAdminOrganisationsEinheit(),
         ];
         beforeEach(() => {
-          component.organisationsEinheitListResource = organisationsEinheiten;
+          component.organisationsEinheitList = organisationsEinheiten;
           fixture.detectChanges();
         });
 
diff --git a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts
index 58d5a086bb989c8c28fb6075f4ff3568d25393dc..377768cc350898e054bd533113aa7e832e40a2d6 100644
--- a/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts
+++ b/alfa-client/libs/admin/organisations-einheit/src/lib/organisations-einheit-container/organisations-einheit-list/organisations-einheit-list.component.ts
@@ -35,7 +35,7 @@ import { isNil } from 'lodash-es';
   imports: [CommonModule, ListComponent, ListItemComponent, ExclamationIconComponent, TooltipDirective, TechSharedModule],
 })
 export class OrganisationsEinheitListComponent {
-  @Input() public organisationsEinheitListResource: AdminOrganisationsEinheit[];
+  @Input() public organisationsEinheitList: AdminOrganisationsEinheit[];
 
   protected readonly isNil = isNil;
 }
diff --git a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts b/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts
index 228f1b0cfaec928f6c70ec566b92d5ae3250eb25..9855a20ebefe86e37ea51815ca5470249fd9c562 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts
+++ b/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.spec.ts
@@ -87,7 +87,7 @@ describe('KeycloakResourceService', () => {
 
     it('should update Resource', fakeAsync(() => {
       const dummyItems = [createDummy(), createDummy()];
-      service.getItemsFromKeycloak = jest.fn().mockReturnValue(of(dummyItems));
+      jest.spyOn(service, 'getItemsFromKeycloak' as any).mockReturnValue(of(dummyItems));
 
       service.loadResource();
       tick();
@@ -108,11 +108,11 @@ describe('KeycloakResourceService', () => {
     });
 
     it('should call createInKeycloak', () => {
-      service.createInKeycloak = jest.fn().mockReturnValue(of({}));
+      const createInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, 'createInKeycloak' as any).mockReturnValue(of({}));
 
       service.create(saveObject);
 
-      expect(service.createInKeycloak).toHaveBeenCalled();
+      expect(createInKeycloakSpy).toHaveBeenCalled();
     });
   });
 
@@ -126,11 +126,11 @@ describe('KeycloakResourceService', () => {
     });
 
     it('should call createInKeycloak', () => {
-      service.saveInKeycloak = jest.fn().mockReturnValue(of({}));
+      const saveInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, 'saveInKeycloak' as any).mockReturnValue(of({}));
 
       service.save(dummyObject);
 
-      expect(service.saveInKeycloak).toHaveBeenCalled();
+      expect(saveInKeycloakSpy).toHaveBeenCalled();
     });
   });
 
@@ -144,11 +144,11 @@ describe('KeycloakResourceService', () => {
     });
 
     it('should call createInKeycloak', () => {
-      service.saveInKeycloak = jest.fn().mockReturnValue(of({}));
+      const saveInKeycloakSpy: jest.SpyInstance = jest.spyOn(service, 'saveInKeycloak' as any).mockReturnValue(of({}));
 
       service.save(id);
 
-      expect(service.saveInKeycloak).toHaveBeenCalled();
+      expect(saveInKeycloakSpy).toHaveBeenCalled();
     });
   });
 
diff --git a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts b/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts
index b1fa837255e8816649e149ff2bbb60c4d5e97b7a..9dc055b4bc0d1084a6209ccff6cc0b3ceece14b0 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts
+++ b/alfa-client/libs/admin/user-shared/src/lib/keycloak.resource.service.ts
@@ -43,7 +43,7 @@ export abstract class KeycloakResourceService<T> {
       .subscribe((items) => this.updateResource(items));
   }
 
-  abstract getItemsFromKeycloak(): Observable<T[]>;
+  protected abstract getItemsFromKeycloak(): Observable<T[]>;
 
   private updateResource(items: T[]): void {
     this.stateResource.next(createStateResource(items));
@@ -53,19 +53,19 @@ export abstract class KeycloakResourceService<T> {
     return this.handleLoading(this.createInKeycloak(item));
   }
 
-  abstract createInKeycloak(item: Partial<T>): Observable<T>;
+  protected abstract createInKeycloak(item: Partial<T>): Observable<T>;
 
   public save(item: T): Observable<boolean> {
     return this.handleLoading(this.saveInKeycloak(item));
   }
 
-  abstract saveInKeycloak(item: T): Observable<void>;
+  protected abstract saveInKeycloak(item: T): Observable<void>;
 
   public delete(id: string): Observable<boolean> {
     return this.handleLoading(this.deleteInKeycloak(id));
   }
 
-  abstract deleteInKeycloak(id: string): Observable<void>;
+  protected abstract deleteInKeycloak(id: string): Observable<void>;
 
   handleLoading(action: Observable<unknown>): Observable<boolean> {
     this.setLoading();
diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts b/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts
index c1148ee01e76d476ddf204eafee43060a936ad38..4769d32ed5c7629d3dc157426e8b581afedc346e 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts
+++ b/alfa-client/libs/admin/user-shared/src/lib/user.service.spec.ts
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { mock, Mock, useFromMock } from '@alfa-client/test-utils';
-import { fakeAsync, tick } from '@angular/core/testing';
+import { UserRepository } from '@admin/keycloak-shared';
+import { mock, Mock } from '@alfa-client/test-utils';
+import { fakeAsync, TestBed, tick } from '@angular/core/testing';
 import { of } from 'rxjs';
 import { createUser } from '../../test/user';
 import { User } from './user.model';
-import { UserRepository } from './user.repository.service';
 import { UserService } from './user.service';
 import * as UserUtil from './user.util';
 
@@ -38,12 +38,15 @@ describe('UserService', () => {
 
   beforeEach(() => {
     repository = { ...mock(UserRepository), getUsers: jest.fn().mockReturnValue(of([user])) };
-    service = new UserService(useFromMock(repository));
+    TestBed.configureTestingModule({
+      providers: [{ provide: UserRepository, useValue: repository }],
+    });
+    service = TestBed.inject(UserService);
   });
 
   describe('getItemsFromKeycloak', () => {
     it('should call getUsers from userRepository', () => {
-      service.getItemsFromKeycloak();
+      (service as any).getItemsFromKeycloak();
 
       expect(repository.getUsers).toHaveBeenCalled();
     });
@@ -51,7 +54,7 @@ describe('UserService', () => {
     it('should call sortUsersByLastName', fakeAsync(() => {
       const sortUsersByLastNameSpy: jest.SpyInstance<User[]> = jest.spyOn(UserUtil, 'sortUsersByLastName');
 
-      service.getItemsFromKeycloak().subscribe();
+      (service as any).getItemsFromKeycloak().subscribe();
       tick();
 
       expect(sortUsersByLastNameSpy).toHaveBeenCalled();
@@ -62,7 +65,7 @@ describe('UserService', () => {
     const user: User = createUser();
 
     it('should call createInKeycloak from userRepository', () => {
-      service.createInKeycloak(user);
+      (service as any).createInKeycloak(user);
 
       expect(repository.createInKeycloak).toHaveBeenCalledWith(user);
     });
diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.service.ts b/alfa-client/libs/admin/user-shared/src/lib/user.service.ts
index 9cbe06b6009eb72145d4c3447940bd30f39fb7d3..76ef2e216284522871b00c7715f7cb1f8997ba43 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/user.service.ts
+++ b/alfa-client/libs/admin/user-shared/src/lib/user.service.ts
@@ -21,35 +21,32 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { Injectable } from '@angular/core';
+import { UserRepository } from '@admin/keycloak-shared';
+import { inject, Injectable } from '@angular/core';
 import { map, Observable } from 'rxjs';
 import { KeycloakResourceService } from './keycloak.resource.service';
 import { User } from './user.model';
-import { UserRepository } from './user.repository.service';
 import { sortUsersByLastName } from './user.util';
 
 @Injectable({
   providedIn: 'root',
 })
 export class UserService extends KeycloakResourceService<User> {
-  // todo: test inject
-  constructor(private userRepository: UserRepository) {
-    super();
-  }
+  private readonly userRepository = inject(UserRepository);
 
-  getItemsFromKeycloak(): Observable<User[]> {
+  protected getItemsFromKeycloak(): Observable<User[]> {
     return this.userRepository.getUsers().pipe(map(sortUsersByLastName));
   }
 
-  createInKeycloak(user: Partial<User>): Observable<User> {
+  protected createInKeycloak(user: Partial<User>): Observable<User> {
     return this.userRepository.createInKeycloak(user);
   }
 
-  saveInKeycloak(user: User): Observable<void> {
+  protected saveInKeycloak(user: User): Observable<void> {
     throw new Error('Method not implemented.');
   }
 
-  deleteInKeycloak(id: string): Observable<void> {
+  protected deleteInKeycloak(id: string): Observable<void> {
     throw new Error('Method not implemented.');
   }
 }
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts
index 93b68bb79ea62249b7864cd63bc3f5d706e0dfcf..f347f2a1a63692a3225c5824c19f2476af9855ef 100644
--- a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts
+++ b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.spec.ts
@@ -31,7 +31,6 @@ import { fakeAsync, TestBed, tick } from '@angular/core/testing';
 import { AbstractControl, UntypedFormBuilder, UntypedFormGroup } from '@angular/forms';
 import { cold } from 'jest-marbles';
 import { createUser } from 'libs/admin/user-shared/test/user';
-import { singleCold } from 'libs/tech-shared/test/marbles';
 import { of, throwError } from 'rxjs';
 import { UserAddFormservice } from './user-add.formservice';
 import SpyInstance = jest.SpyInstance;
@@ -47,7 +46,7 @@ describe('UserAddFormService', () => {
   let snackBarService: Mock<SnackBarService>;
 
   beforeEach(() => {
-    userService = { ...mock(UserService), refresh: jest.fn() };
+    userService = { ...mock(UserService), refresh: jest.fn(), create: jest.fn() };
     navigationService = mock(NavigationService);
     snackBarService = mock(SnackBarService);
 
@@ -181,7 +180,7 @@ describe('UserAddFormService', () => {
     const user: User = createUser();
 
     beforeEach(() => {
-      userService.createInKeycloak.mockReturnValue(of(user));
+      userService.create.mockReturnValue(of(false));
     });
 
     it('should call createUser', () => {
@@ -192,26 +191,30 @@ describe('UserAddFormService', () => {
       expect(createUserSpy).toHaveBeenCalled();
     });
 
-    it('should call userService createInKeycloak', () => {
+    it('should call userService create', () => {
+      jest.spyOn(formService as any, 'createUser').mockReturnValue(user);
+
       formService.submit();
 
-      expect(userService.createInKeycloak).toHaveBeenCalled();
+      expect(userService.create).toHaveBeenCalledWith(user);
     });
 
-    it('should return user as stateResource', fakeAsync(() => {
-      userService.createInKeycloak.mockReturnValue(singleCold(user, '-a'));
+    it('should return user as stateResource', () => {
+      userService.create.mockReturnValue(cold('-ab', { a: true, b: false }));
+      jest.spyOn(formService as any, 'createUser').mockReturnValue(user);
 
       const result = formService.submit();
 
       expect(result).toBeObservable(
-        cold('ab', {
+        cold('abc', {
           a: createEmptyStateResource<User>(true),
-          b: createStateResource(user),
+          b: createStateResource(user, true),
+          c: createStateResource(user, false),
         }),
       );
-    }));
+    });
 
-    it('should call handleOnCreateUserSuccess', fakeAsync(() => {
+    it('should call handleOnCreateUserSuccess if not loading', fakeAsync(() => {
       const handleOnCreateUserSuccessSpy: SpyInstance = jest.spyOn(formService, 'handleOnCreateUserSuccess');
 
       formService.submit().subscribe();
@@ -220,8 +223,18 @@ describe('UserAddFormService', () => {
       expect(handleOnCreateUserSuccessSpy).toHaveBeenCalled();
     }));
 
+    it('should not call handleOnCreateUserSuccess if loading', fakeAsync(() => {
+      userService.create.mockReturnValue(of(true));
+      const handleOnCreateUserSuccessSpy: SpyInstance = jest.spyOn(formService, 'handleOnCreateUserSuccess');
+
+      formService.submit().subscribe();
+      tick();
+
+      expect(handleOnCreateUserSuccessSpy).not.toHaveBeenCalled();
+    }));
+
     it('should call handleSubmitError on error', fakeAsync(() => {
-      userService.createInKeycloak.mockReturnValue(throwError(() => new Error()));
+      userService.create.mockReturnValue(throwError(() => new Error()));
       const handleSubmitErrorSpy: SpyInstance = jest.spyOn(formService, 'handleSubmitError');
 
       formService.submit().subscribe();
@@ -243,12 +256,6 @@ describe('UserAddFormService', () => {
 
       expect(navigationService.navigate).toHaveBeenCalledWith(ROUTES.BENUTZER_UND_ROLLEN);
     });
-
-    it('should refresh userList', () => {
-      formService.handleOnCreateUserSuccess();
-
-      expect(userService.refresh).toHaveBeenCalled();
-    });
   });
 
   describe('handleSubmitError', () => {
diff --git a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts
index 5a6769f495ca2e04048c715bd878959a94486395..dd10a07fb294fc452d893af76750d33c5e7c4efc 100644
--- a/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts
+++ b/alfa-client/libs/admin/user/src/lib/users-roles/user-add-form/user-add.formservice.ts
@@ -147,19 +147,22 @@ export class UserAddFormservice extends AbstractFormService<User> {
   }
 
   protected doSubmit(): Observable<StateResource<User>> {
-    const user: Partial<User> = this.createUser();
-    return this.userService.createInKeycloak(user).pipe(
-      map((createdUser: User): StateResource<User> => createStateResource(createdUser)),
-      tap(() => this.handleOnCreateUserSuccess()),
+    const user: User = this.createUser();
+    return this.userService.create(user).pipe(
+      tap((loading: boolean): void => this.executeIfNotLoading(loading, () => this.handleOnCreateUserSuccess())),
+      map((loading: boolean): StateResource<User> => createStateResource<User>(user, loading)),
       catchError((): Observable<StateResource<User>> => this.handleSubmitError()),
       startWith(createEmptyStateResource<User>(true)),
     );
   }
 
+  private executeIfNotLoading(loading: boolean, func: () => void): void {
+    if (!loading) func();
+  }
+
   handleOnCreateUserSuccess(): void {
     this.snackBarService.showInfo('Der Benutzer wurde hinzugefügt.');
     this.navigationService.navigate(ROUTES.BENUTZER_UND_ROLLEN);
-    this.userService.refresh();
   }
 
   handleSubmitError(): Observable<StateResource<User>> {
@@ -167,8 +170,9 @@ export class UserAddFormservice extends AbstractFormService<User> {
     return of(createEmptyStateResource<User>());
   }
 
-  createUser(): Partial<User> {
+  createUser(): User {
     return {
+      id: EMPTY_STRING,
       email: this.form.get(UserAddFormservice.EMAIL).value,
       username: this.form.get(UserAddFormservice.BENUTZERNAME).value,
       firstName: this.form.get(UserAddFormservice.VORNAME).value,
diff --git a/alfa-client/tsconfig.base.json b/alfa-client/tsconfig.base.json
index 2014ad63b1ebdbf8c2b31b7259bcc0d77011dd4b..645b71e1ced60632f86bbe1484b8d0ba45b27c84 100644
--- a/alfa-client/tsconfig.base.json
+++ b/alfa-client/tsconfig.base.json
@@ -18,6 +18,7 @@
     "paths": {
       "@admin-client/configuration": ["libs/admin/configuration/src/index.ts"],
       "@admin-client/configuration-shared": ["libs/admin/configuration-shared/src/index.ts"],
+      "@admin/keycloak-shared": ["libs/admin/keycloak-shared/src/index.ts"],
       "@admin-client/organisations-einheit": ["libs/admin/organisations-einheit/src/index.ts"],
       "@admin-client/organisations-einheit-shared": ["libs/admin/organisations-einheit-shared/src/index.ts"],
       "@admin-client/postfach": ["libs/admin/postfach/src/index.ts"],
@@ -76,7 +77,7 @@
       "@alfa-client/zustaendige-stelle-shared": ["libs/zustaendige-stelle-shared/src/index.ts"],
       "@authentication": ["libs/authentication/src/index.ts"],
       "@ods/component": ["libs/design-component/src/index.ts"],
-      "@ods/system": ["libs/design-system/src/index.ts"]
+      "@ods/system": ["libs/design-system/src/index.ts"],
     }
   },
   "exclude": ["node_modules", "tmp"]