diff --git a/apps/client/src/app/app.component.ts b/apps/client/src/app/app.component.ts
index ce94cbc7b..3daa9004e 100644
--- a/apps/client/src/app/app.component.ts
+++ b/apps/client/src/app/app.component.ts
@@ -66,28 +66,18 @@ export class AppComponent implements OnDestroy, OnInit {
         this.currentRoute = urlSegments[0].path;
       });
 
-    this.tokenStorageService
-      .onChangeHasToken()
+    this.userService.stateChanged
       .pipe(takeUntil(this.unsubscribeSubject))
-      .subscribe(() => {
-        this.isLoggedIn = !!this.tokenStorageService.getToken();
-
-        if (this.isLoggedIn) {
-          this.userService
-            .get()
-            .pipe(takeUntil(this.unsubscribeSubject))
-            .subscribe((user) => {
-              this.user = user;
-
-              this.canCreateAccount = hasPermission(
-                this.user.permissions,
-                permissions.createUserAccount
-              );
-
-              this.cd.markForCheck();
-            });
-        } else {
-          this.user = null;
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
+
+          this.canCreateAccount = hasPermission(
+            this.user.permissions,
+            permissions.createUserAccount
+          );
+
+          this.cd.markForCheck();
         }
       });
   }
diff --git a/apps/client/src/app/pages/about/about-page.component.ts b/apps/client/src/app/pages/about/about-page.component.ts
index ac5d50d29..0d9db45a5 100644
--- a/apps/client/src/app/pages/about/about-page.component.ts
+++ b/apps/client/src/app/pages/about/about-page.component.ts
@@ -1,6 +1,4 @@
 import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
-import { DataService } from '@ghostfolio/client/services/data.service';
-import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
 import { UserService } from '@ghostfolio/client/services/user/user.service';
 import { baseCurrency } from '@ghostfolio/common/config';
 import { User } from '@ghostfolio/common/interfaces';
@@ -28,8 +26,6 @@ export class AboutPageComponent implements OnInit {
    */
   public constructor(
     private cd: ChangeDetectorRef,
-    private dataService: DataService,
-    private tokenStorageService: TokenStorageService,
     private userService: UserService
   ) {}
 
@@ -37,22 +33,15 @@ export class AboutPageComponent implements OnInit {
    * Initializes the controller
    */
   public ngOnInit() {
-    this.isLoggedIn = !!this.tokenStorageService.getToken();
-
-    if (this.isLoggedIn)
-      this.tokenStorageService
-        .onChangeHasToken()
-        .pipe(takeUntil(this.unsubscribeSubject))
-        .subscribe(() => {
-          this.userService
-            .get()
-            .pipe(takeUntil(this.unsubscribeSubject))
-            .subscribe((user) => {
-              this.user = user;
-
-              this.cd.markForCheck();
-            });
-        });
+    this.userService.stateChanged
+      .pipe(takeUntil(this.unsubscribeSubject))
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
+
+          this.cd.markForCheck();
+        }
+      });
   }
 
   public ngOnDestroy() {
diff --git a/apps/client/src/app/pages/account/account-page.component.ts b/apps/client/src/app/pages/account/account-page.component.ts
index 9f4535e22..fb25010c9 100644
--- a/apps/client/src/app/pages/account/account-page.component.ts
+++ b/apps/client/src/app/pages/account/account-page.component.ts
@@ -1,6 +1,5 @@
 import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
 import { DataService } from '@ghostfolio/client/services/data.service';
-import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
 import { UserService } from '@ghostfolio/client/services/user/user.service';
 import { DEFAULT_DATE_FORMAT } from '@ghostfolio/common/config';
 import { Access, User } from '@ghostfolio/common/interfaces';
@@ -31,7 +30,6 @@ export class AccountPageComponent implements OnDestroy, OnInit {
   public constructor(
     private cd: ChangeDetectorRef,
     private dataService: DataService,
-    private tokenStorageService: TokenStorageService,
     private userService: UserService
   ) {
     this.dataService
@@ -46,23 +44,19 @@ export class AccountPageComponent implements OnDestroy, OnInit {
         );
       });
 
-    this.tokenStorageService
-      .onChangeHasToken()
+    this.userService.stateChanged
       .pipe(takeUntil(this.unsubscribeSubject))
-      .subscribe(() => {
-        this.userService
-          .get()
-          .pipe(takeUntil(this.unsubscribeSubject))
-          .subscribe((user) => {
-            this.user = user;
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
 
-            this.hasPermissionToUpdateUserSettings = hasPermission(
-              this.user.permissions,
-              permissions.updateUserSettings
-            );
+          this.hasPermissionToUpdateUserSettings = hasPermission(
+            this.user.permissions,
+            permissions.updateUserSettings
+          );
 
-            this.cd.markForCheck();
-          });
+          this.cd.markForCheck();
+        }
       });
   }
 
