From a080ebc69ea82fb397fbdb1a19c5e1b4f3290cdb Mon Sep 17 00:00:00 2001 From: Fahri Gedik Date: Fri, 25 Jul 2025 15:33:21 +0300 Subject: [PATCH] Add async auth guard support for OAuth routes Introduced asyncAuthGuard and asyncAbpOAuthGuard to enable asynchronous authentication checks, particularly for OAuth flows involving code exchange. Updated app routes and OAuth module provider to use the new async guards where appropriate. --- .../core/src/lib/abstracts/auth.guard.ts | 6 ++++ .../oauth/src/lib/guards/oauth.guard.ts | 32 ++++++++++++++++++- .../providers/oauth-module-config.provider.ts | 7 +++- 3 files changed, 43 insertions(+), 2 deletions(-) diff --git a/npm/ng-packs/packages/core/src/lib/abstracts/auth.guard.ts b/npm/ng-packs/packages/core/src/lib/abstracts/auth.guard.ts index 50473e4df1..020f750555 100644 --- a/npm/ng-packs/packages/core/src/lib/abstracts/auth.guard.ts +++ b/npm/ng-packs/packages/core/src/lib/abstracts/auth.guard.ts @@ -21,3 +21,9 @@ export const authGuard: CanActivateFn = () => { console.error('You should add @abp/ng-oauth packages or create your own auth packages.'); return false; }; + + +export const asyncAuthGuard: CanActivateFn = () => { + console.error('You should add @abp/ng-oauth packages or create your own auth packages.'); + return false; +}; \ No newline at end of file diff --git a/npm/ng-packs/packages/oauth/src/lib/guards/oauth.guard.ts b/npm/ng-packs/packages/oauth/src/lib/guards/oauth.guard.ts index 6f751804cd..e7f31643aa 100644 --- a/npm/ng-packs/packages/oauth/src/lib/guards/oauth.guard.ts +++ b/npm/ng-packs/packages/oauth/src/lib/guards/oauth.guard.ts @@ -6,7 +6,7 @@ import { CanActivateFn, } from '@angular/router'; -import { Observable } from 'rxjs'; +import { Observable, interval, filter, take, map, firstValueFrom, timeout, catchError, of } from 'rxjs'; import { OAuthService } from 'angular-oauth2-oidc'; import { AuthService, IAbpGuard } from '@abp/ng.core'; @@ -53,3 +53,33 @@ export const abpOAuthGuard: CanActivateFn = ( authService.navigateToLogin(params); return false; }; + +export const asyncAbpOAuthGuard: CanActivateFn = ( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot, +) => { + const authService = inject(AuthService); + const code = new URLSearchParams(window.location.search).get('code'); + + if (code) { + return firstValueFrom( + interval(100).pipe( + map(() => authService.isAuthenticated), + filter(isAuthenticated => isAuthenticated), + take(1), + timeout(3000), + catchError(() => { + authService.navigateToLogin({ returnUrl: state.url }); + return of(false); + }) + ) + ); + } + + if (authService.isAuthenticated) { + return true; + } + + authService.navigateToLogin({ returnUrl: state.url }); + return false; +}; diff --git a/npm/ng-packs/packages/oauth/src/lib/providers/oauth-module-config.provider.ts b/npm/ng-packs/packages/oauth/src/lib/providers/oauth-module-config.provider.ts index 92ecc86012..534882dd13 100644 --- a/npm/ng-packs/packages/oauth/src/lib/providers/oauth-module-config.provider.ts +++ b/npm/ng-packs/packages/oauth/src/lib/providers/oauth-module-config.provider.ts @@ -2,6 +2,7 @@ import { AuthService, AuthGuard, authGuard, + asyncAuthGuard, ApiInterceptor, PIPE_TO_LOGIN_FN_KEY, CHECK_AUTHENTICATION_STATE_FN_KEY, @@ -11,7 +12,7 @@ import { import { Provider, makeEnvironmentProviders, inject, provideAppInitializer } from '@angular/core'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { OAuthModule, OAuthStorage } from 'angular-oauth2-oidc'; -import { AbpOAuthGuard, abpOAuthGuard } from '../guards'; +import { AbpOAuthGuard, abpOAuthGuard, asyncAbpOAuthGuard, } from '../guards'; import { OAuthConfigurationHandler } from '../handlers'; import { OAuthApiInterceptor } from '../interceptors'; import { AbpOAuthService, OAuthErrorFilterService } from '../services'; @@ -31,6 +32,10 @@ export function provideAbpOAuth() { { provide: authGuard, useValue: abpOAuthGuard, + }, + { + provide: asyncAuthGuard, + useValue: asyncAbpOAuthGuard, }, { provide: ApiInterceptor,