diff --git a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts index de98878b0f..66cf601e3b 100644 --- a/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/config-state.service.ts @@ -61,6 +61,7 @@ export class ConfigStateService { return this.getlocalizationResource(cultureName).pipe( map(result => ({ ...appState, localization: { ...appState.localization, ...result } })), + tap(() => (this.uiCultureFromAuthCodeFlow = undefined)), ); } diff --git a/npm/ng-packs/packages/core/src/lib/services/window.service.ts b/npm/ng-packs/packages/core/src/lib/services/window.service.ts index 522bb19c94..6534065d0d 100644 --- a/npm/ng-packs/packages/core/src/lib/services/window.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/window.service.ts @@ -3,9 +3,9 @@ import { DOCUMENT } from '@angular/common'; @Injectable({ providedIn: 'root' }) export class AbpWindowService { - protected readonly document = inject(DOCUMENT); - protected readonly window = this.document.defaultView; - protected readonly navigator = this.window.navigator; + public readonly document = inject(DOCUMENT); + public readonly window = this.document.defaultView; + public readonly navigator = this.window.navigator; copyToClipboard(text: string): Promise { return this.navigator.clipboard.writeText(text); diff --git a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts index 3d33d4325a..4c239ac5e3 100644 --- a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts +++ b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-code-flow-strategy.ts @@ -1,6 +1,6 @@ import { noop } from '@abp/ng.core'; import { Params } from '@angular/router'; -import { filter, from, of, tap } from 'rxjs'; +import { filter, from, of, take, tap } from 'rxjs'; import { AuthFlowStrategy } from './auth-flow-strategy'; import { isTokenExpired } from '../utils'; @@ -9,7 +9,7 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy { async init() { this.checkRememberMeOption(); - this.setUICulture(); + this.listenToTokenReceived(); return super .init() @@ -35,6 +35,46 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy { } } + private getCultureParams(queryParams?: Params) { + const lang = this.sessionState.getLanguage(); + const culture = { culture: lang, 'ui-culture': lang }; + return { ...(lang && culture), ...queryParams }; + } + + protected setUICulture() { + const urlParams = new URLSearchParams(window.location.search); + this.configState.uiCultureFromAuthCodeFlow = urlParams.get('ui-culture'); + } + + protected replaceURLParams() { + const location = this.windowService.window.location; + const history = this.windowService.window.history; + + const href = + location.origin + + location.pathname + + location.search + .replace(/iss=[^&$]*/, '') + .replace(/culture=[^&$]*/, '') + .replace(/ui-culture=[^&$]*/, '') + + location.hash; + + history.replaceState(null, '', href); + } + + protected listenToTokenReceived() { + this.oAuthService.events + .pipe( + filter(event => event.type === 'token_received'), + tap(() => { + this.setUICulture(); + this.replaceURLParams(); + }), + take(1), + ) + .subscribe(); + } + navigateToLogin(queryParams?: Params) { let additionalState = ''; if (queryParams?.returnUrl) { @@ -63,23 +103,4 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy { this.oAuthService.initCodeFlow('', this.getCultureParams(queryParams)); return of(null); } - - private getCultureParams(queryParams?: Params) { - const lang = this.sessionState.getLanguage(); - const culture = { culture: lang, 'ui-culture': lang }; - return { ...(lang && culture), ...queryParams }; - } - - private setUICulture() { - this.oAuthService.events - .pipe( - filter(event => event.type === 'token_received'), - tap(e => { - const urlParams = new URLSearchParams(window.location.search); - this.configState.uiCultureFromAuthCodeFlow = urlParams.get('ui-culture'); - window.history.replaceState(null, '', window.location.pathname); - }), - ) - .subscribe(); - } } diff --git a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts index dd7958b023..02e5dd4ea3 100644 --- a/npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts +++ b/npm/ng-packs/packages/oauth/src/lib/strategies/auth-flow-strategy.ts @@ -13,6 +13,7 @@ import { import { AbpLocalStorageService, + AbpWindowService, ConfigStateService, EnvironmentService, HttpErrorReporterService, @@ -38,6 +39,7 @@ export abstract class AuthFlowStrategy { protected sessionState: SessionStateService; protected localStorageService: AbpLocalStorageService; protected rememberMeService: RememberMeService; + protected windowService: AbpWindowService; protected tenantKey: string; protected router: Router; @@ -65,6 +67,7 @@ export abstract class AuthFlowStrategy { this.router = injector.get(Router); this.oAuthErrorFilterService = injector.get(OAuthErrorFilterService); this.rememberMeService = injector.get(RememberMeService); + this.windowService = injector.get(AbpWindowService); this.listenToOauthErrors(); }