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 c1bf50e0b5..b47eeb3ac7 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 { AbpLocalStorageService, ConfigStateService, @@ -32,13 +32,11 @@ export abstract class AuthFlowStrategy { protected sessionState: SessionStateService; protected localStorageService: AbpLocalStorageService; 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) => { @@ -55,6 +53,7 @@ export abstract class AuthFlowStrategy { this.localStorageService = injector.get(AbpLocalStorageService); this.oAuthConfig = this.environment.getEnvironment().oAuthConfig || {}; this.tenantKey = injector.get(TENANT_KEY); + this.router = injector.get(Router); this.listenToOauthErrors(); } @@ -71,6 +70,8 @@ export abstract class AuthFlowStrategy { .pipe(filter(event => event.type === 'token_refresh_error')) .subscribe(() => this.navigateToLogin()); + this.navigateToPreviousUrl(); + return this.oAuthService .loadDiscoveryDocument() .then(() => { @@ -83,6 +84,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()); } diff --git a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts index 4f833fe0f1..adbbba4ddf 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/handlers/error.handler.ts @@ -123,9 +123,11 @@ export class ErrorHandler { } private executeErrorHandler = (error: any) => { - const returnValue = this.httpErrorHandler(this.injector, error); + const errHandler = this.httpErrorHandler(this.injector, error); + const isObservable = errHandler instanceof Observable; + const response = isObservable ? errHandler : of(null); - return (returnValue instanceof Observable ? returnValue : of(null)).pipe( + return response.pipe( catchError(err => { this.handleError(err); return of(null); @@ -139,6 +141,11 @@ export class ErrorHandler { defaultValue: DEFAULT_ERROR_MESSAGES.defaultError.title, }; + if (err instanceof HttpErrorResponse && err.headers.get('Abp-Tenant-Resolve-Error')) { + this.authService.logout().subscribe(); + return; + } + if (err instanceof HttpErrorResponse && err.headers.get('_AbpErrorFormat')) { const confirmation$ = this.showErrorWithRequestBody(body); @@ -147,8 +154,6 @@ export class ErrorHandler { this.navigateToLogin(); }); } - } if(err instanceof HttpErrorResponse && err.headers.get('Abp-Tenant-Resolve-Error')){ - this.authService.logout().subscribe(); } else { switch (err.status) { case 401: @@ -178,7 +183,7 @@ export class ErrorHandler { status: 403, }); break; - case 404:{ + case 404: this.canCreateCustomError(404) ? this.show404Page() : this.showError( @@ -191,9 +196,7 @@ export class ErrorHandler { defaultValue: DEFAULT_ERROR_MESSAGES.defaultError404.title, }, ); - break; - } - + break; case 500: this.createErrorComponent({ title: {