diff --git a/alfa-client/apps/admin-e2e/src/components/benutzer/benutzer.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/benutzer/benutzer.e2e.component.ts
index bdf514f6f2b5fd78539ffcee8ca271131bb1f483..673ea2c47571873cc69795547f6dc5359609e99a 100644
--- a/alfa-client/apps/admin-e2e/src/components/benutzer/benutzer.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/benutzer/benutzer.e2e.component.ts
@@ -115,6 +115,10 @@ export class BenutzerE2EComponent {
     return cy.getTestElement(this.headline);
   }
 
+  public getHeadline(): Cypress.Chainable<Element> {
+    return cy.getTestElement(this.headline);
+  }
+
   public getVornameInput(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.userVorname);
   }
diff --git a/alfa-client/apps/admin-e2e/src/components/postfach/postfach.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/postfach/postfach.e2e.component.ts
index 62527711781b022092af5336db78779b0df2c914..f177cf791efec0113ceaebf9d6098e2008bc21f9 100644
--- a/alfa-client/apps/admin-e2e/src/components/postfach/postfach.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/postfach/postfach.e2e.component.ts
@@ -21,19 +21,24 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { haveValue, typeText } from '../../support/cypress.util';
+import { haveValue } from '../../support/cypress.util';
 
 export class PostfachE2EComponent {
+  private readonly headline: string = 'headline';
   private readonly signaturText: string = 'signature-textarea';
   private readonly saveSignaturButton: string = 'save-button';
 
+  public getHeadline(): any {
+    return cy.getTestElement(this.headline);
+  }
+
   public getSignaturText(): any {
     return cy.getTestElement(this.signaturText);
   }
 
   public setSignatur(signatur: string): void {
     this.clearSignatur();
-    typeText(this.getSignaturText(), signatur);
+    this.getSignaturText().type(signatur);
   }
 
   public clearSignatur(): void {
diff --git a/alfa-client/apps/admin-e2e/src/components/zustaendige-stelle/zustaendige-stelle-dialog.e2e.component.ts b/alfa-client/apps/admin-e2e/src/components/zustaendige-stelle/zustaendige-stelle-dialog.e2e.component.ts
index 337cad0fe51c3ba1e7bf0b1123e8f324c57dbc73..6bd293d6fc2c39febbea6bfef0fb4e66de7e22b6 100644
--- a/alfa-client/apps/admin-e2e/src/components/zustaendige-stelle/zustaendige-stelle-dialog.e2e.component.ts
+++ b/alfa-client/apps/admin-e2e/src/components/zustaendige-stelle/zustaendige-stelle-dialog.e2e.component.ts
@@ -1,5 +1,3 @@
-import { typeText } from '../../support/cypress.util';
-
 export class ZustaendigeStelleDialogE2EComponent {
   private readonly locatorZustaendigeStelleForm: string = 'search-organisations-einheit';
   private readonly locatorSearchInput: string = 'instant_search-text-input';
@@ -15,7 +13,7 @@ export class ZustaendigeStelleDialogE2EComponent {
   }
 
   public enterSearchTerm(searchTerm: string): void {
-    typeText(this.getSearchInput(), searchTerm);
+    this.getSearchInput().type(searchTerm);
   }
 
   public countSearchEntries(): Cypress.Chainable<number> {
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts
index faa2082e1c7e0fe5d47730d7682cd4d4e5fd11ae..9c1ff6974d5b21497c2529e3babae686b28f6f10 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/benutzer_rollen/benutzer_rollen.cy.ts
@@ -21,23 +21,10 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import {
-  BenutzerE2EComponent,
-  BenutzerListE2EComponent,
-  BenutzerListItemE2EComponent,
-} from 'apps/admin-e2e/src/components/benutzer/benutzer.e2e.component';
+import { BenutzerE2EComponent, BenutzerListE2EComponent, BenutzerListItemE2EComponent, } from 'apps/admin-e2e/src/components/benutzer/benutzer.e2e.component';
 import { E2EBenutzerHelper } from 'apps/admin-e2e/src/helper/benutzer/benutzer.helper';
 import { OrganisationsEinheitE2E } from 'apps/admin-e2e/src/model/organisations-einheit';
-import {
-  beChecked,
-  beEnabled,
-  contains,
-  exist,
-  mouseEnter,
-  notBeChecked,
-  notBeEnabled,
-  visible,
-} from 'apps/admin-e2e/src/support/cypress.util';
+import { beChecked, beEnabled, contains, exist, mouseEnter, notBeChecked, notBeEnabled, visible, } from 'apps/admin-e2e/src/support/cypress.util';
 import { AlfaRollen, AlfaUsers, loginAsAriane } from 'apps/admin-e2e/src/support/user-util';
 
 describe('Benutzer und Rollen', () => {
@@ -56,7 +43,7 @@ describe('Benutzer und Rollen', () => {
   it('should show users and attributes in list', () => {
     helper.openBenutzerListPage();
 
-    const ariane: BenutzerListItemE2EComponent = benutzerListPage.getItem(AlfaUsers.ARAINE);
+    const ariane: BenutzerListItemE2EComponent = benutzerListPage.getItem(AlfaUsers.ARIANE);
     exist(ariane.getRoot());
     contains(ariane.getRoles(), AlfaRollen.USER);
 
@@ -85,25 +72,21 @@ describe('Benutzer und Rollen', () => {
     exist(richard.getNoOrganisationsEinheitText());
   });
 
-  it('should show single user screen on click', () => {
+  it('should show checkbox for each role', () => {
     helper.openNewBenutzerPage();
 
-    exist(benutzerPage.getVornameInput());
-    exist(benutzerPage.getNachnameInput());
-    exist(benutzerPage.getBenutzernameInput());
-    exist(benutzerPage.getMailInput());
-
-    notBeChecked(benutzerPage.getAdminCheckbox().getRoot());
-    notBeChecked(benutzerPage.getLoeschenCheckbox().getRoot());
-    notBeChecked(benutzerPage.getUserCheckbox().getRoot());
-    notBeChecked(benutzerPage.getPostCheckbox().getRoot());
+    notBeChecked(benutzerPage.getAdminCheckbox());
+    notBeChecked(benutzerPage.getDatenbeauftragungCheckbox());
+    notBeChecked(benutzerPage.getLoeschenCheckbox());
+    notBeChecked(benutzerPage.getUserCheckbox());
+    notBeChecked(benutzerPage.getPostCheckbox());
   });
 
-  it('should activate loeschen checkbox and deactivate the other two checkboxes', () => {
-    benutzerPage.getLoeschenCheckbox().getRoot().click();
-    beChecked(benutzerPage.getLoeschenCheckbox().getRoot());
-    notBeEnabled(benutzerPage.getUserCheckbox().getRoot());
-    notBeEnabled(benutzerPage.getPostCheckbox().getRoot());
+  it('should deactivate other alfa roles if "loeschen" role is selected', () => {
+    benutzerPage.getLoeschenCheckbox().click();
+    beChecked(benutzerPage.getLoeschenCheckbox());
+    notBeEnabled(benutzerPage.getUserCheckbox());
+    notBeEnabled(benutzerPage.getPostCheckbox());
 
     benutzerPage.getLoeschenCheckbox().getRoot().click();
     notBeChecked(benutzerPage.getLoeschenCheckbox().getRoot());
@@ -111,39 +94,40 @@ describe('Benutzer und Rollen', () => {
     beEnabled(benutzerPage.getPostCheckbox().getRoot());
   });
 
-  it('should additionally activate and deactivate admin checkbox', () => {
-    benutzerPage.getLoeschenCheckbox().getRoot().click();
-    benutzerPage.getAdminCheckbox().getRoot().click();
-    beChecked(benutzerPage.getLoeschenCheckbox().getRoot());
-    beChecked(benutzerPage.getAdminCheckbox().getRoot());
+  it('should deactivate other alfa roles if "user" role is selected', () => {
+    benutzerPage.getUserCheckbox().click();
+    beChecked(benutzerPage.getUserCheckbox());
+    notBeEnabled(benutzerPage.getLoeschenCheckbox());
+    notBeEnabled(benutzerPage.getPostCheckbox());
 
-    benutzerPage.getAdminCheckbox().getRoot().click();
-    notBeChecked(benutzerPage.getAdminCheckbox().getRoot());
+    benutzerPage.getUserCheckbox().click();
+    notBeChecked(benutzerPage.getUserCheckbox());
+    beEnabled(benutzerPage.getLoeschenCheckbox());
+    beEnabled(benutzerPage.getPostCheckbox());
   });
 
-  it('should activate user checkbox and deactivate the other two checkboxes', () => {
-    benutzerPage.getLoeschenCheckbox().getRoot().click();
-    benutzerPage.getUserCheckbox().getRoot().click();
-    beChecked(benutzerPage.getUserCheckbox().getRoot());
-    notBeEnabled(benutzerPage.getLoeschenCheckbox().getRoot());
-    notBeEnabled(benutzerPage.getPostCheckbox().getRoot());
-
-    benutzerPage.getUserCheckbox().getRoot().click();
-    notBeChecked(benutzerPage.getUserCheckbox().getRoot());
-    beEnabled(benutzerPage.getLoeschenCheckbox().getRoot());
-    beEnabled(benutzerPage.getPostCheckbox().getRoot());
+  it('should deactivate other alfa roles if "poststelle" role is selected', () => {
+    benutzerPage.getPostCheckbox().click();
+    beChecked(benutzerPage.getPostCheckbox());
+    notBeEnabled(benutzerPage.getLoeschenCheckbox());
+    notBeEnabled(benutzerPage.getUserCheckbox());
+
+    benutzerPage.getPostCheckbox().click();
+    notBeChecked(benutzerPage.getPostCheckbox());
+    beEnabled(benutzerPage.getLoeschenCheckbox());
+    beEnabled(benutzerPage.getUserCheckbox());
   });
 
-  it('should activate post checkbox and deactivate the other two checkboxes', () => {
-    benutzerPage.getPostCheckbox().getRoot().click();
-    beChecked(benutzerPage.getPostCheckbox().getRoot());
-    notBeEnabled(benutzerPage.getLoeschenCheckbox().getRoot());
-    notBeEnabled(benutzerPage.getUserCheckbox().getRoot());
+  it('should activate and deactivate admin roles', () => {
+    benutzerPage.getAdminCheckbox().click();
+    benutzerPage.getDatenbeauftragungCheckbox().click();
+    beChecked(benutzerPage.getAdminCheckbox());
+    beChecked(benutzerPage.getDatenbeauftragungCheckbox());
 
-    benutzerPage.getPostCheckbox().getRoot().click();
-    notBeChecked(benutzerPage.getPostCheckbox().getRoot());
-    beEnabled(benutzerPage.getLoeschenCheckbox().getRoot());
-    beEnabled(benutzerPage.getUserCheckbox().getRoot());
+    benutzerPage.getAdminCheckbox().click();
+    benutzerPage.getDatenbeauftragungCheckbox().click();
+    notBeChecked(benutzerPage.getAdminCheckbox());
+    notBeChecked(benutzerPage.getDatenbeauftragungCheckbox());
   });
 
   describe('hint text', () => {
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/ariane.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/ariane.cy.ts
index 80987765996348c4f24f3105abc2328713ef4371..64218bf8c50d791ca4f221c518a454cc54df37fe 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/ariane.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/ariane.cy.ts
@@ -1,29 +1,33 @@
-import { MainPage, waitForSpinnerToDisappear } from 'apps/admin-e2e/src/page-objects/main.po';
-import { exist, notExist } from 'apps/admin-e2e/src/support/cypress.util';
+import { MainPage } from 'apps/admin-e2e/src/page-objects/main.po';
+import { containClass, exist, notExist } from 'apps/admin-e2e/src/support/cypress.util';
 import { loginAsAriane } from 'apps/admin-e2e/src/support/user-util';
 
-describe('Navigation', () => {
+describe('Ariane Navigation', () => {
   const mainPage: MainPage = new MainPage();
 
   describe('with user ariane', () => {
     before(() => {
       loginAsAriane();
-
-      waitForSpinnerToDisappear();
     });
 
     it('should show benutzer navigation item', () => {
       exist(mainPage.getBenutzerNavigationItem());
     });
 
-    it('should show postfach navigation item', () => {
-      exist(mainPage.getPostfachNavigationItem());
-    });
-
     it('should show organisationseinheiten navigation item', () => {
       exist(mainPage.getOrganisationEinheitNavigationItem());
     });
 
+    describe('postfach navigation item', () => {
+      it('should be visible', () => {
+        exist(mainPage.getPostfachNavigationItem());
+      });
+
+      it('should be selected initial', () => {
+        containClass(mainPage.getPostfachNavigationItem(), 'border-selected');
+      });
+    });
+
     it('should hide statistik navigation item', () => {
       notExist(mainPage.getStatistikNavigationItem());
     });
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/daria.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/daria.cy.ts
index 33a06a73b83c3a839b0490f96aa17ddb42106994..4fda0a2dee6bfb74ad354a08e46f27ced5e15bc6 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/daria.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/daria.cy.ts
@@ -1,43 +1,34 @@
-import { MainPage, waitForSpinnerToDisappear } from 'apps/admin-e2e/src/page-objects/main.po';
-import { exist, notExist, visible } from 'apps/admin-e2e/src/support/cypress.util';
+import { MainPage } from 'apps/admin-e2e/src/page-objects/main.po';
+import { containClass, exist, notExist } from 'apps/admin-e2e/src/support/cypress.util';
 import { loginAsDaria } from 'apps/admin-e2e/src/support/user-util';
-import { StatistikE2EComponent } from '../../../components/statistik/statistik.e2e.component';
 
-describe('Navigation', () => {
+describe('Daria Navigation', () => {
   const mainPage: MainPage = new MainPage();
 
-  const statistikPage: StatistikE2EComponent = new StatistikE2EComponent();
-
   describe('with user daria', () => {
     before(() => {
       loginAsDaria();
-
-      waitForSpinnerToDisappear();
     });
 
-    it('should hide other navigation item', () => {
+    it('should hide benutzer navigation item', () => {
       notExist(mainPage.getBenutzerNavigationItem());
     });
 
-    it('should hide postfach navigation item', () => {
-      notExist(mainPage.getPostfachNavigationItem());
-    });
-
     it('should hide organisationseinheiten navigation item', () => {
       notExist(mainPage.getOrganisationEinheitNavigationItem());
     });
 
-    describe('statistik', () => {
+    it('should hide postfach navigation item', () => {
+      notExist(mainPage.getPostfachNavigationItem());
+    });
+
+    describe('statistik navigation item', () => {
       it('should be visible', () => {
         exist(mainPage.getStatistikNavigationItem());
       });
 
       it('should be initial selected', () => {
-        mainPage.isStatistikNavigationItemSelected();
-      });
-
-      it('should show header text', () => {
-        visible(statistikPage.getHeaderText());
+        containClass(mainPage.getStatistikNavigationItem(), 'border-selected');
       });
     });
   });
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/safira.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/safira.cy.ts
index 005da2e5a576948787fdeb1f26165bd250b22138..ae328f579e493b6c493a687da703269120bebbd5 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/safira.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/navigation/safira.cy.ts
@@ -1,50 +1,35 @@
-import { MainPage, waitForSpinnerToDisappear } from 'apps/admin-e2e/src/page-objects/main.po';
-import { exist, visible } from 'apps/admin-e2e/src/support/cypress.util';
+import { MainPage } from 'apps/admin-e2e/src/page-objects/main.po';
+import { containClass, exist } from 'apps/admin-e2e/src/support/cypress.util';
 import { loginAsSafira } from 'apps/admin-e2e/src/support/user-util';
-import { StatistikE2EComponent } from '../../../components/statistik/statistik.e2e.component';
 
-describe('Navigation', () => {
+describe('Safira Navigation', () => {
   const mainPage: MainPage = new MainPage();
 
-  const statistikPage: StatistikE2EComponent = new StatistikE2EComponent();
-
   describe('with user safira', () => {
     before(() => {
       loginAsSafira();
-
-      waitForSpinnerToDisappear();
     });
 
     it('should show benutzer navigation item', () => {
       exist(mainPage.getBenutzerNavigationItem());
     });
 
-    it('should show postfach navigation item', () => {
-      exist(mainPage.getPostfachNavigationItem());
-    });
-
     it('should show organisationseinheiten navigation item', () => {
       exist(mainPage.getOrganisationEinheitNavigationItem());
     });
 
-    describe('statistik', () => {
+    describe('postfach navigation item', () => {
       it('should be visible', () => {
-        exist(mainPage.getStatistikNavigationItem());
+        exist(mainPage.getPostfachNavigationItem());
       });
 
-      describe('on selection', () => {
-        before(() => {
-          mainPage.clickStatistikNavigationItem();
-        });
-
-        it('should show page on selection', () => {
-          visible(statistikPage.getHeaderText());
-        });
-
-        it('should mark navigation item as selected', () => {
-          mainPage.isStatistikNavigationItemSelected();
-        });
+      it('should be selected initial', () => {
+        containClass(mainPage.getPostfachNavigationItem(), 'border-selected');
       });
     });
+
+    it('should show statistik navigation item', () => {
+      exist(mainPage.getStatistikNavigationItem());
+    });
   });
 });
diff --git a/alfa-client/apps/admin-e2e/src/e2e/main-tests/postfach/postfach-signatur.cy.ts b/alfa-client/apps/admin-e2e/src/e2e/main-tests/postfach/postfach-signatur.cy.ts
index 1a8b4a69f8b1f19d1c2daf27b65274f46fea62e0..779a88f3c46a4724f9d188768e7344e9b992cf1d 100644
--- a/alfa-client/apps/admin-e2e/src/e2e/main-tests/postfach/postfach-signatur.cy.ts
+++ b/alfa-client/apps/admin-e2e/src/e2e/main-tests/postfach/postfach-signatur.cy.ts
@@ -21,12 +21,12 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { E2EPostfachHelper } from 'apps/admin-e2e/src/helper/postfach/postfach.helper';
 import { PostfachE2EComponent } from '../../../components/postfach/postfach.e2e.component';
-import { waitForSpinnerToDisappear } from '../../../page-objects/main.po';
-import { exist } from '../../../support/cypress.util';
 import { loginAsAriane } from '../../../support/user-util';
 
-describe('Signatur', () => {
+describe('(TODO: Ist noch wackelig in Bezug auf die Eingabe in das Feld) Postfach Signatur', () => {
+  const postfachHelper: E2EPostfachHelper = new E2EPostfachHelper();
   const postfach: PostfachE2EComponent = new PostfachE2EComponent();
 
   const signaturText: string = 'Signatur\nmit\n\n\n\nZeilenumbruch\n\n';
@@ -35,12 +35,9 @@ describe('Signatur', () => {
     loginAsAriane();
   });
 
-  it('should show Postfach page', () => {
-    waitForSpinnerToDisappear();
-    exist(postfach.getSignaturText());
-  });
-
   it('should show signature input with scrollbar', () => {
+    postfachHelper.openPostfachPage();
+
     postfach.setSignatur(signaturText);
     postfach.saveSignatur();
 
diff --git a/alfa-client/apps/admin-e2e/src/helper/postfach/postfach.helper.ts b/alfa-client/apps/admin-e2e/src/helper/postfach/postfach.helper.ts
new file mode 100644
index 0000000000000000000000000000000000000000..90624b0151bdae26e5e1859734132d6b2e24cf62
--- /dev/null
+++ b/alfa-client/apps/admin-e2e/src/helper/postfach/postfach.helper.ts
@@ -0,0 +1,9 @@
+import { E2EPostfachNavigator } from './postfach.navigator';
+
+export class E2EPostfachHelper {
+  private readonly navigator: E2EPostfachNavigator = new E2EPostfachNavigator();
+
+  public openPostfachPage(): void {
+    this.navigator.openPostfachPage();
+  }
+}
diff --git a/alfa-client/apps/admin-e2e/src/helper/postfach/postfach.navigator.ts b/alfa-client/apps/admin-e2e/src/helper/postfach/postfach.navigator.ts
new file mode 100644
index 0000000000000000000000000000000000000000..074438baaaf22cc22669f085412ddd5d2f22046d
--- /dev/null
+++ b/alfa-client/apps/admin-e2e/src/helper/postfach/postfach.navigator.ts
@@ -0,0 +1,18 @@
+import { PostfachE2EComponent } from '../../components/postfach/postfach.e2e.component';
+import { MainPage } from '../../page-objects/main.po';
+import { exist } from '../../support/cypress.util';
+
+export class E2EPostfachNavigator {
+  private mainPage: MainPage = new MainPage();
+  private postfach: PostfachE2EComponent = new PostfachE2EComponent();
+
+  public openPostfachPage(): void {
+    this.navigateToDomain();
+    this.mainPage.getPostfachNavigationItem().click();
+    exist(this.postfach.getHeadline());
+  }
+
+  private navigateToDomain(): void {
+    this.mainPage.getHeader().getLogo().click();
+  }
+}
diff --git a/alfa-client/apps/admin-e2e/src/model/util.ts b/alfa-client/apps/admin-e2e/src/model/util.ts
index 03041ea28be5dae394e7df97d6bf38ae72d2a182..7ad5cd61ab1741c43e02532c38b711c92eb9c8dc 100644
--- a/alfa-client/apps/admin-e2e/src/model/util.ts
+++ b/alfa-client/apps/admin-e2e/src/model/util.ts
@@ -46,6 +46,7 @@ export interface AdminUserE2E {
   username: string;
   email: string;
   isAdmin?: boolean;
+  isDatenbeauftragung?: boolean;
   isUser?: boolean;
   isLoeschen?: boolean;
   isPoststelle?: boolean;
diff --git a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
index 338c98286a6f1fc02e97d52381b99de0dbfc3db6..75ecbdaefa5d692ca637af325afb58ec05f80abe 100644
--- a/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
+++ b/alfa-client/apps/admin-e2e/src/page-objects/main.po.ts
@@ -22,17 +22,16 @@
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
 import { BuildInfoE2EComponent } from '../components/buildinfo/buildinfo.e2e.component';
-import { containClass, exist } from '../support/cypress.util';
 import { HeaderE2EComponent } from './header.po';
 
 export class MainPage {
   private readonly buildInfo: BuildInfoE2EComponent = new BuildInfoE2EComponent();
   private readonly header: HeaderE2EComponent = new HeaderE2EComponent();
 
-  private readonly benutzerNavigationItem: string = 'caption-Benutzer__Rollen';
-  private readonly postfachNavigationItem: string = 'postfach-navigation';
-  private readonly organisationEinheitNavigationItem: string = 'organisations-einheiten-navigation';
-  private readonly statistikNavigationItem: string = 'statistik-navigation';
+  private readonly benutzerNavigationItem: string = 'link-path-benutzer';
+  private readonly organisationEinheitNavigationItem: string = 'link-path-organisationseinheiten';
+  private readonly postfachNavigationItem: string = 'link-path-postfach';
+  private readonly statistikNavigationItem: string = 'link-path-statistik';
 
   public getBuildInfo(): BuildInfoE2EComponent {
     return this.buildInfo;
@@ -46,41 +45,17 @@ export class MainPage {
     return cy.getTestElement(this.benutzerNavigationItem);
   }
 
-  public clickBenutzerNavigationItem(): void {
-    this.getBenutzerNavigationItem().click();
-  }
-
-  public benutzerNavigationItemIsVisible(): void {
-    exist(this.getBenutzerNavigationItem());
-  }
-
   public getPostfachNavigationItem(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.postfachNavigationItem);
   }
 
-  public clickPostfachNavigationItem(): void {
-    this.getPostfachNavigationItem().click();
-  }
-
   public getOrganisationEinheitNavigationItem(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.organisationEinheitNavigationItem);
   }
 
-  public clickOrganisationsEinheitenNavigationItem(): void {
-    this.getOrganisationEinheitNavigationItem().click();
-  }
-
   public getStatistikNavigationItem(): Cypress.Chainable<Element> {
     return cy.getTestElement(this.statistikNavigationItem);
   }
-
-  public clickStatistikNavigationItem(): void {
-    this.getStatistikNavigationItem().click();
-  }
-
-  public isStatistikNavigationItemSelected(): void {
-    containClass(this.getStatistikNavigationItem().get('a'), 'border-selected');
-  }
 }
 
 export function waitForSpinnerToDisappear(): boolean {
diff --git a/alfa-client/apps/admin-e2e/src/support/cypress.util.ts b/alfa-client/apps/admin-e2e/src/support/cypress.util.ts
index d18cc34fbfe2cedb9d21aae60b730283b96e9392..63f3c24872ebea08644aa85eead331dac07f1b40 100644
--- a/alfa-client/apps/admin-e2e/src/support/cypress.util.ts
+++ b/alfa-client/apps/admin-e2e/src/support/cypress.util.ts
@@ -124,10 +124,6 @@ export function enterWith(element: Cypress.Chainable<Element>, value: string, de
   element.type(CypressKeyboardActions.ENTER);
 }
 
-export function typeText(element: Cypress.Chainable<Element>, value: string): void {
-  element.type(value);
-}
-
 export function backspaceOn(element: Cypress.Chainable<Element>): void {
   element.type(CypressKeyboardActions.BACKSPACE);
 }
diff --git a/alfa-client/apps/admin-e2e/src/support/user-util.ts b/alfa-client/apps/admin-e2e/src/support/user-util.ts
index d5e7462638087a82b1e4d365e0a59e11932962e5..989e061babc526985e62ace05e516bdb2d058516 100644
--- a/alfa-client/apps/admin-e2e/src/support/user-util.ts
+++ b/alfa-client/apps/admin-e2e/src/support/user-util.ts
@@ -89,10 +89,12 @@ export enum AlfaRollen {
   LOESCHEN = 'VERWALTUNG_LOESCHEN',
   POSTSTELLE = 'VERWALTUNG_POSTSTELLE',
   ADMIN = 'ADMIN_ADMIN',
+  DATEN = 'DATENBEAUFTRAGUNG',
 }
 
 export enum AlfaUsers {
-  ARAINE = 'ariane',
+  ARIANE = 'ariane',
+  DARIA = 'daria',
   DOROTHEA = 'dorothea',
   LUDWIG = 'ludwig',
   PETER = 'peter',
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 b0a354caa1b666ad9ad15a4527e77f8a632496c6..baa8c7fcc532a0e859fe596782a94bf7b2257803 100644
--- a/alfa-client/apps/admin/src/app/app.component.spec.ts
+++ b/alfa-client/apps/admin/src/app/app.component.spec.ts
@@ -55,29 +55,31 @@ describe('AppComponent', () => {
   const routerOutletSelector: string = getDataTestIdOf('router-outlet');
   const menuContainer: string = getDataTestIdOf('menu-container');
 
-  const authenticationService: Mock<AuthenticationService> = {
-    ...mock(AuthenticationService),
-    login: jest.fn().mockResolvedValue(Promise.resolve()),
-  };
-
-  const router: Mock<Router> = mock(Router);
-  const route: Mock<ActivatedRoute> = {
-    ...mock(ActivatedRoute),
-    snapshot: {
-      queryParams: {
-        iss: 'some-iss',
-        state: 'some-state',
-        session_state: 'some-session-state',
-        code: 'some-code',
-      },
-    } as any,
-  };
-
-  const apiRootService: Mock<ApiRootService> = mock(ApiRootService);
+  let authenticationService: Mock<AuthenticationService>;
+  let router: Mock<Router>;
+  let route: Mock<ActivatedRoute>;
+  let apiRootService: Mock<ApiRootService>;
   let configurationService: Mock<ConfigurationService>;
   let keycloakTokenService: Mock<KeycloakTokenService>;
 
   beforeEach(async () => {
+    authenticationService = {
+      ...mock(AuthenticationService),
+      login: jest.fn().mockResolvedValue(Promise.resolve()),
+    };
+    router = mock(Router);
+    route = {
+      ...mock(ActivatedRoute),
+      snapshot: {
+        queryParams: {
+          iss: 'some-iss',
+          state: 'some-state',
+          session_state: 'some-session-state',
+          code: 'some-code',
+        },
+      } as any,
+    };
+    apiRootService = mock(ApiRootService);
     configurationService = mock(ConfigurationService);
     keycloakTokenService = mock(KeycloakTokenService);
 
@@ -145,81 +147,110 @@ describe('AppComponent', () => {
         expect(authenticationService.login).toHaveBeenCalled();
       });
 
-      it('should call doAfterLoggedIn', async () => {
-        component.doAfterLoggedIn = jest.fn();
+      it('should call doAfterLoggedIn only once', async () => {
+        component._doAfterLoggedIn = jest.fn();
 
         component.ngOnInit();
         await fixture.whenStable();
 
-        expect(component.doAfterLoggedIn).toHaveBeenCalled();
+        expect(component._doAfterLoggedIn).toHaveBeenCalledTimes(1);
       });
     });
 
     describe('do after logged in', () => {
       beforeEach(() => {
-        component.evaluateInitialNavigation = jest.fn();
+        component._evaluateInitialNavigation = jest.fn();
       });
 
       it('should call apiRootService to getApiRoot', () => {
-        component.doAfterLoggedIn();
+        component._doAfterLoggedIn();
 
         expect(apiRootService.getApiRoot).toHaveBeenCalled();
       });
 
       it('should call keycloak token service to register token provider', () => {
-        component.doAfterLoggedIn();
+        component._doAfterLoggedIn();
 
         expect(keycloakTokenService.registerAccessTokenProvider).toHaveBeenCalled();
       });
 
       it('should call evaluateInitialNavigation', () => {
-        component.doAfterLoggedIn();
+        component._doAfterLoggedIn();
 
-        expect(component.evaluateInitialNavigation).toHaveBeenCalled();
+        expect(component._evaluateInitialNavigation).toHaveBeenCalled();
       });
     });
 
     describe('evaluate initial navigation', () => {
       beforeEach(() => {
-        component.evaluateNavigationByApiRoot = jest.fn();
+        component._evaluateNavigationByApiRoot = jest.fn();
+        component._subscribeApiRootForEvaluation = jest.fn();
       });
 
-      it('should call evaluate navigation by apiRoot', () => {
-        const apiRootResource: ApiRootResource = createApiRootResource();
+      it('should call router navigate', () => {
+        window.location.pathname = '/path';
+        (router as any).url = '/path';
+
+        component._evaluateInitialNavigation();
+
+        expect(router.navigate).toHaveBeenCalledWith([window.location.pathname]);
+      });
+
+      it('should call subscribe api root evaluation if url starts with /?state', () => {
+        (router as any).url = '/?state=some-state';
+
+        component._evaluateInitialNavigation();
+
+        expect(component._subscribeApiRootForEvaluation).toHaveBeenCalled();
+      });
+    });
+
+    describe('subscribeApiRootForEvaluation', () => {
+      const apiRootResource: ApiRootResource = createApiRootResource();
+
+      beforeEach(() => {
         component.apiRootStateResource$ = of(createStateResource(apiRootResource));
+        component._evaluateNavigationByApiRoot = jest.fn();
+      });
 
-        component.evaluateInitialNavigation();
+      it('should set apiRootSubscription', () => {
+        component._subscribeApiRootForEvaluation();
+
+        expect(component.apiRootSubscription).toBeDefined();
+      });
+
+      it('should call evaluate navigation by apiRoot', () => {
+        component._subscribeApiRootForEvaluation();
 
-        expect(component.evaluateNavigationByApiRoot).toHaveBeenCalledWith(apiRootResource);
+        expect(component._evaluateNavigationByApiRoot).toHaveBeenCalledWith(apiRootResource);
       });
 
       it('should NOT call evaluate navigation by apiRoot if resource is loading', () => {
-        component.apiRootStateResource$ = of(createEmptyStateResource<ApiRootResource>(true));
-        component.evaluateNavigationByApiRoot = jest.fn();
+        component.apiRootStateResource$ = of(createStateResource(apiRootResource, true));
 
-        component.evaluateInitialNavigation();
+        component._subscribeApiRootForEvaluation();
 
-        expect(component.evaluateNavigationByApiRoot).not.toHaveBeenCalled();
+        expect(component._evaluateNavigationByApiRoot).not.toHaveBeenCalled();
       });
     });
 
     describe('evaluate navigation api root', () => {
       it('should evaluate navigation by configuration if link exists', () => {
-        component.evaluateNavigationByConfiguration = jest.fn();
+        component._evaluateNavigationByConfiguration = jest.fn();
         const apiRootResource: ApiRootResource = createApiRootResource([ApiRootLinkRel.CONFIGURATION]);
 
-        component.evaluateNavigationByApiRoot(apiRootResource);
+        component._evaluateNavigationByApiRoot(apiRootResource);
 
-        expect(component.evaluateNavigationByConfiguration).toHaveBeenCalled();
+        expect(component._evaluateNavigationByConfiguration).toHaveBeenCalled();
       });
 
       it('should navigate by api root if link is missing', () => {
-        component.navigateByApiRoot = jest.fn();
+        component._navigateByApiRoot = jest.fn();
         const apiRootResource: ApiRootResource = createApiRootResource();
 
-        component.evaluateNavigationByApiRoot(apiRootResource);
+        component._evaluateNavigationByApiRoot(apiRootResource);
 
-        expect(component.navigateByApiRoot).toHaveBeenCalledWith(apiRootResource);
+        expect(component._navigateByApiRoot).toHaveBeenCalledWith(apiRootResource);
       });
     });
 
@@ -228,83 +259,83 @@ describe('AppComponent', () => {
 
       beforeEach(() => {
         configurationService.get.mockReturnValue(of(createStateResource(configurationResource)));
-        component.navigateByConfiguration = jest.fn();
+        component._navigateByConfiguration = jest.fn();
       });
 
       it('should call configuration service to get resource', () => {
-        component.evaluateNavigationByConfiguration();
+        component._evaluateNavigationByConfiguration();
 
         expect(configurationService.get).toHaveBeenCalled();
       });
 
       it('should call navigate by configuration', () => {
-        component.evaluateNavigationByConfiguration();
+        component._evaluateNavigationByConfiguration();
 
-        expect(component.navigateByConfiguration).toHaveBeenCalledWith(configurationResource);
+        expect(component._navigateByConfiguration).toHaveBeenCalledWith(configurationResource);
       });
 
       it('should NOT call navigate by configuration if resource is loading', () => {
         configurationService.get.mockReturnValue(of(createEmptyStateResource<ConfigurationResource>(true)));
 
-        component.evaluateNavigationByConfiguration();
+        component._evaluateNavigationByConfiguration();
 
-        expect(component.navigateByConfiguration).not.toHaveBeenCalled();
+        expect(component._navigateByConfiguration).not.toHaveBeenCalled();
       });
     });
 
     describe('navigate by configuration', () => {
       beforeEach(() => {
-        component.unsubscribe = jest.fn();
+        component._unsubscribe = jest.fn();
       });
 
       it('should navigate to postfach if settings link exists', () => {
-        component.navigateByConfiguration(createConfigurationResource([ConfigurationLinkRel.SETTING]));
+        component._navigateByConfiguration(createConfigurationResource([ConfigurationLinkRel.SETTING]));
 
         expect(router.navigate).toHaveBeenCalledWith(['/postfach']);
       });
 
       it('should navigate to statistik if aggregation mapping link exists', () => {
-        component.navigateByConfiguration(createConfigurationResource([ConfigurationLinkRel.AGGREGATION_MAPPINGS]));
+        component._navigateByConfiguration(createConfigurationResource([ConfigurationLinkRel.AGGREGATION_MAPPINGS]));
 
         expect(router.navigate).toHaveBeenCalledWith(['/statistik']);
       });
 
       it('should navigate to unavailable page if no link exists', () => {
-        component.navigateByConfiguration(createConfigurationResource());
+        component._navigateByConfiguration(createConfigurationResource());
 
         expect(router.navigate).toHaveBeenCalledWith(['/unavailable']);
       });
 
       it('should call unsubscribe', () => {
-        component.navigateByConfiguration(createConfigurationResource());
+        component._navigateByConfiguration(createConfigurationResource());
 
-        expect(component.unsubscribe).toHaveBeenCalled();
+        expect(component._unsubscribe).toHaveBeenCalled();
       });
     });
 
     describe('navigate by api root', () => {
       beforeEach(() => {
-        component.unsubscribe = jest.fn();
+        component._unsubscribe = jest.fn();
       });
 
       it('should navigate to benutzer und rollen if users link exists', () => {
         const apiRootResource: ApiRootResource = createApiRootResource([ApiRootLinkRel.USERS]);
 
-        component.navigateByApiRoot(apiRootResource);
+        component._navigateByApiRoot(apiRootResource);
 
         expect(router.navigate).toHaveBeenCalledWith([`/${ROUTES.BENUTZER}`]);
       });
 
       it('should navigate to unavailable page if no link exists', () => {
-        component.navigateByApiRoot(createApiRootResource());
+        component._navigateByApiRoot(createApiRootResource());
 
         expect(router.navigate).toHaveBeenCalledWith([`/${ROUTES.UNAVAILABLE}`]);
       });
 
       it('should call unsubscribe', () => {
-        component.navigateByApiRoot(createApiRootResource());
+        component._navigateByApiRoot(createApiRootResource());
 
-        expect(component.unsubscribe).toHaveBeenCalled();
+        expect(component._unsubscribe).toHaveBeenCalled();
       });
     });
 
@@ -314,7 +345,7 @@ describe('AppComponent', () => {
           component.apiRootSubscription = <any>mock(Subscription);
           component.apiRootSubscription.unsubscribe = jest.fn();
 
-          component.unsubscribe();
+          component._unsubscribe();
 
           expect(component.apiRootSubscription.unsubscribe).toHaveBeenCalled();
         });
@@ -323,7 +354,7 @@ describe('AppComponent', () => {
           component.apiRootSubscription = undefined;
           const unsubscribeSpy: jest.SpyInstance = jest.spyOn(Subscription.prototype, 'unsubscribe');
 
-          component.unsubscribe();
+          component._unsubscribe();
 
           expect(unsubscribeSpy).not.toHaveBeenCalled();
           unsubscribeSpy.mockRestore();
@@ -335,7 +366,7 @@ describe('AppComponent', () => {
           component.configurationSubscription = <any>mock(Subscription);
           component.configurationSubscription.unsubscribe = jest.fn();
 
-          component.unsubscribe();
+          component._unsubscribe();
 
           expect(component.configurationSubscription.unsubscribe).toHaveBeenCalled();
         });
@@ -344,7 +375,7 @@ describe('AppComponent', () => {
           component.apiRootSubscription = undefined;
           const unsubscribeSpy: jest.SpyInstance = jest.spyOn(Subscription.prototype, 'unsubscribe');
 
-          component.unsubscribe();
+          component._unsubscribe();
 
           expect(unsubscribeSpy).not.toHaveBeenCalled();
           unsubscribeSpy.mockRestore();
diff --git a/alfa-client/apps/admin/src/app/app.component.ts b/alfa-client/apps/admin/src/app/app.component.ts
index bb5f2013fde365c95ae01525f1b8cb170decddd6..909b6cd198bd3ccb91dd61e922abb6a1ed79210c 100644
--- a/alfa-client/apps/admin/src/app/app.component.ts
+++ b/alfa-client/apps/admin/src/app/app.component.ts
@@ -33,13 +33,7 @@ import { Component, inject, OnInit } from '@angular/core';
 import { Router, RouterLink, RouterOutlet } from '@angular/router';
 import { AuthenticationService } from '@authentication';
 import { hasLink } from '@ngxp/rest';
-import {
-  AdminLogoIconComponent,
-  NavbarComponent,
-  NavItemComponent,
-  OrgaUnitIconComponent,
-  UsersIconComponent,
-} from '@ods/system';
+import { AdminLogoIconComponent, NavbarComponent, NavItemComponent, OrgaUnitIconComponent, UsersIconComponent, } from '@ods/system';
 import { filter, Observable, Subscription } from 'rxjs';
 import { UserProfileButtonContainerComponent } from '../../../../libs/admin/user-profile/src/lib/user-menu/user-profile.button-container.component';
 import { UnavailablePageComponent } from '../pages/unavailable/unavailable-page/unavailable-page.component';
@@ -83,37 +77,49 @@ export class AppComponent implements OnInit {
   public readonly routes = ROUTES;
 
   ngOnInit(): void {
-    this.authenticationService.login().then(() => this.doAfterLoggedIn());
+    this.authenticationService.login().then(() => this._doAfterLoggedIn());
   }
 
-  doAfterLoggedIn(): void {
+  _doAfterLoggedIn(): void {
     this.apiRootStateResource$ = this.apiRootService.getApiRoot();
     this.keycloakTokenService.registerAccessTokenProvider();
-    this.evaluateInitialNavigation();
+    this._evaluateInitialNavigation();
   }
 
-  evaluateInitialNavigation(): void {
+  _evaluateInitialNavigation(): void {
+    if (this.router.url.startsWith('/?state')) {
+      this._subscribeApiRootForEvaluation();
+    } else {
+      this.refreshForGuardEvaluation();
+    }
+  }
+
+  _subscribeApiRootForEvaluation(): void {
     this.apiRootSubscription = this.apiRootStateResource$
       .pipe(filter(isLoaded), mapToResource<ApiRootResource>())
-      .subscribe((apiRootResource: ApiRootResource) => this.evaluateNavigationByApiRoot(apiRootResource));
+      .subscribe((apiRootResource: ApiRootResource) => this._evaluateNavigationByApiRoot(apiRootResource));
+  }
+
+  private refreshForGuardEvaluation(): void {
+    this.router.navigate([window.location.pathname]);
   }
 
-  evaluateNavigationByApiRoot(apiRootResource: ApiRootResource): void {
+  _evaluateNavigationByApiRoot(apiRootResource: ApiRootResource): void {
     if (hasLink(apiRootResource, ApiRootLinkRel.CONFIGURATION)) {
-      this.evaluateNavigationByConfiguration();
+      this._evaluateNavigationByConfiguration();
     } else {
-      this.navigateByApiRoot(apiRootResource);
+      this._navigateByApiRoot(apiRootResource);
     }
   }
 
-  evaluateNavigationByConfiguration(): void {
+  _evaluateNavigationByConfiguration(): void {
     this.configurationSubscription = this.configurationService
       .get()
       .pipe(filter(isLoaded), mapToResource<ApiRootResource>())
-      .subscribe((configurationResource: ConfigurationResource) => this.navigateByConfiguration(configurationResource));
+      .subscribe((configurationResource: ConfigurationResource) => this._navigateByConfiguration(configurationResource));
   }
 
-  navigateByConfiguration(configurationResource: ConfigurationResource): void {
+  _navigateByConfiguration(configurationResource: ConfigurationResource): void {
     if (hasLink(configurationResource, ConfigurationLinkRel.SETTING)) {
       this.navigate(ROUTES.POSTFACH);
     } else if (hasLink(configurationResource, ConfigurationLinkRel.AGGREGATION_MAPPINGS)) {
@@ -121,23 +127,23 @@ export class AppComponent implements OnInit {
     } else {
       this.navigate(ROUTES.UNAVAILABLE);
     }
-    this.unsubscribe();
+    this._unsubscribe();
   }
 
-  navigateByApiRoot(apiRootResource: ApiRootResource): void {
+  _navigateByApiRoot(apiRootResource: ApiRootResource): void {
     if (hasLink(apiRootResource, ApiRootLinkRel.USERS)) {
       this.navigate(ROUTES.BENUTZER);
     } else {
       this.navigate(ROUTES.UNAVAILABLE);
     }
-    this.unsubscribe();
+    this._unsubscribe();
   }
 
   private navigate(routePath: string): void {
     this.router.navigate(['/' + routePath]);
   }
 
-  unsubscribe(): void {
+  _unsubscribe(): void {
     if (isNotUndefined(this.apiRootSubscription)) this.apiRootSubscription.unsubscribe();
     if (isNotUndefined(this.configurationSubscription)) this.configurationSubscription.unsubscribe();
   }
diff --git a/alfa-client/apps/admin/src/app/app.guard.spec.ts b/alfa-client/apps/admin/src/app/app.guard.spec.ts
index 24e0a21eca4fb630c66112e19ba4b0024bf983a9..41cfe7506366e35bdd3d16d4f24d054c16eef40c 100644
--- a/alfa-client/apps/admin/src/app/app.guard.spec.ts
+++ b/alfa-client/apps/admin/src/app/app.guard.spec.ts
@@ -27,6 +27,7 @@ import { createStateResource, LinkRelationName, StateResource } from '@alfa-clie
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
 import { TestBed } from '@angular/core/testing';
 import { ActivatedRouteSnapshot, Router, UrlTree } from '@angular/router';
+import { AuthenticationService } from '@authentication';
 import { Resource } from '@ngxp/rest';
 import { createConfigurationResource } from 'libs/admin/configuration-shared/test/configuration';
 import { createApiRootResource } from 'libs/api-root-shared/test/api-root';
@@ -139,10 +140,49 @@ describe('Guard', () => {
     const resource: Resource = createDummyResource([DummyLinkRel.DUMMY]);
     const stateResource$: Observable<StateResource<Resource>> = of(createStateResource(resource));
 
+    let authService: Mock<AuthenticationService>;
+    let router: Mock<Router>;
+
+    beforeEach(() => {
+      authService = {
+        ...mock(AuthenticationService),
+        isLoggedIn: jest.fn().mockReturnValue(true),
+      };
+      router = mock(Router);
+
+      TestBed.configureTestingModule({
+        providers: [
+          {
+            provide: Router,
+            useValue: router,
+          },
+          {
+            provide: AuthenticationService,
+            useValue: authService,
+          },
+        ],
+      });
+    });
+
     afterEach(() => {
       jest.restoreAllMocks();
     });
 
+    it('should call authenticationService isLoggedIn', () => {
+      evaluate().subscribe();
+
+      expect(authService.isLoggedIn).toHaveBeenCalled();
+    });
+
+    it('should return observable true if not logged in', (done) => {
+      authService.isLoggedIn.mockReturnValue(false);
+
+      evaluate().subscribe((resolvedValue) => {
+        expect(resolvedValue).toEqual(true);
+        done();
+      });
+    });
+
     it('should evaluate resource', () => {
       const urlTreeMock: Mock<UrlTree> = mock(UrlTree);
       const evaluateResourceSpy: jest.SpyInstance = jest
@@ -151,7 +191,7 @@ describe('Guard', () => {
 
       evaluate().subscribe();
 
-      expect(evaluateResourceSpy).toHaveBeenCalledWith(resource, DummyLinkRel.DUMMY);
+      expect(evaluateResourceSpy).toHaveBeenCalledWith(resource, DummyLinkRel.DUMMY, router);
     });
 
     it('should return evaluated boolean', (done) => {
@@ -181,34 +221,23 @@ describe('Guard', () => {
   });
 
   describe('evaluate resource', () => {
-    let router: Mock<Router>;
-
-    beforeEach(() => {
-      router = mock(Router);
-
-      TestBed.configureTestingModule({
-        providers: [
-          {
-            provide: Router,
-            useValue: router,
-          },
-        ],
-      });
-    });
+    const router: Mock<Router> = mock(Router);
 
     afterEach(() => {
       jest.restoreAllMocks();
     });
 
     it('should return true if link exists', () => {
-      const result: boolean = <boolean>evaluateResource(createDummyResource([DummyLinkRel.DUMMY]));
+      const result: boolean = <boolean>(
+        Guard.evaluateResource(createDummyResource([DummyLinkRel.DUMMY]), DummyLinkRel.DUMMY, useFromMock(router))
+      );
 
       expect(result).toBeTruthy();
     });
 
     describe('if link not exists', () => {
       it('should call router', () => {
-        evaluateResource(createDummyResource());
+        Guard.evaluateResource(createDummyResource(), DummyLinkRel.DUMMY, useFromMock(router));
 
         expect(router.createUrlTree).toHaveBeenCalledWith(['/unavailable']);
       });
@@ -217,14 +246,10 @@ describe('Guard', () => {
         const urlTree: Mock<UrlTree> = mock(UrlTree);
         router.createUrlTree.mockReturnValue(urlTree);
 
-        const result: UrlTree = <UrlTree>evaluateResource(createDummyResource());
+        const result: UrlTree = <UrlTree>Guard.evaluateResource(createDummyResource(), DummyLinkRel.DUMMY, useFromMock(router));
 
         expect(result).toEqual(urlTree);
       });
     });
-
-    function evaluateResource(dummyResource: Resource): boolean | UrlTree {
-      return <boolean | UrlTree>TestBed.runInInjectionContext(() => Guard.evaluateResource(dummyResource, DummyLinkRel.DUMMY));
-    }
   });
 });
diff --git a/alfa-client/apps/admin/src/app/app.guard.ts b/alfa-client/apps/admin/src/app/app.guard.ts
index 85625be095c256aa593faa2d0d415352258aa1e0..c61df188c0c4ea38de5c66cfe69a55e39fc780ce 100644
--- a/alfa-client/apps/admin/src/app/app.guard.ts
+++ b/alfa-client/apps/admin/src/app/app.guard.ts
@@ -21,24 +21,25 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
+import { ConfigurationService } from '@admin-client/configuration-shared';
 import { ROUTES } from '@admin-client/shared';
 import { ApiRootService } from '@alfa-client/api-root-shared';
 import { LinkRelationName, mapToResource, StateResource } from '@alfa-client/tech-shared';
 import { inject } from '@angular/core';
 import { ActivatedRouteSnapshot, CanActivateFn, Router, UrlTree } from '@angular/router';
+import { AuthenticationService } from '@authentication';
 import { hasLink, Resource } from '@ngxp/rest';
-import { filter, map, Observable } from 'rxjs';
+import { filter, map, Observable, of } from 'rxjs';
 import { GuardData } from './app.routes';
-import { ConfigurationService } from '@admin-client/configuration-shared';
 
 import * as Guard from './app.guard';
 
-export const apiRootGuard: CanActivateFn = (route: ActivatedRouteSnapshot) => {
+export const apiRootGuard: CanActivateFn = (route: ActivatedRouteSnapshot): Observable<true | UrlTree> => {
   const apiRootService: ApiRootService = inject(ApiRootService);
   return Guard.evaluate(apiRootService.getApiRoot(), getLinkRelationName(route));
 };
 
-export const configurationGuard: CanActivateFn = (route: ActivatedRouteSnapshot) => {
+export const configurationGuard: CanActivateFn = (route: ActivatedRouteSnapshot): Observable<true | UrlTree> => {
   const configurationService: ConfigurationService = inject(ConfigurationService);
   return Guard.evaluate(configurationService.get(), getLinkRelationName(route));
 };
@@ -46,11 +47,16 @@ export const configurationGuard: CanActivateFn = (route: ActivatedRouteSnapshot)
 export function evaluate(
   stateResource$: Observable<StateResource<Resource>>,
   linkRelationName: LinkRelationName,
-): Observable<boolean | UrlTree> {
+): Observable<true | UrlTree> {
+  const authService = inject(AuthenticationService);
+  const router = inject(Router);
+
+  if (!authService.isLoggedIn()) return of(true);
+
   return stateResource$.pipe(
-    filter((stateResource: StateResource<Resource>) => stateResource.loaded),
+    filter((stateResource: StateResource<Resource>): boolean => stateResource.loaded),
     mapToResource<Resource>(),
-    map((resource: Resource) => Guard.evaluateResource(resource, linkRelationName)),
+    map((resource: Resource): true | UrlTree => Guard.evaluateResource(resource, linkRelationName, router)),
   );
 }
 
@@ -58,10 +64,10 @@ function getLinkRelationName(route: ActivatedRouteSnapshot): string {
   return (<GuardData>route.data).linkRelName;
 }
 
-export function evaluateResource(resource: Resource, linkRelationName: LinkRelationName): boolean | UrlTree {
-  return hasLink(resource, linkRelationName) ? true : redirectToUnavailable();
+export function evaluateResource(resource: Resource, linkRelationName: LinkRelationName, router: Router): true | UrlTree {
+  return hasLink(resource, linkRelationName) ? true : redirectToUnavailable(router);
 }
 
-function redirectToUnavailable(): UrlTree {
-  return inject(Router).createUrlTree(['/' + ROUTES.UNAVAILABLE]);
+function redirectToUnavailable(router: Router): UrlTree {
+  return router.createUrlTree(['/' + ROUTES.UNAVAILABLE]);
 }
diff --git a/alfa-client/apps/admin/src/app/app.routes.ts b/alfa-client/apps/admin/src/app/app.routes.ts
index 279141277b1bbd700ca663d7009e886b89453429..c5974993c237ec15254220a64157b63ae0f46136 100644
--- a/alfa-client/apps/admin/src/app/app.routes.ts
+++ b/alfa-client/apps/admin/src/app/app.routes.ts
@@ -44,6 +44,7 @@ export const appRoutes: Route[] = [
     path: ROUTES.POSTFACH,
     component: PostfachPageComponent,
     title: 'Admin | Postfach',
+    runGuardsAndResolvers: 'always',
     canActivate: [configurationGuard],
     data: <GuardData>{ linkRelName: ConfigurationLinkRel.SETTING },
   },
@@ -51,6 +52,7 @@ export const appRoutes: Route[] = [
     path: ROUTES.BENUTZER,
     component: UserListPageComponent,
     title: 'Admin | Benutzer',
+    runGuardsAndResolvers: 'always',
     canActivate: [apiRootGuard],
     data: <GuardData>{ linkRelName: ApiRootLinkRel.USERS },
   },
@@ -58,6 +60,7 @@ export const appRoutes: Route[] = [
     path: ROUTES.BENUTZER_NEU,
     component: UserFormPageComponent,
     title: 'Admin | Benutzer anlegen',
+    runGuardsAndResolvers: 'always',
     canActivate: [apiRootGuard],
     data: <GuardData>{ linkRelName: ApiRootLinkRel.USERS },
   },
@@ -65,6 +68,7 @@ export const appRoutes: Route[] = [
     path: ROUTES.BENUTZER_ID,
     component: UserFormComponent,
     title: 'Admin | Benutzer bearbeiten',
+    runGuardsAndResolvers: 'always',
     canActivate: [apiRootGuard],
     data: <GuardData>{ linkRelName: ApiRootLinkRel.USERS },
   },
@@ -82,6 +86,7 @@ export const appRoutes: Route[] = [
     path: ROUTES.STATISTIK,
     component: StatistikPageComponent,
     title: 'Admin | Statistik',
+    runGuardsAndResolvers: 'always',
     canActivate: [configurationGuard],
     data: <GuardData>{ linkRelName: ConfigurationLinkRel.AGGREGATION_MAPPINGS },
   },
@@ -89,7 +94,13 @@ export const appRoutes: Route[] = [
     path: ROUTES.STATISTIK_NEU,
     component: StatistikFieldsFormPageComponent,
     title: 'Admin | Statistik weitere Felder auswerten',
+    runGuardsAndResolvers: 'always',
     canActivate: [configurationGuard],
     data: <GuardData>{ linkRelName: ConfigurationLinkRel.AGGREGATION_MAPPINGS },
   },
+  {
+    path: '**',
+    component: UnavailablePageComponent,
+    title: 'Unavailable',
+  },
 ];
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.spec.ts
index be3f115f38c800b3b1cf87b3aaec5044e9b3c121..348a6c4b49125dca4d13765528be6b83f8b6e1de 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.spec.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.spec.ts
@@ -1,18 +1,18 @@
+import { mockWindowError } from '@alfa-client/test-utils';
 import { FormControl, FormGroup } from '@angular/forms';
 import { patchForm } from './form.util';
 
 describe('FormUtil', () => {
   describe('patch form', () => {
     it('should not throw any errors', () => {
-      const errorHandler = jest.fn();
-      window.onerror = errorHandler;
+      const errorSpy: jest.SpyInstance = mockWindowError();
       const formGroup: FormGroup = new FormGroup({
         existingKey: new FormControl(null),
       });
 
       patchForm({ missingKey: 'dummyValue' }, formGroup);
 
-      expect(errorHandler).not.toHaveBeenCalled();
+      expect(errorSpy).not.toHaveBeenCalled();
     });
 
     describe('on strings', () => {
@@ -57,6 +57,15 @@ describe('FormUtil', () => {
         expect(arrayFormGroup.controls['arrayValue1'].value).toBeTruthy();
         expect(arrayFormGroup.controls['arrayValue2'].value).toBeFalsy();
       });
+
+      it('should not throw any error if control is missing', () => {
+        const errorSpy: jest.SpyInstance = mockWindowError();
+        const formGroup: FormGroup = new FormGroup({ array: new FormGroup({}) });
+
+        patchForm({ array: ['arrayValue1'] }, formGroup);
+
+        expect(errorSpy).not.toHaveBeenCalled();
+      });
     });
 
     describe('on object value', () => {
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.ts
index 877cf9e458b14b0d2f7732086f5e033ba3b40bf5..d57cf619353a41d05d4e9d866ca098331d4345b1 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/form.util.ts
@@ -15,7 +15,9 @@ function patchNonStringValues(valueToPatch: any, formGroup: FormGroup): void {
 
 function patchNonStringValue(value: any, formGroup: FormGroup): void {
   if (Array.isArray(value)) {
-    value.forEach((oneValue: any) => formGroup.controls[oneValue].patchValue(true));
+    value.forEach((oneValue: any) => {
+      if (formGroup.contains(oneValue)) formGroup.controls[oneValue].patchValue(true);
+    });
   } else if (!isString(value) && !isBoolean(value)) {
     patchNonStringValues(value, formGroup);
   }
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts
index d0806e198efa5090d375832bbd313ca99482149b..afbb09bee049b4e79cda30ee0d97f3e4810799f9 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.spec.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { User } from '@admin-client/user-shared';
+import { RoleMappings, User } from '@admin-client/user-shared';
 import { UserRepository } from '@admin/keycloak-shared';
 import { StateResource } from '@alfa-client/tech-shared';
 import { Mock, mock } from '@alfa-client/test-utils';
@@ -30,10 +30,10 @@ import { faker } from '@faker-js/faker';
 import KcAdminClient from '@keycloak/keycloak-admin-client';
 import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
 import MappingsRepresentation from '@keycloak/keycloak-admin-client/lib/defs/mappingsRepresentation';
-import RoleRepresentation, { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
+import { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
 import { Users } from '@keycloak/keycloak-admin-client/lib/resources/users';
 import { cold } from 'jest-marbles';
-import { omit } from 'lodash-es';
+import { omit, times } from 'lodash-es';
 import { throwError } from 'rxjs';
 import { createUser } from '../../../user-shared/test/user';
 import { UserFormService } from '../../../user/src/lib/user-form/user.formservice';
@@ -71,18 +71,18 @@ describe('UserRepository', () => {
       expect(kcAdminClient.users['create']).toHaveBeenCalledWith(omit(user, 'groupIds'));
     });
 
-    it('should call addUserRoles', fakeAsync(() => {
-      repository._addUserRoles = jest.fn();
+    it('should call updateUserRoles', fakeAsync(() => {
+      repository._updateUserRoles = jest.fn();
 
       repository.createInKeycloak(user).subscribe();
       tick();
 
-      expect(repository._addUserRoles).toHaveBeenCalledWith(user.id, user.clientRoles);
+      expect(repository._updateUserRoles).toHaveBeenCalledWith(user.id, user.clientRoles);
     }));
 
     it('should call sendActivationMail', (done) => {
       repository._sendActivationMail = jest.fn();
-      repository._addUserRoles = jest.fn().mockReturnValue(Promise.resolve());
+      repository._updateUserRoles = jest.fn().mockReturnValue(Promise.resolve());
 
       repository.createInKeycloak(user).subscribe(() => {
         expect(repository._sendActivationMail).toHaveBeenCalledWith(user.id);
@@ -107,7 +107,7 @@ describe('UserRepository', () => {
         update: jest.fn().mockReturnValue(Promise.resolve()),
       };
 
-      repository._addUserRoles = jest.fn().mockReturnValue(Promise.resolve());
+      repository._updateUserRoles = jest.fn().mockReturnValue(Promise.resolve());
       repository._updateUserGroups = jest.fn().mockReturnValue(Promise.resolve());
     });
 
@@ -117,11 +117,11 @@ describe('UserRepository', () => {
       expect(kcAdminClient.users['update']).toHaveBeenCalledWith({ id: user.id }, omit(user, 'groupIds'));
     });
 
-    it('should call addUserRoles', fakeAsync(() => {
+    it('should call updateUserRoles', fakeAsync(() => {
       repository.saveInKeycloak(user).subscribe();
       tick();
 
-      expect(repository._addUserRoles).toHaveBeenCalledWith(user.id, user.clientRoles);
+      expect(repository._updateUserRoles).toHaveBeenCalledWith(user.id, user.clientRoles);
     }));
 
     it('should call updateUserGroups', (done) => {
@@ -241,70 +241,197 @@ describe('UserRepository', () => {
     });
   });
 
-  describe('addUserRoles', () => {
-    it('should call addUserRolesForClient for admin', async () => {
-      repository._addUserRolesForClient = jest.fn();
+  describe('UpdateUserRoles', () => {
+    const clientId: string = faker.string.uuid();
 
-      await repository._addUserRoles(user.id, { admin: [UserFormService.ADMIN], alfa: [] });
+    beforeEach(() => {
+      repository._updateUserRolesForClient = jest.fn();
+      repository._getClientId = jest.fn().mockReturnValue(clientId);
+    });
 
-      expect(repository._addUserRolesForClient).toHaveBeenCalledWith(
-        user.id,
-        [UserFormService.ADMIN],
-        UserRepository.ADMIN_CLIENT_NAME,
-      );
+    it('should call getClientId for admin', async () => {
+      await repository._updateUserRoles(user.id, { admin: [UserFormService.ADMIN], alfa: [] });
+
+      expect(repository._getClientId).toHaveBeenCalledWith(UserRepository.ADMIN_CLIENT_NAME);
     });
 
-    it('should call addUserRolesForClient for admin', async () => {
-      repository._addUserRolesForClient = jest.fn();
+    it('should call UpdateUserRolesForClient for admin', async () => {
+      await repository._updateUserRoles(user.id, { admin: [UserFormService.ADMIN], alfa: [] });
 
-      await repository._addUserRoles(user.id, { alfa: [UserFormService.POSTSTELLE], admin: [] });
+      expect(repository._updateUserRolesForClient).toHaveBeenCalledWith(user.id, [UserFormService.ADMIN], clientId);
+    });
 
-      expect(repository._addUserRolesForClient).toHaveBeenCalledWith(
-        user.id,
-        [UserFormService.POSTSTELLE],
-        UserRepository.ALFA_CLIENT_NAME,
-      );
+    it('should call getClientId for admin', async () => {
+      await repository._updateUserRoles(user.id, { alfa: [UserFormService.POSTSTELLE], admin: [] });
+
+      expect(repository._getClientId).toHaveBeenCalledWith(UserRepository.ALFA_CLIENT_NAME);
+    });
+
+    it('should call UpdateUserRolesForClient for admin', async () => {
+      await repository._updateUserRoles(user.id, { alfa: [UserFormService.POSTSTELLE], admin: [] });
+
+      expect(repository._updateUserRolesForClient).toHaveBeenCalledWith(user.id, [UserFormService.POSTSTELLE], clientId);
     });
+  });
+
+  describe('updateUserRolesForClient', () => {
+    const clientId: string = faker.string.uuid();
+    const clientRoles: string[] = times(3, () => faker.word.sample());
+    const newClientRoleMappings: RoleMappingPayload[] = clientRoles.map((role: string) => ({
+      id: faker.string.uuid(),
+      name: role,
+    }));
+    const oldClientRoleMappings: RoleMappingPayload[] = newClientRoleMappings.slice(1);
+    const clientRoleMappings: RoleMappings = { newClientRoleMappings, oldClientRoleMappings };
 
-    it('should not call addUserRolesForClient if clientRoles alfa and admin are empty', async () => {
-      repository._addUserRolesForClient = jest.fn();
+    beforeEach(() => {
+      repository._getClientRoleMappings = jest.fn().mockReturnValue(Promise.resolve(clientRoleMappings));
+      repository._deleteUserRoles = jest.fn();
+      repository._addUserRoles = jest.fn();
+    });
+
+    it('should call getClientRoleMappings', async () => {
+      await repository._updateUserRolesForClient(user.id, clientRoles, clientId);
+
+      expect(repository._getClientRoleMappings).toHaveBeenCalledWith(user.id, clientId, clientRoles);
+    });
 
-      await repository._addUserRoles(user.id, { admin: [], alfa: [] });
+    it('should call deleteUserRoles', async () => {
+      await repository._updateUserRolesForClient(user.id, clientRoles, clientId);
 
-      expect(repository._addUserRolesForClient).not.toHaveBeenCalled();
+      expect(repository._deleteUserRoles).toHaveBeenCalledWith(user.id, clientRoleMappings, clientId);
+    });
+
+    it('should call addUserRoles', async () => {
+      await repository._updateUserRolesForClient(user.id, clientRoles, clientId);
+
+      expect(repository._addUserRoles).toHaveBeenCalledWith(user.id, clientRoleMappings, clientId);
     });
   });
 
-  describe('addUserRolesForClient', () => {
+  describe('getClientRoleMappings', () => {
     const clientId: string = faker.string.uuid();
-    const roleMapping: RoleMappingPayload[] = [{ id: faker.string.uuid(), name: faker.word.sample() }];
+    const newClientRoles: string[] = times(3, () => faker.word.sample());
+    const newClientRoleMappings: RoleMappingPayload[] = newClientRoles.map((role: string) => ({
+      id: faker.string.uuid(),
+      name: role,
+    }));
+    const oldClientRoleMappings: RoleMappingPayload[] = newClientRoleMappings.slice(1);
+    const clientRoleMappings: RoleMappings = { newClientRoleMappings, oldClientRoleMappings };
 
     beforeEach(() => {
+      repository._getOldUserRoleMappings = jest.fn().mockReturnValue(Promise.resolve(oldClientRoleMappings));
       repository._getClientId = jest.fn().mockReturnValue(Promise.resolve(clientId));
-      repository._mapUserRoles = jest.fn().mockReturnValue(Promise.resolve(roleMapping));
-      repository._addUserRolesInKeycloak = jest.fn();
+      repository._mapUserRoles = jest.fn().mockReturnValue(Promise.resolve(newClientRoleMappings));
+      repository._deleteUserRoles = jest.fn();
+      repository._addUserRoles = jest.fn();
+    });
+
+    it('should call mapUserRoles', () => {
+      repository._getClientRoleMappings(user.id, clientId, newClientRoles);
+
+      expect(repository._mapUserRoles).toHaveBeenCalledWith(clientId, newClientRoles);
+    });
+
+    it('should call get old user role mappings', async () => {
+      await repository._getClientRoleMappings(user.id, clientId, newClientRoles);
+
+      expect(repository._getOldUserRoleMappings).toHaveBeenCalledWith(user.id, clientId);
+    });
+
+    it('should return clientRoleMappings', async () => {
+      const result: RoleMappings = await repository._getClientRoleMappings(user.id, clientId, newClientRoles);
+
+      expect(result).toEqual(clientRoleMappings);
+    });
+  });
+
+  describe('getOldUserRoleMappings', () => {
+    const clientId: string = faker.string.uuid();
+    const roleMapping: RoleMappingPayload[] = [{ id: faker.string.uuid(), name: faker.word.sample() }];
+
+    beforeEach(() => {
+      kcAdminClient.users = <any>{
+        listClientRoleMappings: jest.fn().mockReturnValue(Promise.resolve(roleMapping)),
+      };
+    });
+
+    it('should call users listClientRoleMappings', () => {
+      repository._getOldUserRoleMappings(user.id, clientId);
+
+      expect(kcAdminClient.users['listClientRoleMappings']).toHaveBeenCalledWith({ id: user.id, clientUniqueId: clientId });
+    });
+
+    it('should return roleMapping', async () => {
+      const result: RoleMappingPayload[] = await repository._getOldUserRoleMappings(user.id, clientId);
+
+      expect(result).toEqual(roleMapping);
+    });
+  });
+
+  describe('deleteUserRoles', () => {
+    const clientId: string = faker.string.uuid();
+    const clientRoles: string[] = times(3, () => faker.word.sample());
+    const oldClientRoleMappings: RoleMappingPayload[] = clientRoles.map((role: string) => ({
+      id: faker.string.uuid(),
+      name: role,
+    }));
+    const newClientRoleMappings: RoleMappingPayload[] = oldClientRoleMappings.slice(1);
+    const clientRoleMappings: RoleMappings = { newClientRoleMappings, oldClientRoleMappings };
+
+    beforeEach(() => {
+      repository._deleteUserRolesInKeycloak = jest.fn();
 
       kcAdminClient.users = <any>{
         addClientRoleMappings: jest.fn().mockReturnValue(Promise.resolve()),
       };
     });
 
-    it('should call getClientId', async () => {
-      await repository._addUserRolesForClient(user.id, [UserFormService.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
+    it('should call deleteUserRolesInKeycloak', async () => {
+      await repository._deleteUserRoles(user.id, clientRoleMappings, clientId);
+
+      expect(repository._deleteUserRolesInKeycloak).toHaveBeenCalledWith(user.id, clientId, [oldClientRoleMappings[0]]);
+    });
+
+    it('should call not call deleteUserRolesInKeycloak if no roles to delete', async () => {
+      await repository._deleteUserRoles(
+        user.id,
+        { oldClientRoleMappings, newClientRoleMappings: oldClientRoleMappings },
+        clientId,
+      );
 
-      expect(repository._getClientId).toHaveBeenCalled();
+      expect(repository._deleteUserRolesInKeycloak).not.toHaveBeenCalled();
     });
+  });
+
+  describe('addUserRoles', () => {
+    const clientId: string = faker.string.uuid();
+    const clientRoles: string[] = times(3, () => faker.word.sample());
+    const newClientRoleMappings: RoleMappingPayload[] = clientRoles.map((role: string) => ({
+      id: faker.string.uuid(),
+      name: role,
+    }));
+    const oldClientRoleMappings: RoleMappingPayload[] = newClientRoleMappings.slice(1);
+    const clientRoleMappings: RoleMappings = { newClientRoleMappings, oldClientRoleMappings };
 
-    it('should call getAlfaClientId', async () => {
-      await repository._addUserRolesForClient(user.id, [UserFormService.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
+    beforeEach(() => {
+      repository._addUserRolesInKeycloak = jest.fn();
 
-      expect(repository._mapUserRoles).toHaveBeenCalledWith(clientId, [UserFormService.ADMIN]);
+      kcAdminClient.users = <any>{
+        addClientRoleMappings: jest.fn().mockReturnValue(Promise.resolve()),
+      };
     });
 
     it('should call addUserRolesInKeycloak', async () => {
-      await repository._addUserRolesForClient(user.id, [UserFormService.ADMIN], UserRepository.ADMIN_CLIENT_NAME);
+      await repository._addUserRoles(user.id, clientRoleMappings, clientId);
 
-      expect(repository._addUserRolesInKeycloak).toHaveBeenCalledWith(user.id, clientId, roleMapping);
+      expect(repository._addUserRolesInKeycloak).toHaveBeenCalledWith(user.id, clientId, [newClientRoleMappings[0]]);
+    });
+
+    it('should not call addUserRolesInKeycloak if no roles to add', async () => {
+      await repository._addUserRoles(user.id, { newClientRoleMappings, oldClientRoleMappings: newClientRoleMappings }, clientId);
+
+      expect(repository._addUserRolesInKeycloak).not.toHaveBeenCalled();
     });
   });
 
@@ -332,11 +459,11 @@ describe('UserRepository', () => {
 
   describe('mapUserRoles', () => {
     const clientId: string = faker.string.uuid();
-    const clientRoles: RoleRepresentation[] = Array.from({ length: 3 }, () => ({
+    const clientRoles: RoleMappingPayload[] = Array.from({ length: 3 }, () => ({
       id: faker.string.uuid(),
       name: faker.word.sample(),
     }));
-    const userRoles: string[] = clientRoles.map((role) => role.name).slice(1);
+    const userRoles: string[] = clientRoles.map((role: RoleMappingPayload): string => role.name).slice(1);
 
     beforeEach(() => {
       kcAdminClient.clients = <any>{
@@ -353,7 +480,7 @@ describe('UserRepository', () => {
     it('should return roleMapping', async () => {
       const result: RoleMappingPayload[] = await repository._mapUserRoles(clientId, userRoles);
 
-      expect(result).toEqual(clientRoles.slice(1).map((role) => ({ id: role.id, name: role.name })));
+      expect(result).toEqual(clientRoles.slice(1));
     });
 
     it('should filter roles if they are not in clientRoles', async () => {
@@ -383,6 +510,26 @@ describe('UserRepository', () => {
     });
   });
 
+  describe('deleteUserRolesInKeycloak', () => {
+    beforeEach(() => {
+      kcAdminClient.users = <any>{
+        delClientRoleMappings: jest.fn().mockReturnValue(Promise.resolve()),
+      };
+    });
+
+    it('should call kcAdminClient users delClientRoleMappings', async () => {
+      const clientId: string = faker.string.uuid();
+      const roles: RoleMappingPayload[] = Array.from({ length: 3 }, () => ({
+        id: faker.string.uuid(),
+        name: faker.word.sample(),
+      }));
+
+      await repository._deleteUserRolesInKeycloak(user.id, clientId, roles);
+
+      expect(kcAdminClient.users['delClientRoleMappings']).toHaveBeenCalledWith({ id: user.id, clientUniqueId: clientId, roles });
+    });
+  });
+
   describe('sendActivationMail', () => {
     it('should call kcAdminClient users executeActionsEmail', () => {
       const userId: string = faker.string.uuid();
diff --git a/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts
index a5df128a7de4ceb8bd71c4d2edc337078b57bcca..e5eca5be54120f7fdf51b66d130053a330ced543 100644
--- a/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts
+++ b/alfa-client/libs/admin/keycloak-shared/src/lib/user.repository.ts
@@ -21,18 +21,20 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import { ClientMapping, ClientRoles, User } from '@admin-client/user-shared';
+import { ClientMapping, ClientRoles, RoleMappings, User } from '@admin-client/user-shared';
 import { createStateResource, StateResource } from '@alfa-client/tech-shared';
 import { inject, Injectable } from '@angular/core';
 import KcAdminClient from '@keycloak/keycloak-admin-client';
 import ClientRepresentation from '@keycloak/keycloak-admin-client/lib/defs/clientRepresentation';
 import GroupRepresentation from '@keycloak/keycloak-admin-client/lib/defs/groupRepresentation';
 import MappingsRepresentation from '@keycloak/keycloak-admin-client/lib/defs/mappingsRepresentation';
-import RoleRepresentation, { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
+import { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
 import UserRepresentation from '@keycloak/keycloak-admin-client/lib/defs/userRepresentation';
 import { isNil, omit } from 'lodash-es';
 import { catchError, concatMap, forkJoin, from, map, mergeMap, Observable, tap, throwError } from 'rxjs';
 
+import * as _ from 'lodash-es';
+
 @Injectable({
   providedIn: 'root',
 })
@@ -45,7 +47,7 @@ export class UserRepository {
   public createInKeycloak(user: User): Observable<User> {
     return from(this.kcAdminClient.users.create(omit(user, 'groupIds'))).pipe(
       concatMap(async (response: { id: string }): Promise<{ id: string }> => {
-        await this._addUserRoles(response.id, user.clientRoles);
+        await this._updateUserRoles(response.id, user.clientRoles);
         return response;
       }),
       tap((response: { id: string }): void => this._sendActivationMail(response.id)),
@@ -58,7 +60,7 @@ export class UserRepository {
     const { groupIds, ...userToSave } = user;
     return from(this.kcAdminClient.users.update({ id: user.id }, userToSave)).pipe(
       concatMap(async (): Promise<void> => {
-        await this._addUserRoles(user.id, user.clientRoles);
+        await this._updateUserRoles(user.id, user.clientRoles);
         await this._updateUserGroups(user.id, user.groupIds);
       }),
       map((): User => user),
@@ -73,8 +75,10 @@ export class UserRepository {
   }
 
   async _getOldUserGroupIds(userId: string): Promise<string[]> {
-    const oldUserGroupsReps: GroupRepresentation[] = await this.kcAdminClient.users.listGroups({ id: userId });
-    return oldUserGroupsReps.map((group: GroupRepresentation): string => group.id);
+    const oldUserGroupsReps: RoleMappingPayload[] = <RoleMappingPayload[]>(
+      await this.kcAdminClient.users.listGroups({ id: userId })
+    );
+    return _.map(oldUserGroupsReps, 'id');
   }
 
   async _deleteUserGroups(userId: string, newGroupIds: string[], oldGroupIds: string[]): Promise<void> {
@@ -87,7 +91,7 @@ export class UserRepository {
     );
   }
 
-  async _addUserGroups(userId: string, newGroupIds: string[], oldGroupIds): Promise<void> {
+  async _addUserGroups(userId: string, newGroupIds: string[], oldGroupIds: string[]): Promise<void> {
     await Promise.all(
       newGroupIds
         .filter((group) => !oldGroupIds.includes(group))
@@ -97,20 +101,54 @@ export class UserRepository {
     );
   }
 
-  async _addUserRoles(userId: string, clientRoles: ClientRoles): Promise<void> {
-    if (clientRoles.admin.length > 0) {
-      await this._addUserRolesForClient(userId, clientRoles.admin, UserRepository.ADMIN_CLIENT_NAME);
+  async _updateUserRoles(userId: string, clientRoles: ClientRoles): Promise<void> {
+    await this._updateUserRolesForClient(userId, clientRoles.admin, await this._getClientId(UserRepository.ADMIN_CLIENT_NAME));
+    await this._updateUserRolesForClient(userId, clientRoles.alfa, await this._getClientId(UserRepository.ALFA_CLIENT_NAME));
+  }
+
+  async _updateUserRolesForClient(userId: string, clientRoles: string[], clientId: string): Promise<void> {
+    const roleMappings: RoleMappings = await this._getClientRoleMappings(userId, clientId, clientRoles);
+    await this._deleteUserRoles(userId, roleMappings, clientId);
+    await this._addUserRoles(userId, roleMappings, clientId);
+  }
+
+  async _getClientRoleMappings(userId: string, clientId: string, clientRoles: string[]): Promise<RoleMappings> {
+    const newClientRoleMappings: RoleMappingPayload[] = await this._mapUserRoles(clientId, clientRoles);
+    const oldClientRoleMappings: RoleMappingPayload[] = await this._getOldUserRoleMappings(userId, clientId);
+    return { newClientRoleMappings, oldClientRoleMappings };
+  }
+
+  async _getOldUserRoleMappings(userId: string, clientId: string): Promise<RoleMappingPayload[]> {
+    return <RoleMappingPayload[]>await this.kcAdminClient.users.listClientRoleMappings({
+      id: userId,
+      clientUniqueId: clientId,
+    });
+  }
+
+  async _deleteUserRoles(userId: string, roleMappings: RoleMappings, clientId: string): Promise<void> {
+    const rolesToDelete: RoleMappingPayload[] = this.getRolesToDelete(roleMappings);
+    if (rolesToDelete.length > 0) {
+      await this._deleteUserRolesInKeycloak(userId, clientId, rolesToDelete);
     }
+  }
+
+  private getRolesToDelete(roleMappings: RoleMappings): RoleMappingPayload[] {
+    return roleMappings.oldClientRoleMappings.filter(
+      (role: RoleMappingPayload) => !_.map(roleMappings.newClientRoleMappings, 'name').includes(role.name),
+    );
+  }
 
-    if (clientRoles.alfa.length > 0) {
-      await this._addUserRolesForClient(userId, clientRoles.alfa, UserRepository.ALFA_CLIENT_NAME);
+  async _addUserRoles(userId: string, roleMappings: RoleMappings, clientId: string): Promise<void> {
+    const rolesToAdd: RoleMappingPayload[] = this.getRolesToAdd(roleMappings);
+    if (rolesToAdd.length > 0) {
+      await this._addUserRolesInKeycloak(userId, clientId, rolesToAdd);
     }
   }
 
-  async _addUserRolesForClient(userId: string, userRoles: string[], client: string): Promise<void> {
-    const clientId: string = await this._getClientId(client);
-    const roles: RoleMappingPayload[] = await this._mapUserRoles(clientId, userRoles);
-    await this._addUserRolesInKeycloak(userId, clientId, roles);
+  private getRolesToAdd(roleMappings: RoleMappings): RoleMappingPayload[] {
+    return roleMappings.newClientRoleMappings.filter(
+      (role: RoleMappingPayload) => !_.map(roleMappings.oldClientRoleMappings, 'name').includes(role.name),
+    );
   }
 
   async _getClientId(client: string): Promise<string | undefined> {
@@ -119,10 +157,8 @@ export class UserRepository {
   }
 
   async _mapUserRoles(clientId: string, userRoles: string[]): Promise<RoleMappingPayload[]> {
-    const roles: RoleRepresentation[] = await this.kcAdminClient.clients.listRoles({ id: clientId });
-    return roles
-      .filter((role: RoleRepresentation): boolean => userRoles.includes(role.name))
-      .map((role: RoleRepresentation): RoleMappingPayload => ({ id: role.id, name: role.name }));
+    const roles: RoleMappingPayload[] = <RoleMappingPayload[]>await this.kcAdminClient.clients.listRoles({ id: clientId });
+    return roles.filter((role: RoleMappingPayload): boolean => userRoles.includes(role.name));
   }
 
   async _addUserRolesInKeycloak(userId: string, clientId: string, roles: RoleMappingPayload[]): Promise<void> {
@@ -133,6 +169,14 @@ export class UserRepository {
     });
   }
 
+  async _deleteUserRolesInKeycloak(userId: string, clientId: string, roles: RoleMappingPayload[]): Promise<void> {
+    await this.kcAdminClient.users.delClientRoleMappings({
+      id: userId,
+      clientUniqueId: clientId,
+      roles,
+    });
+  }
+
   _sendActivationMail(userId: string): void {
     this.kcAdminClient.users.executeActionsEmail({
       id: userId,
@@ -208,7 +252,7 @@ export class UserRepository {
 
   private getUserGroups(user: User): Observable<string[]> {
     return from(this.kcAdminClient.users.listGroups({ id: user.id })).pipe(
-      map((groups: GroupRepresentation[]): string[] => groups.map((group: GroupRepresentation): string => group.name)),
+      map((groups: GroupRepresentation[]): string[] => _.map(groups, 'name')),
     );
   }
 
@@ -230,6 +274,6 @@ export class UserRepository {
       return [];
     }
 
-    return clientMappingsAlfa.mappings.map((role: RoleRepresentation): string => role.name);
+    return _.map(clientMappingsAlfa.mappings, 'name');
   }
 }
diff --git a/alfa-client/libs/admin/postfach/src/lib/postfach-container/postfach-container.component.html b/alfa-client/libs/admin/postfach/src/lib/postfach-container/postfach-container.component.html
index 3e8e4b49ae09ba083768eb4a1ffa4155ab1bb49c..4cc1c39f9ceae871719596a641734e16f8f966c4 100644
--- a/alfa-client/libs/admin/postfach/src/lib/postfach-container/postfach-container.component.html
+++ b/alfa-client/libs/admin/postfach/src/lib/postfach-container/postfach-container.component.html
@@ -1,2 +1,2 @@
-<h1 class="heading-1">Postfach</h1>
+<h1 class="heading-1" data-test-id="headline">Postfach</h1>
 <admin-postfach-form [postfachStateResource]="postfachStateResource$ | async" />
diff --git a/alfa-client/libs/admin/user-shared/src/lib/user.model.ts b/alfa-client/libs/admin/user-shared/src/lib/user.model.ts
index db185a0209450a60d50e2ffc89a263d62f480d12..f496e42b8734907ab060fe4872fc91cb29b14c42 100644
--- a/alfa-client/libs/admin/user-shared/src/lib/user.model.ts
+++ b/alfa-client/libs/admin/user-shared/src/lib/user.model.ts
@@ -21,7 +21,7 @@
  * Die sprachspezifischen Genehmigungen und Beschränkungen
  * unter der Lizenz sind dem Lizenztext zu entnehmen.
  */
-import RoleRepresentation from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
+import RoleRepresentation, { RoleMappingPayload } from '@keycloak/keycloak-admin-client/lib/defs/roleRepresentation';
 
 export interface User {
   id?: string;
@@ -43,3 +43,8 @@ export interface ClientRoles {
 export interface ClientMapping {
   mappings: RoleRepresentation[];
 }
+
+export interface RoleMappings {
+  newClientRoleMappings: RoleMappingPayload[];
+  oldClientRoleMappings: RoleMappingPayload[];
+}
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.html b/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.html
index b604db41588c7f1fbd381c194a8fb98a69aad0c3..d25b43725be072ab68c5e322fc268d172a88982b 100644
--- a/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.html
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user-form-roles/user-form-roles.component.html
@@ -12,6 +12,16 @@
           <ods-info-icon />
         </button>
       </div>
+      <div class="flex items-center gap-2">
+        <ods-checkbox-editor
+          [formControlName]="UserFormService.DATENBEAUFTRAGUNG"
+          label="Datenbeauftragung"
+          inputId="datenbeauftragung"
+        />
+        <ods-info-icon
+          tooltip='Diese Rolle kann in der Administration unter dem Menüpunkt "Statistik" Felder zur Auswertung konfigurieren. Sie ist mit allen anderen Rollen kompatibel.'
+        />
+      </div>
     </div>
     <div [formGroupName]="UserFormService.ALFA_GROUP" class="flex flex-col gap-2">
       <h3 class="text-md block font-medium text-text">Alfa</h3>
diff --git a/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.ts b/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.ts
index 3d0960b1d363fe87688c1c9fd07f7b61ddefc67c..494673b77cf049e6219418f7a726173af20e3fd0 100644
--- a/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.ts
+++ b/alfa-client/libs/admin/user/src/lib/user-form/user.formservice.ts
@@ -52,6 +52,7 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest
   public static readonly GROUPS: string = 'groups';
   public static readonly ADMINISTRATION_GROUP: string = 'admin';
   public static readonly ADMIN: string = 'ADMIN_ADMIN';
+  public static readonly DATENBEAUFTRAGUNG: string = 'DATENBEAUFTRAGUNG';
   public static readonly ALFA_GROUP: string = 'alfa';
   public static readonly LOESCHEN: string = 'VERWALTUNG_LOESCHEN';
   public static readonly USER: string = 'VERWALTUNG_USER';
@@ -100,6 +101,7 @@ export class UserFormService extends KeycloakFormService<User> implements OnDest
         {
           [UserFormService.ADMINISTRATION_GROUP]: this.formBuilder.group({
             [UserFormService.ADMIN]: new FormControl(false),
+            [UserFormService.DATENBEAUFTRAGUNG]: new FormControl(false),
           }),
           [UserFormService.ALFA_GROUP]: this.formBuilder.group({
             [UserFormService.LOESCHEN]: new FormControl(false),
diff --git a/alfa-client/libs/admin/user/test/form.ts b/alfa-client/libs/admin/user/test/form.ts
index 7b3f06850de1ff16504596b38056fb3752b3d5e5..d8ac4bb73c5b96a51e5559e85d8876a1695506aa 100644
--- a/alfa-client/libs/admin/user/test/form.ts
+++ b/alfa-client/libs/admin/user/test/form.ts
@@ -12,6 +12,7 @@ export function createUserFormGroup(): UntypedFormGroup {
     [UserFormService.CLIENT_ROLES]: new UntypedFormGroup({
       [UserFormService.ADMINISTRATION_GROUP]: new UntypedFormGroup({
         [UserFormService.ADMIN]: new FormControl(false),
+        [UserFormService.DATENBEAUFTRAGUNG]: new FormControl(false),
       }),
       [UserFormService.ALFA_GROUP]: new UntypedFormGroup({
         [UserFormService.LOESCHEN]: new FormControl(false),
diff --git a/alfa-client/libs/authentication/src/lib/authentication.service.spec.ts b/alfa-client/libs/authentication/src/lib/authentication.service.spec.ts
index 486415f425de82475e9733ec3f5800cb47128c92..0e2ba5d44dd5054b2fa2b0e651b8205cf0327258 100644
--- a/alfa-client/libs/authentication/src/lib/authentication.service.spec.ts
+++ b/alfa-client/libs/authentication/src/lib/authentication.service.spec.ts
@@ -23,10 +23,11 @@
  */
 import { Mock, mock, useFromMock } from '@alfa-client/test-utils';
 import { UserProfileResource } from '@alfa-client/user-profile-shared';
+import { NavigationEnd, Router } from '@angular/router';
 import { AuthConfig, OAuthEvent, OAuthService } from 'angular-oauth2-oidc';
 import { Environment } from 'libs/environment-shared/src/lib/environment.model';
 import { createUserProfileResource } from 'libs/user-profile-shared/test/user-profile';
-import { Subject } from 'rxjs';
+import { of, Subject } from 'rxjs';
 import { createEnvironment } from '../../../environment-shared/test/environment';
 import { createAuthConfig, createOAuthEvent } from '../../test/authentication';
 import { AuthenticationService } from './authentication.service';
@@ -34,6 +35,7 @@ import { AuthenticationService } from './authentication.service';
 describe('AuthenticationService', () => {
   let service: AuthenticationService;
   let oAuthService: Mock<OAuthService>;
+  let router: Mock<Router>;
   let environmentConfig: Environment;
 
   let eventsSubject: Subject<OAuthEvent>;
@@ -41,6 +43,7 @@ describe('AuthenticationService', () => {
   beforeEach(() => {
     eventsSubject = new Subject<OAuthEvent>();
 
+    router = mock(Router);
     oAuthService = <any>{
       ...mock(OAuthService),
       loadDiscoveryDocumentAndLogin: jest.fn().mockResolvedValue(() => Promise.resolve()),
@@ -50,12 +53,19 @@ describe('AuthenticationService', () => {
     Object.defineProperty(oAuthService, 'events', { get: () => eventsSubject });
 
     environmentConfig = createEnvironment();
-    service = new AuthenticationService(useFromMock(oAuthService), environmentConfig);
+    service = new AuthenticationService(useFromMock(oAuthService), useFromMock(router), environmentConfig);
   });
 
   describe('login', () => {
     beforeEach(() => {
       service.buildAuthEventPromise = jest.fn();
+      service._initialNavigationIsDone = jest.fn().mockResolvedValue(() => Promise.resolve());
+    });
+
+    it('should wait for initial navigation', async () => {
+      await service.login();
+
+      expect(service._initialNavigationIsDone).toHaveBeenCalled();
     });
 
     it('should configure service with authConfig', async () => {
@@ -89,8 +99,8 @@ describe('AuthenticationService', () => {
       expect(service.buildAuthEventPromise).toHaveBeenCalled();
     });
 
-    it('should load discovery document and login', () => {
-      service.login();
+    it('should load discovery document and login', async () => {
+      await service.login();
 
       expect(oAuthService.loadDiscoveryDocumentAndLogin).toHaveBeenCalled();
     });
@@ -105,6 +115,16 @@ describe('AuthenticationService', () => {
     });
   });
 
+  describe('_initialNavigationIsDone', () => {
+    it('should wait for navigation end event', async () => {
+      (router.events as any) = of(new NavigationEnd(0, 'url1', 'url1'));
+
+      const promise: Promise<void> = service._initialNavigationIsDone();
+
+      await expect(promise).resolves.toBeUndefined();
+    });
+  });
+
   describe('build auth event promise', () => {
     const event: OAuthEvent = createOAuthEvent();
 
@@ -350,4 +370,20 @@ describe('AuthenticationService', () => {
       expect(oAuthService.revokeTokenAndLogout).toHaveBeenCalled();
     });
   });
+
+  describe('isLoggedIn', () => {
+    it('should call oAuthService hasValidAccessToken', () => {
+      service.isLoggedIn();
+
+      expect(oAuthService.hasValidAccessToken).toHaveBeenCalled();
+    });
+
+    it('should return result', () => {
+      oAuthService.hasValidAccessToken.mockReturnValue(true);
+
+      const isLoggedIn: boolean = service.isLoggedIn();
+
+      expect(isLoggedIn).toBe(true);
+    });
+  });
 });
diff --git a/alfa-client/libs/authentication/src/lib/authentication.service.ts b/alfa-client/libs/authentication/src/lib/authentication.service.ts
index e350dcafe7cb9312799db97db5eb50c0d25c8319..4918b8f8d7e95c9ff71b2c53a7aa487266e91155 100644
--- a/alfa-client/libs/authentication/src/lib/authentication.service.ts
+++ b/alfa-client/libs/authentication/src/lib/authentication.service.ts
@@ -23,11 +23,12 @@
  */
 import { Environment, ENVIRONMENT_CONFIG } from '@alfa-client/environment-shared';
 import { Inject, Injectable } from '@angular/core';
+import { NavigationEnd, Router } from '@angular/router';
 import { AuthConfig, OAuthEvent, OAuthService } from 'angular-oauth2-oidc';
 import { JwksValidationHandler } from 'angular-oauth2-oidc-jwks';
 import { UserProfileResource } from 'libs/user-profile-shared/src/lib/user-profile.model';
 import { getUserNameInitials } from 'libs/user-profile-shared/src/lib/user-profile.util';
-import { filter, Subscription } from 'rxjs';
+import { filter, firstValueFrom, Subscription } from 'rxjs';
 
 @Injectable({ providedIn: 'root' })
 export class AuthenticationService {
@@ -37,10 +38,13 @@ export class AuthenticationService {
 
   constructor(
     private oAuthService: OAuthService,
+    private router: Router,
     @Inject(ENVIRONMENT_CONFIG) private envConfig: Environment,
   ) {}
 
   public async login(): Promise<void> {
+    await this._initialNavigationIsDone();
+
     this.oAuthService.configure(this.buildConfiguration());
     this.oAuthService.setupAutomaticSilentRefresh();
     this.oAuthService.tokenValidationHandler = new JwksValidationHandler();
@@ -50,6 +54,10 @@ export class AuthenticationService {
     return eventPromise;
   }
 
+  async _initialNavigationIsDone(): Promise<void> {
+    await firstValueFrom(this.router.events.pipe(filter((event) => event instanceof NavigationEnd)));
+  }
+
   buildAuthEventPromise(): Promise<void> {
     return new Promise<void>((resolve, reject) => this.handleAuthEventsForPromise(resolve, reject));
   }
@@ -90,7 +98,7 @@ export class AuthenticationService {
     return {
       issuer: this.envConfig.authServer + '/realms/' + this.envConfig.realm,
       tokenEndpoint: this.envConfig.authServer + '/realms/' + this.envConfig.realm + '/protocol/openid-connect/token',
-      redirectUri: window.location.origin + '/',
+      redirectUri: window.location.origin + window.location.pathname,
       clientId: this.envConfig.clientId,
       scope: 'openid profile',
       requireHttps: false,
@@ -119,4 +127,8 @@ export class AuthenticationService {
   public logout(): void {
     this.oAuthService.revokeTokenAndLogout();
   }
+
+  public isLoggedIn(): boolean {
+    return this.oAuthService.hasValidAccessToken();
+  }
 }
diff --git a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html
index edd8aff832236fb11a9b372a47c40f4bbb8d06d3..007a02ec854d9001c4eaef88f688760d6db3fa8d 100644
--- a/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html
+++ b/alfa-client/libs/bescheid/src/lib/bescheid-wizard-container/bescheid-wizard/dokumente-hochladen-container/form/bescheid-wizard-dokumente-hochladen-form.component.html
@@ -23,7 +23,7 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<div class="mt-4 flex flex-col gap-4">
+<div class="mt-4 flex max-w-72 flex-col gap-4">
   @if (bescheidResource | hasLink: BescheidLinkRel.CREATE_DOCUMENT) {
     <alfa-bescheid-wizard-create-document-button-container
       [bescheidResource]="bescheidResource"
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html
index cfa93fbc6b3b9dbd01834a8d31c1bf74f4088299..de2d67af94b520ec15bb8292ef9278cb78d8e395 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html
+++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.html
@@ -23,9 +23,7 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<ods-attachment-wrapper>
-  <alfa-binary-file-list
-    [binaryFileListStateResource]="binaryFileListStateResource$ | async"
-    [listOrientation]="listOrientation"
-  ></alfa-binary-file-list>
-</ods-attachment-wrapper>
+<alfa-binary-file-list
+  [binaryFileListStateResource]="binaryFileListStateResource$ | async"
+  [listOrientation]="listOrientation"
+></alfa-binary-file-list>
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts
index e9473e9ee486bc437328ee6fe85227d12c6293e5..6cca0983e8268484b83772fa1f78dafda782e70e 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list-container.component.spec.ts
@@ -34,27 +34,19 @@ import { of } from 'rxjs';
 import { BinaryFileListContainerComponent } from './binary-file-list-container.component';
 import { BinaryFileListComponent } from './binary-file-list/binary-file-list.component';
 
-import { AttachmentWrapperComponent } from '@ods/system';
-
 describe('BinaryFileListContainerComponent', () => {
   let component: BinaryFileListContainerComponent;
   let fixture: ComponentFixture<BinaryFileListContainerComponent>;
 
   const binaryFileService: Mock<BinaryFileService> = mock(BinaryFileService);
 
-  const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(
-    createBinaryFileResource(),
-  );
+  const binaryFileStateResource: StateResource<BinaryFileResource> = createStateResource(createBinaryFileResource());
   const resource: Resource = createDummyResource();
   const linkRel: LinkRelationName = DummyLinkRel.DUMMY;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [
-        BinaryFileListContainerComponent,
-        MockComponent(BinaryFileListComponent),
-        MockComponent(AttachmentWrapperComponent),
-      ],
+      declarations: [BinaryFileListContainerComponent, MockComponent(BinaryFileListComponent)],
       providers: [
         {
           provide: BinaryFileService,
@@ -85,8 +77,10 @@ describe('BinaryFileListContainerComponent', () => {
 
   describe('binary file list', () => {
     it('should be called with binary file state resource', () => {
-      const binaryFileListComponent: BinaryFileListComponent =
-        getMockComponent<BinaryFileListComponent>(fixture, BinaryFileListComponent);
+      const binaryFileListComponent: BinaryFileListComponent = getMockComponent<BinaryFileListComponent>(
+        fixture,
+        BinaryFileListComponent,
+      );
 
       expect(binaryFileListComponent.binaryFileListStateResource).toBe(binaryFileStateResource);
     });
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html
index 70054de869940144f9b0e1d3fa0eb7c23ea72a33..a4ee6adc69c75525b8a32dd2e0ad5a9352701c2d 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html
+++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.html
@@ -23,11 +23,13 @@
     unter der Lizenz sind dem Lizenztext zu entnehmen.
 
 -->
-<div [binaryFileListOrientation]="listOrientation">
-  <alfa-binary-file2-container
-    *ngFor="let binaryFile of binaryFileListStateResource.resource | toEmbeddedResources: binaryFileListLinkRel.FILE_LIST"
-    [file]="binaryFile"
-    [deletable]="false"
-  >
-  </alfa-binary-file2-container>
-</div>
+@if (binaryFileListStateResource.resource | toEmbeddedResources: binaryFileListLinkRel.FILE_LIST; as binaryFileList) {
+  @if (binaryFileList.length) {
+    <ods-attachment-wrapper data-test-id="binary-file-list-wrapper">
+      <div [binaryFileListOrientation]="listOrientation">
+        <alfa-binary-file2-container *ngFor="let binaryFile of binaryFileList" [file]="binaryFile" [deletable]="false">
+        </alfa-binary-file2-container>
+      </div>
+    </ods-attachment-wrapper>
+  }
+}
diff --git a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts
index fbbc820600ee4d1b3a9235dafd3515f9c1f16404..354a9d2be51cb3f1bd9bdb20d1525ed75b653904 100644
--- a/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts
+++ b/alfa-client/libs/binary-file/src/lib/binary-file-list-container/binary-file-list/binary-file-list.component.spec.ts
@@ -23,9 +23,11 @@
  */
 import { BinaryFileListResource, BinaryFileResource } from '@alfa-client/binary-file-shared';
 import { createStateResource, StateResource, ToEmbeddedResourcesPipe } from '@alfa-client/tech-shared';
-import { getMockComponent } from '@alfa-client/test-utils';
+import { existsAsHtmlElement, getMockComponent, notExistsAsHtmlElement } from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { AttachmentWrapperComponent } from '@ods/system';
 import { createBinaryFileListResource, createBinaryFileResource } from 'libs/binary-file-shared/test/binary-file';
+import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent, MockDirective } from 'ng-mocks';
 import { BinaryFile2ContainerComponent } from '../../binary-file2-container/binary-file2-container.component';
 import { BinaryFileListOrientationDirective } from '../../directive/binary-file-list-orientation/binary-file-list-orientation.directive';
@@ -36,9 +38,11 @@ describe('BinaryFileListComponent', () => {
   let fixture: ComponentFixture<BinaryFileListComponent>;
 
   const binaryFile: BinaryFileResource = createBinaryFileResource();
-  const binaryFileListStateResource: StateResource<BinaryFileListResource> = createStateResource(
-    createBinaryFileListResource([binaryFile]),
-  );
+  function getBinaryFileListStateResource(binaryFiles: BinaryFileResource[]): StateResource<BinaryFileListResource> {
+    return createStateResource(createBinaryFileListResource(binaryFiles));
+  }
+
+  const wrapperSelector: string = getDataTestIdOf('binary-file-list-wrapper');
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
@@ -46,13 +50,14 @@ describe('BinaryFileListComponent', () => {
         BinaryFileListComponent,
         ToEmbeddedResourcesPipe,
         MockComponent(BinaryFile2ContainerComponent),
+        MockComponent(AttachmentWrapperComponent),
         MockDirective(BinaryFileListOrientationDirective),
       ],
     }).compileComponents();
 
     fixture = TestBed.createComponent(BinaryFileListComponent);
     component = fixture.componentInstance;
-    component.binaryFileListStateResource = binaryFileListStateResource;
+    component.binaryFileListStateResource = getBinaryFileListStateResource([binaryFile]);
     fixture.detectChanges();
   });
 
@@ -60,6 +65,22 @@ describe('BinaryFileListComponent', () => {
     expect(component).toBeTruthy();
   });
 
+  describe('template', () => {
+    describe('attachment wrapper', () => {
+      it('should show', () => {
+        existsAsHtmlElement(fixture, wrapperSelector);
+      });
+
+      it('should hide', () => {
+        component.binaryFileListStateResource = getBinaryFileListStateResource([]);
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, wrapperSelector);
+      });
+    });
+  });
+
   describe('binary file container', () => {
     it('should be called with file', () => {
       const binaryFileContainerComponent: BinaryFile2ContainerComponent = getMockComponent<BinaryFile2ContainerComponent>(
diff --git a/alfa-client/libs/binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive.ts b/alfa-client/libs/binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive.ts
index 3a1a42958aca047046c5aa29edaed15dc77a1705..956be5722cdcd4966e12c8a5216bfb0dde53d706 100644
--- a/alfa-client/libs/binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive.ts
+++ b/alfa-client/libs/binary-file/src/lib/directive/binary-file-list-orientation/binary-file-list-orientation.directive.ts
@@ -1,7 +1,7 @@
 import { Directive, ElementRef, Input } from '@angular/core';
 
 export const _verticalClasses: string[] = ['flex', 'flex-col'];
-export const _horizontalClasses: string[] = ['flex', 'flex-row', 'flex-wrap'];
+export const _horizontalClasses: string[] = ['flex', 'flex-wrap', 'gap-2'];
 
 export enum BinaryFileListOrientation {
   HORIZONTAL = 'horizontal',
diff --git a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.html b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.html
index 1bfa1fb53740999476b2e6b342777abec551f000..4024dc2de95e58d010447f113834a2b1b0387252 100644
--- a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.html
+++ b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.html
@@ -4,10 +4,12 @@
   [attr.data-test-id]="(label | convertForDataTest) + '-file-upload-button'"
   [multi]="true"
   [isLoading]="isUploadInProgress$ | async"
-  class="relative w-72"
+  [variant]="uploadButtonVariant"
   data-test-id="binary-file-upload"
 >
   <ods-spinner-icon spinner size="medium" />
   <ods-attachment-icon icon size="medium" />
-  <p text class="text-center">{{ label }}</p>
+  @if (label) {
+    <p text data-test-id="upload-button-label" class="text-center">{{ label }}</p>
+  }
 </ods-file-upload-button>
diff --git a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.spec.ts b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.spec.ts
index dc42e69a0f52518ba01f5f3ddf2009ef04e344e9..38303a464c9f128eb05963f94df756663567e129 100644
--- a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.spec.ts
+++ b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.spec.ts
@@ -1,11 +1,17 @@
 import { BinaryFileService, FileUploadType, ToUploadFile } from '@alfa-client/binary-file-shared';
 import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
-import { existsAsHtmlElement, getElementComponentFromFixtureByCss, mock, Mock } from '@alfa-client/test-utils';
+import {
+  existsAsHtmlElement,
+  getElementComponentFromFixtureByCss,
+  mock,
+  Mock,
+  notExistsAsHtmlElement,
+} from '@alfa-client/test-utils';
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 import { faker } from '@faker-js/faker/.';
 import { expect } from '@jest/globals';
 import { getUrl, Resource } from '@ngxp/rest';
-import { FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
+import { FileUploadButtonComponent, SpinnerIconComponent, UploadButtonVariants } from '@ods/system';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { MockComponent } from 'ng-mocks';
 import { of } from 'rxjs';
@@ -23,6 +29,7 @@ describe('MultiFileUploadEditorComponent', () => {
   const uploadResource: Resource = createDummyResource([uploadLinkRel]);
 
   const buttonTestId: string = getDataTestIdOf('Ein_Label-file-upload-button');
+  const buttonLabelTestId: string = getDataTestIdOf('upload-button-label');
 
   let binaryFileService: Mock<BinaryFileService>;
 
@@ -104,6 +111,24 @@ describe('MultiFileUploadEditorComponent', () => {
         } as ToUploadFile);
       });
     });
+
+    describe('get uploadButtonVariant', () => {
+      it('should return "label"', () => {
+        component.label = 'test';
+
+        const result: UploadButtonVariants['variant'] = component.uploadButtonVariant;
+
+        expect(result).toBe('label');
+      });
+
+      it('should return "icon"', () => {
+        component.label = '';
+
+        const result: UploadButtonVariants['variant'] = component.uploadButtonVariant;
+
+        expect(result).toBe('icon');
+      });
+    });
   });
 
   describe('template', () => {
@@ -125,5 +150,22 @@ describe('MultiFileUploadEditorComponent', () => {
         expect(fileButtonComponent.isLoading).toEqual(true);
       });
     });
+    describe('upload button label', () => {
+      it('should show', () => {
+        component.label = 'test';
+
+        fixture.detectChanges();
+
+        existsAsHtmlElement(fixture, buttonLabelTestId);
+      });
+
+      it('should hide', () => {
+        component.label = '';
+
+        fixture.detectChanges();
+
+        notExistsAsHtmlElement(fixture, buttonLabelTestId);
+      });
+    });
   });
 });
diff --git a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.ts b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.ts
index 4c057b3f3d7b52b25dc63164e62f06bb054b83c8..2a9623612015f5350b39822c605c8faed1903d59 100644
--- a/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.ts
+++ b/alfa-client/libs/binary-file/src/lib/multi-file-upload-editor/multi-file-upload-editor.component.ts
@@ -5,7 +5,7 @@ import { AsyncPipe } from '@angular/common';
 import { Component, HostListener, inject, Input, OnInit } from '@angular/core';
 import { ControlContainer, FormGroupDirective, ReactiveFormsModule } from '@angular/forms';
 import { getUrl, Resource } from '@ngxp/rest';
-import { AttachmentIconComponent, FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
+import { AttachmentIconComponent, FileUploadButtonComponent, SpinnerIconComponent, UploadButtonVariants } from '@ods/system';
 import { uniqueId } from 'lodash-es';
 import { Observable } from 'rxjs';
 
@@ -55,4 +55,8 @@ export class MultiFileUploadEditorComponent implements OnInit {
       });
     }
   }
+
+  get uploadButtonVariant(): UploadButtonVariants['variant'] {
+    return this.label ? 'label' : 'icon';
+  }
 }
diff --git a/alfa-client/libs/binary-file/src/lib/multi-file-upload/multi-file-upload.component.html b/alfa-client/libs/binary-file/src/lib/multi-file-upload/multi-file-upload.component.html
index 184ac868f9f594da443f6f89b969ce1cc85b1dfc..8efd002c007d46dba8fc79c2526e59e132191c66 100644
--- a/alfa-client/libs/binary-file/src/lib/multi-file-upload/multi-file-upload.component.html
+++ b/alfa-client/libs/binary-file/src/lib/multi-file-upload/multi-file-upload.component.html
@@ -1,13 +1,15 @@
-<ods-file-upload-list-container
-  [parentFormArrayName]="filesFormFieldName"
-  [fileUploadType]="fileUploadType"
-  [filesResource]="filesResource"
-  [filesLinkRel]="filesLinkRelation"
-  data-test-id="file-list"
-></ods-file-upload-list-container>
-<ods-multi-file-upload-editor
-  [fileUploadType]="fileUploadType"
-  [uploadResource]="uploadResource"
-  [uploadLinkRelation]="uploadLinkRelation"
-  data-test-id="multi-file-upload-editor"
-></ods-multi-file-upload-editor>
\ No newline at end of file
+<div class="flex flex-col gap-2">
+  <ods-file-upload-list-container
+    [parentFormArrayName]="filesFormFieldName"
+    [fileUploadType]="fileUploadType"
+    [filesResource]="filesResource"
+    [filesLinkRel]="filesLinkRelation"
+    data-test-id="file-list"
+  />
+  <ods-multi-file-upload-editor
+    [fileUploadType]="fileUploadType"
+    [uploadResource]="uploadResource"
+    [uploadLinkRelation]="uploadLinkRelation"
+    data-test-id="multi-file-upload-editor"
+  />
+</div>
diff --git a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts
index a62e384fb3c9ff9c15b453cc9927438d1e1790c4..7de4a0bf3fc04340fa80daed1896235559f6dd18 100644
--- a/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts
+++ b/alfa-client/libs/design-component/src/lib/form/single-file-upload-editor/single-file-upload-editor.component.ts
@@ -24,7 +24,7 @@
 import { ConvertForDataTestPipe, isNotNil } from '@alfa-client/tech-shared';
 import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core';
 import { ReactiveFormsModule } from '@angular/forms';
-import { FileUploadButtonComponent, SpinnerIconComponent } from '@ods/system';
+import { FileUploadButtonComponent } from '@ods/system';
 import { uniqueId } from 'lodash-es';
 import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstract.component';
 
@@ -32,7 +32,8 @@ import { FormControlEditorAbstractComponent } from '../formcontrol-editor.abstra
   selector: 'ods-single-file-upload-editor',
   templateUrl: './single-file-upload-editor.component.html',
   standalone: true,
-  imports: [FileUploadButtonComponent, SpinnerIconComponent, ReactiveFormsModule, ConvertForDataTestPipe],
+  styles: [':host {@apply contents}'],
+  imports: [FileUploadButtonComponent, ReactiveFormsModule, ConvertForDataTestPipe],
 })
 export class SingleFileUploadEditorComponent extends FormControlEditorAbstractComponent {
   @Input() label: string = '';
diff --git a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.html b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.html
index dc2b6cef68ea7358023c7791fea0eb6efbaf47bf..b65b88d5b02c74982b872549c6d87aeccdf1644b 100644
--- a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.html
+++ b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.html
@@ -34,14 +34,13 @@
   [multiple]="multi"
   [attr.data-test-id]="(id | convertForDataTest) + '-file-upload-input'"
 />
-<label
-  [for]="id"
-  class="z-10 inline-flex w-full flex-grow items-center justify-start gap-4 break-words rounded-md bg-background-50 py-3 pl-6 pr-6 text-text hover:bg-background-100 focus:outline-none focus:ring-2 focus:ring-primary peer-focus-visible:outline peer-focus-visible:outline-2 peer-focus-visible:outline-offset-2 peer-focus-visible:outline-ozgblue-800 peer-disabled:cursor-wait peer-disabled:hover:bg-background-50"
-  role="button"
->
-  <ng-content *ngIf="!isLoading" select="[icon]"></ng-content>
-  <ng-content *ngIf="isLoading" select="[spinner]"></ng-content>
-  <div class="flex-grow">
+<label [for]="id" [ngClass]="uploadButtonVariants({ variant })" role="button">
+  @if (isLoading) {
+    <ng-content select="[spinner]"></ng-content>
+  } @else {
+    <ng-content select="[icon]"></ng-content>
+  }
+  <div class="flex-grow empty:hidden">
     <ng-content select="[text]"></ng-content>
   </div>
 </label>
diff --git a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts
index 2371918f9cdba62e0ea0ee3a5e315ee9f1d9e378..b5048be11b1b7e67eaf8c077e3d4cd0caab66388 100644
--- a/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts
+++ b/alfa-client/libs/design-system/src/lib/form/file-upload-button/file-upload-button.component.ts
@@ -24,12 +24,33 @@
 import { ConvertForDataTestPipe } from '@alfa-client/tech-shared';
 import { CommonModule } from '@angular/common';
 import { Component, ElementRef, Input, ViewChild } from '@angular/core';
+import { cva, VariantProps } from 'class-variance-authority';
+
+export const uploadButtonVariants = cva(
+  [
+    'z-10 inline-flex flex-grow items-center justify-start gap-4 break-words rounded-md text-primary',
+    'border border-transparent hover:bg-ghost-hover peer-focus-visible:border-background-200',
+    'peer-focus-visible:outline peer-focus-visible:outline-focus peer-focus-visible:bg-ghost-hover peer-focus-visible:outline-offset-1',
+  ],
+  {
+    variants: {
+      variant: {
+        label: 'py-3 px-6 bg-background-50 w-full',
+        icon: 'p-2 w-fit',
+      },
+    },
+    defaultVariants: {
+      variant: 'label',
+    },
+  },
+);
+export type UploadButtonVariants = VariantProps<typeof uploadButtonVariants>;
 
 @Component({
   selector: 'ods-file-upload-button',
   standalone: true,
   imports: [CommonModule, ConvertForDataTestPipe],
-  styles: [':host {@apply inline-flex}'],
+  styles: [':host {@apply relative}'],
   templateUrl: './file-upload-button.component.html',
 })
 export class FileUploadButtonComponent {
@@ -37,9 +58,12 @@ export class FileUploadButtonComponent {
   @Input() isLoading: boolean = false;
   @Input() accept: string = '*/*';
   @Input() multi: boolean = false;
+  @Input() variant: UploadButtonVariants['variant'];
 
   @ViewChild('inputElement') inputElement: ElementRef = new ElementRef({});
 
+  readonly uploadButtonVariants = uploadButtonVariants;
+
   resetInput(): void {
     this.inputElement.nativeElement.value = '';
   }