diff --git a/apps/client/src/app/pages/accounts/accounts-page.component.ts b/apps/client/src/app/pages/accounts/accounts-page.component.ts
index cf631bc39..b86e8599b 100644
--- a/apps/client/src/app/pages/accounts/accounts-page.component.ts
+++ b/apps/client/src/app/pages/accounts/accounts-page.component.ts
@@ -5,7 +5,6 @@ import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto
 import { UpdateAccountDto } from '@ghostfolio/api/app/account/update-account.dto';
 import { DataService } from '@ghostfolio/client/services/data.service';
 import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
-import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
 import { UserService } from '@ghostfolio/client/services/user/user.service';
 import { User } from '@ghostfolio/common/interfaces';
 import { hasPermission, permissions } from '@ghostfolio/common/permissions';
@@ -43,7 +42,6 @@ export class AccountsPageComponent implements OnInit {
     private impersonationStorageService: ImpersonationStorageService,
     private route: ActivatedRoute,
     private router: Router,
-    private tokenStorageService: TokenStorageService,
     private userService: UserService
   ) {
     this.routeQueryParams = route.queryParams
@@ -77,27 +75,23 @@ export class AccountsPageComponent implements OnInit {
         this.hasImpersonationId = !!aId;
       });
 
-    this.tokenStorageService
-      .onChangeHasToken()
+    this.userService.stateChanged
       .pipe(takeUntil(this.unsubscribeSubject))
-      .subscribe(() => {
-        this.userService
-          .get()
-          .pipe(takeUntil(this.unsubscribeSubject))
-          .subscribe((user) => {
-            this.user = user;
-
-            this.hasPermissionToCreateAccount = hasPermission(
-              user.permissions,
-              permissions.createAccount
-            );
-            this.hasPermissionToDeleteAccount = hasPermission(
-              user.permissions,
-              permissions.deleteAccount
-            );
-
-            this.cd.markForCheck();
-          });
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
+
+          this.hasPermissionToCreateAccount = hasPermission(
+            this.user.permissions,
+            permissions.createAccount
+          );
+          this.hasPermissionToDeleteAccount = hasPermission(
+            this.user.permissions,
+            permissions.deleteAccount
+          );
+
+          this.cd.markForCheck();
+        }
       });
 
     this.fetchAccounts();
diff --git a/apps/client/src/app/pages/admin/admin-page.component.ts b/apps/client/src/app/pages/admin/admin-page.component.ts
index 1b25c50fc..c715983d8 100644
--- a/apps/client/src/app/pages/admin/admin-page.component.ts
+++ b/apps/client/src/app/pages/admin/admin-page.component.ts
@@ -2,7 +2,6 @@ import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
 import { AdminService } from '@ghostfolio/client/services/admin.service';
 import { CacheService } from '@ghostfolio/client/services/cache.service';
 import { DataService } from '@ghostfolio/client/services/data.service';
-import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
 import { UserService } from '@ghostfolio/client/services/user/user.service';
 import { DEFAULT_DATE_FORMAT } from '@ghostfolio/common/config';
 import { AdminData, User } from '@ghostfolio/common/interfaces';
@@ -35,7 +34,6 @@ export class AdminPageComponent implements OnInit {
     private cacheService: CacheService,
     private cd: ChangeDetectorRef,
     private dataService: DataService,
-    private tokenStorageService: TokenStorageService,
     private userService: UserService
   ) {}
 
