diff --git a/npm/ng-packs/packages/identity/ng-package.json b/npm/ng-packs/packages/identity/ng-package.json index a0824f39e5..68f95303e4 100644 --- a/npm/ng-packs/packages/identity/ng-package.json +++ b/npm/ng-packs/packages/identity/ng-package.json @@ -6,6 +6,7 @@ }, "allowedNonPeerDependencies": [ "@abp/ng.theme.shared", - "@abp/ng.permission-management" + "@abp/ng.permission-management", + "@abp/ng.components" ] } 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 357e861ba0..4b2d95af74 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 @@ -1,5 +1,5 @@ import { Injectable } from '@angular/core'; -import { CanActivate, UrlTree } from '@angular/router'; +import { CanActivate, UrlTree, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router'; import { OAuthService } from 'angular-oauth2-oidc'; import { Observable } from 'rxjs'; import { AuthService, IAuthGuard } from '@abp/ng.core'; @@ -10,13 +10,17 @@ import { AuthService, IAuthGuard } from '@abp/ng.core'; export class AbpOAuthGuard implements CanActivate, IAuthGuard { constructor(private oauthService: OAuthService, private authService: AuthService) {} - canActivate(): Observable | boolean | UrlTree { + canActivate( + route: ActivatedRouteSnapshot, + state: RouterStateSnapshot, + ): Observable | boolean | UrlTree { const hasValidAccessToken = this.oauthService.hasValidAccessToken(); if (hasValidAccessToken) { return true; } - this.authService.navigateToLogin(); + const params = { returnUrl: state.url }; + this.authService.navigateToLogin(params); return false; } } 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 946d1295ca..184ef59dca 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 @@ -14,7 +14,10 @@ export class AuthCodeFlowStrategy extends AuthFlowStrategy { } navigateToLogin(queryParams?: Params) { - this.oAuthService.initCodeFlow('', this.getCultureParams(queryParams)); + const additionalState = queryParams.returnUrl; + const cultureParams = this.getCultureParams(queryParams); + + this.oAuthService.initCodeFlow(additionalState, cultureParams); } checkIfInternalAuth(queryParams?: Params) { 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 7a07cb8985..59315449b0 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 @@ -1,5 +1,5 @@ import { Injector } from '@angular/core'; -import { Params } from '@angular/router'; +import { Params, Router } from '@angular/router'; import { AuthConfig, OAuthErrorEvent, @@ -7,7 +7,7 @@ import { OAuthStorage, } from 'angular-oauth2-oidc'; import { Observable, of } from 'rxjs'; -import { filter, switchMap, tap } from 'rxjs/operators'; +import { filter, map, switchMap, take, tap } from 'rxjs/operators'; import { ConfigStateService, EnvironmentService, @@ -30,13 +30,11 @@ export abstract class AuthFlowStrategy { protected oAuthConfig!: AuthConfig; protected sessionState: SessionStateService; protected tenantKey: string; + protected router: Router; abstract checkIfInternalAuth(queryParams?: Params): boolean; - abstract navigateToLogin(queryParams?: Params): void; - abstract logout(queryParams?: Params): Observable; - abstract login(params?: LoginParams | Params): Observable; private catchError = (err: HttpErrorResponse) => { @@ -52,6 +50,7 @@ export abstract class AuthFlowStrategy { this.sessionState = injector.get(SessionStateService); this.oAuthConfig = this.environment.getEnvironment().oAuthConfig || {}; this.tenantKey = injector.get(TENANT_KEY); + this.router = injector.get(Router); this.listenToOauthErrors(); } @@ -68,6 +67,8 @@ export abstract class AuthFlowStrategy { .pipe(filter(event => event.type === 'token_refresh_error')) .subscribe(() => this.navigateToLogin()); + this.navigateToPreviousUrl(); + return this.oAuthService .loadDiscoveryDocument() .then(() => { @@ -80,6 +81,32 @@ export abstract class AuthFlowStrategy { .catch(this.catchError); } + protected navigateToPreviousUrl(): void { + const { responseType } = this.oAuthConfig; + if (responseType === 'code') { + this.oAuthService.events + .pipe( + filter(event => event.type === 'token_received' && !!this.oAuthService.state), + take(1), + map(() => { + const redirect_uri = decodeURIComponent(this.oAuthService.state); + + if (redirect_uri && redirect_uri !== '/') { + return redirect_uri; + } + return '/'; + }), + switchMap(redirectUri => + this.configState.getOne$('currentUser').pipe( + filter(user => !!user?.isAuthenticated), + tap(() => this.router.navigate([redirectUri])), + ), + ), + ) + .subscribe(); + } + } + protected refreshToken() { return this.oAuthService.refreshToken().catch(() => clearOAuthStorage()); }