From 08914f7546050516a76491e77453b0f45b475478 Mon Sep 17 00:00:00 2001 From: Amelia <77553571+Fesaa@users.noreply.github.com> Date: Tue, 1 Jul 2025 20:22:17 +0200 Subject: [PATCH] Fix the login flashing sometimes Race condition between being able to login via OIDC in the background, and making first requests --- UI/Web/src/app/_resolvers/oidc.resolver.ts | 16 ++++++++++++++++ UI/Web/src/app/_services/oidc.service.ts | 10 ++++++---- UI/Web/src/app/app-routing.module.ts | 7 +++++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 UI/Web/src/app/_resolvers/oidc.resolver.ts diff --git a/UI/Web/src/app/_resolvers/oidc.resolver.ts b/UI/Web/src/app/_resolvers/oidc.resolver.ts new file mode 100644 index 000000000..9124cddec --- /dev/null +++ b/UI/Web/src/app/_resolvers/oidc.resolver.ts @@ -0,0 +1,16 @@ +import {ActivatedRouteSnapshot, Resolve, RouterStateSnapshot} from '@angular/router'; +import {Injectable} from "@angular/core"; +import {Observable, take} from "rxjs"; +import {OidcService} from "../_services/oidc.service"; + +@Injectable({ + providedIn: 'root' +}) +export class OidcResolver implements Resolve { + + constructor(private oidcService: OidcService) {} + + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable { + return this.oidcService.loaded$.pipe(take(1)); + } +} diff --git a/UI/Web/src/app/_services/oidc.service.ts b/UI/Web/src/app/_services/oidc.service.ts index 1efaeb348..e66c93cc2 100644 --- a/UI/Web/src/app/_services/oidc.service.ts +++ b/UI/Web/src/app/_services/oidc.service.ts @@ -1,6 +1,6 @@ import {DestroyRef, effect, inject, Injectable, signal} from '@angular/core'; import {OAuthErrorEvent, OAuthService} from "angular-oauth2-oidc"; -import {BehaviorSubject, from} from "rxjs"; +import {BehaviorSubject, from, Observable} from "rxjs"; import {HttpClient} from "@angular/common/http"; import {environment} from "../../environments/environment"; import {OidcPublicConfig} from "../admin/_models/oidc-config"; @@ -23,6 +23,8 @@ export class OidcService { baseUrl = environment.apiUrl; + private readonly loaded = new BehaviorSubject(false); + public readonly loaded$: Observable = this.loaded.asObservable(); private readonly _ready = signal(false); public readonly ready = this._ready.asReadonly(); private readonly _settings = signal(undefined); @@ -42,6 +44,7 @@ export class OidcService { this.config().subscribe(oidcSetting => { if (!oidcSetting.authority) { + this.loaded.next(true); return } @@ -72,9 +75,8 @@ export class OidcService { }); from(this.oauth2.loadDiscoveryDocumentAndTryLogin()).subscribe({ - next: success => { - if (!success) return; - + next: _ => { + this.loaded.next(true); this._ready.set(true); }, error: error => { diff --git a/UI/Web/src/app/app-routing.module.ts b/UI/Web/src/app/app-routing.module.ts index e03c924a1..bdbe6e831 100644 --- a/UI/Web/src/app/app-routing.module.ts +++ b/UI/Web/src/app/app-routing.module.ts @@ -2,12 +2,19 @@ import {NgModule} from '@angular/core'; import {PreloadAllModules, RouterModule, Routes} from '@angular/router'; import {AuthGuard} from './_guards/auth.guard'; import {LibraryAccessGuard} from './_guards/library-access.guard'; +import {OidcResolver} from "./_resolvers/oidc.resolver"; const routes: Routes = [ { path: '', canActivate: [AuthGuard], runGuardsAndResolvers: 'always', + resolve: { + // Require OIDC discovery to be loaded before launching the app + // making sure we don't flash the login screen because we've made request before we could auto login + // If no OIDC is set up, this will resolve after one request to the backend + _: OidcResolver, + }, children: [ { path: 'settings',