@@ -45,16 +43,12 @@ export class AdminPageComponent implements OnInit {
   public ngOnInit() {
     this.fetchAdminData();
 
-    this.tokenStorageService
-      .onChangeHasToken()
+    this.userService.stateChanged
       .pipe(takeUntil(this.unsubscribeSubject))
-      .subscribe(() => {
-        this.userService
-          .get()
-          .pipe(takeUntil(this.unsubscribeSubject))
-          .subscribe((user) => {
-            this.user = user;
-          });
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
+        }
       });
   }
 
diff --git a/apps/client/src/app/pages/analysis/analysis-page.component.ts b/apps/client/src/app/pages/analysis/analysis-page.component.ts
index 2fffa14a7..7d68b6f12 100644
--- a/apps/client/src/app/pages/analysis/analysis-page.component.ts
+++ b/apps/client/src/app/pages/analysis/analysis-page.component.ts
@@ -2,7 +2,6 @@ import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
 import { ToggleOption } from '@ghostfolio/client/components/toggle/interfaces/toggle-option.type';
 import { DataService } from '@ghostfolio/client/services/data.service';
 import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
-import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
 import { UserService } from '@ghostfolio/client/services/user/user.service';
 import {
   PortfolioItem,
@@ -45,7 +44,6 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
     private dataService: DataService,
     private deviceService: DeviceDetectorService,
     private impersonationStorageService: ImpersonationStorageService,
-    private tokenStorageService: TokenStorageService,
     private userService: UserService
   ) {}
 
@@ -81,18 +79,14 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
         this.cd.markForCheck();
       });
 
-    this.tokenStorageService
-      .onChangeHasToken()
+    this.userService.stateChanged
       .pipe(takeUntil(this.unsubscribeSubject))
-      .subscribe(() => {
-        this.userService
-          .get()
-          .pipe(takeUntil(this.unsubscribeSubject))
-          .subscribe((user) => {
-            this.user = user;
-
-            this.cd.markForCheck();
-          });
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
+
+          this.cd.markForCheck();
+        }
       });
   }
 
diff --git a/apps/client/src/app/pages/home/home-page.component.ts b/apps/client/src/app/pages/home/home-page.component.ts
index faec629f4..df1f1397e 100644
--- a/apps/client/src/app/pages/home/home-page.component.ts
+++ b/apps/client/src/app/pages/home/home-page.component.ts
@@ -10,7 +10,6 @@ import {
   RANGE,
   SettingsStorageService
 } from '@ghostfolio/client/services/settings-storage.service';
-import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
 import { UserService } from '@ghostfolio/client/services/user/user.service';
 import {
   PortfolioOverview,
@@ -67,7 +66,6 @@ export class HomePageComponent implements OnDestroy, OnInit {
     private route: ActivatedRoute,
     private router: Router,
     private settingsStorageService: SettingsStorageService,
-    private tokenStorageService: TokenStorageService,
     private userService: UserService
   ) {
     this.routeQueryParams = this.route.queryParams
@@ -78,39 +76,35 @@ export class HomePageComponent implements OnDestroy, OnInit {
         }
       });
 
-    this.tokenStorageService
-      .onChangeHasToken()
+    this.userService.stateChanged
       .pipe(takeUntil(this.unsubscribeSubject))
-      .subscribe(() => {
-        this.userService
-          .get()
-          .pipe(takeUntil(this.unsubscribeSubject))
-          .subscribe((user) => {
-            this.user = user;
-
-            this.hasPermissionToAccessFearAndGreedIndex = hasPermission(
-              user.permissions,
-              permissions.accessFearAndGreedIndex
-            );
-
-            if (this.hasPermissionToAccessFearAndGreedIndex) {
-              this.dataService
-                .fetchSymbolItem('GF.FEAR_AND_GREED_INDEX')
-                .pipe(takeUntil(this.unsubscribeSubject))
-                .subscribe(({ marketPrice }) => {
-                  this.fearAndGreedIndex = marketPrice;
-
-                  this.cd.markForCheck();
-                });
-            }
-
-            this.hasPermissionToReadForeignPortfolio = hasPermission(
-              user.permissions,
-              permissions.readForeignPortfolio
-            );
-
-            this.cd.markForCheck();
-          });
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
+
+          this.hasPermissionToAccessFearAndGreedIndex = hasPermission(
+            this.user.permissions,
+            permissions.accessFearAndGreedIndex
+          );
+
+          if (this.hasPermissionToAccessFearAndGreedIndex) {
+            this.dataService
+              .fetchSymbolItem('GF.FEAR_AND_GREED_INDEX')
+              .pipe(takeUntil(this.unsubscribeSubject))
+              .subscribe(({ marketPrice }) => {
+                this.fearAndGreedIndex = marketPrice;
+
+                this.cd.markForCheck();
+              });
+          }
+
+          this.hasPermissionToReadForeignPortfolio = hasPermission(
+            this.user.permissions,
+            permissions.readForeignPortfolio
+          );
+
+          this.cd.markForCheck();
+        }
       });
   }
 
diff --git a/apps/client/src/app/pages/pricing/pricing-page.component.ts b/apps/client/src/app/pages/pricing/pricing-page.component.ts
index 135d30249..650baa890 100644
--- a/apps/client/src/app/pages/pricing/pricing-page.component.ts
+++ b/apps/client/src/app/pages/pricing/pricing-page.component.ts
@@ -1,6 +1,4 @@
 import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
-import { DataService } from '@ghostfolio/client/services/data.service';
-import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
 import { UserService } from '@ghostfolio/client/services/user/user.service';
 import { baseCurrency } from '@ghostfolio/common/config';
 import { User } from '@ghostfolio/common/interfaces';
@@ -24,8 +22,6 @@ export class PricingPageComponent implements OnInit {
    */
   public constructor(
     private cd: ChangeDetectorRef,
-    private dataService: DataService,
-    private tokenStorageService: TokenStorageService,
     private userService: UserService
   ) {}
 
@@ -33,22 +29,15 @@ export class PricingPageComponent implements OnInit {
    * Initializes the controller
    */
   public ngOnInit() {
-    this.isLoggedIn = !!this.tokenStorageService.getToken();
+    this.userService.stateChanged
+      .pipe(takeUntil(this.unsubscribeSubject))
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
 
-    if (this.isLoggedIn)
-      this.tokenStorageService
-        .onChangeHasToken()
-        .pipe(takeUntil(this.unsubscribeSubject))
-        .subscribe(() => {
-          this.userService
-            .get()
-            .pipe(takeUntil(this.unsubscribeSubject))
-            .subscribe((user) => {
-              this.user = user;
-
-              this.cd.markForCheck();
-            });
-        });
+          this.cd.markForCheck();
+        }
+      });
   }
 
   public ngOnDestroy() {
diff --git a/apps/client/src/app/pages/transactions/transactions-page.component.ts b/apps/client/src/app/pages/transactions/transactions-page.component.ts
index f1e3a3951..ba38adfac 100644
--- a/apps/client/src/app/pages/transactions/transactions-page.component.ts
+++ b/apps/client/src/app/pages/transactions/transactions-page.component.ts
@@ -5,7 +5,6 @@ import { CreateOrderDto } from '@ghostfolio/api/app/order/create-order.dto';
 import { UpdateOrderDto } from '@ghostfolio/api/app/order/update-order.dto';
 import { DataService } from '@ghostfolio/client/services/data.service';
 import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
-import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
 import { UserService } from '@ghostfolio/client/services/user/user.service';
 import { User } from '@ghostfolio/common/interfaces';
 import { hasPermission, permissions } from '@ghostfolio/common/permissions';
@@ -43,7 +42,6 @@ export class TransactionsPageComponent implements OnInit {
     private impersonationStorageService: ImpersonationStorageService,
     private route: ActivatedRoute,
     private router: Router,
-    private tokenStorageService: TokenStorageService,
     private userService: UserService
   ) {
     this.routeQueryParams = route.queryParams
@@ -77,27 +75,23 @@ export class TransactionsPageComponent implements OnInit {
         this.hasImpersonationId = !!aId;
       });
 
-    this.tokenStorageService
-      .onChangeHasToken()
+    this.userService.stateChanged
       .pipe(takeUntil(this.unsubscribeSubject))
-      .subscribe(() => {
-        this.userService
-          .get()
-          .pipe(takeUntil(this.unsubscribeSubject))
-          .subscribe((user) => {
-            this.user = user;
-
-            this.hasPermissionToCreateOrder = hasPermission(
-              user.permissions,
-              permissions.createOrder
-            );
-            this.hasPermissionToDeleteOrder = hasPermission(
-              user.permissions,
-              permissions.deleteOrder
-            );
-
-            this.cd.markForCheck();
-          });
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
+
+          this.hasPermissionToCreateOrder = hasPermission(
+            this.user.permissions,
+            permissions.createOrder
+          );
+          this.hasPermissionToDeleteOrder = hasPermission(
+            this.user.permissions,
+            permissions.deleteOrder
+          );
+
+          this.cd.markForCheck();
+        }
       });
 
     this.fetchOrders();
diff --git a/apps/client/src/app/pages/zen/zen-page.component.ts b/apps/client/src/app/pages/zen/zen-page.component.ts
index 6781e9ad0..83596f7fe 100644
--- a/apps/client/src/app/pages/zen/zen-page.component.ts
+++ b/apps/client/src/app/pages/zen/zen-page.component.ts
@@ -2,7 +2,6 @@ import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
 import { LineChartItem } from '@ghostfolio/client/components/line-chart/interfaces/line-chart.interface';
 import { DataService } from '@ghostfolio/client/services/data.service';
 import { ImpersonationStorageService } from '@ghostfolio/client/services/impersonation-storage.service';
-import { TokenStorageService } from '@ghostfolio/client/services/token-storage.service';
 import { UserService } from '@ghostfolio/client/services/user/user.service';
 import { PortfolioPerformance, User } from '@ghostfolio/common/interfaces';
 import { hasPermission, permissions } from '@ghostfolio/common/permissions';
@@ -36,26 +35,21 @@ export class ZenPageComponent implements OnDestroy, OnInit {
     private dataService: DataService,
     private deviceService: DeviceDetectorService,
     private impersonationStorageService: ImpersonationStorageService,
-    private tokenStorageService: TokenStorageService,
     private userService: UserService
   ) {
-    this.tokenStorageService
-      .onChangeHasToken()
+    this.userService.stateChanged
       .pipe(takeUntil(this.unsubscribeSubject))
-      .subscribe(() => {
-        this.userService
-          .get()
-          .pipe(takeUntil(this.unsubscribeSubject))
-          .subscribe((user) => {
-            this.user = user;
+      .subscribe((state) => {
+        if (state?.user) {
+          this.user = state.user;
 
-            this.hasPermissionToReadForeignPortfolio = hasPermission(
-              user.permissions,
-              permissions.readForeignPortfolio
-            );
+          this.hasPermissionToReadForeignPortfolio = hasPermission(
+            this.user.permissions,
+            permissions.readForeignPortfolio
+          );
 
-            this.cd.markForCheck();
-          });
+          this.cd.markForCheck();
+        }
       });
   }
 
diff --git a/apps/client/src/app/services/token-storage.service.ts b/apps/client/src/app/services/token-storage.service.ts
index 88fcbe221..9e7e47513 100644
--- a/apps/client/src/app/services/token-storage.service.ts
+++ b/apps/client/src/app/services/token-storage.service.ts
@@ -1,5 +1,4 @@
 import { Injectable } from '@angular/core';
-import { BehaviorSubject } from 'rxjs';
 
 const TOKEN_KEY = 'auth-token';
 
@@ -7,23 +6,15 @@ const TOKEN_KEY = 'auth-token';
   providedIn: 'root'
 })
 export class TokenStorageService {
-  private hasTokenChangeSubject = new BehaviorSubject<void>(null);
-
   public constructor() {}
 
   public getToken(): string {
     return window.localStorage.getItem(TOKEN_KEY);
   }
 
-  public onChangeHasToken() {
-    return this.hasTokenChangeSubject.asObservable();
-  }
-
   public saveToken(token: string): void {
     window.localStorage.removeItem(TOKEN_KEY);
     window.localStorage.setItem(TOKEN_KEY, token);
-
-    this.hasTokenChangeSubject.next();
   }
 
   public signOut(): void {
@@ -34,7 +25,5 @@ export class TokenStorageService {
     if (utmSource) {
       window.localStorage.setItem('utm_source', utmSource);
     }
-
-    this.hasTokenChangeSubject.next();
   }
 }