From f841612e1c990b655c040cb96fab888992860bf8 Mon Sep 17 00:00:00 2001 From: Giuseppe Digilio Date: Wed, 4 Apr 2018 13:32:02 +0200 Subject: [PATCH] Added redirect to login whether token is expired --- src/app/core/auth/auth.effects.ts | 1 + src/app/core/auth/auth.interceptor.ts | 17 +++++++++++----- src/app/core/auth/auth.service.ts | 25 ++++++++++++++++++++---- src/app/core/auth/authenticated.guard.ts | 1 - 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/app/core/auth/auth.effects.ts b/src/app/core/auth/auth.effects.ts index ee0e8bf0c3..dcedbe0aec 100644 --- a/src/app/core/auth/auth.effects.ts +++ b/src/app/core/auth/auth.effects.ts @@ -134,6 +134,7 @@ export class AuthEffects { @Effect({dispatch: false}) public redirectToLogin: Observable = this.actions$ .ofType(AuthActionTypes.REDIRECT_TOKEN_EXPIRED, AuthActionTypes.REDIRECT_AUTHENTICATION_REQUIRED) + .do(() => this.authService.removeToken()) .do(() => this.authService.redirectToLogin()); /** diff --git a/src/app/core/auth/auth.interceptor.ts b/src/app/core/auth/auth.interceptor.ts index e5d7afc72d..45c41312a1 100644 --- a/src/app/core/auth/auth.interceptor.ts +++ b/src/app/core/auth/auth.interceptor.ts @@ -17,6 +17,7 @@ import { AuthTokenInfo } from './models/auth-token-info.model'; import { isNotEmpty, isUndefined } from '../../shared/empty.util'; import { RedirectWhenTokenExpiredAction, RefreshTokenAction } from './auth.actions'; import { Store } from '@ngrx/store'; +import { Router } from '@angular/router'; @Injectable() export class AuthInterceptor implements HttpInterceptor { @@ -26,7 +27,7 @@ export class AuthInterceptor implements HttpInterceptor { // we're creating a refresh token request list protected refreshTokenRequestUrls = []; - constructor(private inj: Injector, private store: Store) { } + constructor(private inj: Injector, private router: Router, private store: Store) { } private isUnauthorized(response: HttpResponseBase): boolean { // invalid_token The access token provided is expired, revoked, malformed, or invalid for other reasons @@ -38,7 +39,7 @@ export class AuthInterceptor implements HttpInterceptor { } private isAuthRequest(http: HttpRequest | HttpResponseBase): boolean { - return http.url + return http && http.url && (http.url.endsWith('/authn/login') || http.url.endsWith('/authn/logout') || http.url.endsWith('/authn/status')); @@ -71,10 +72,16 @@ export class AuthInterceptor implements HttpInterceptor { const authService = this.inj.get(AuthService); const token = authService.getToken(); - let newReq; - // Intercept a request that is not to the authentication endpoint - if (!this.isAuthRequest(req) && isNotEmpty(token)) { + + if (authService.isTokenExpired()) { + authService.setRedirectUrl(this.router.url); + // The access token is expired + // Redirect to the login route + this.store.dispatch(new RedirectWhenTokenExpiredAction('Your session has expired. Please log in again.')); + return Observable.of(null); + } else if (!this.isAuthRequest(req) && isNotEmpty(token)) { + // Intercept a request that is not to the authentication endpoint authService.isTokenExpiring() .filter((isExpiring) => isExpiring) .subscribe(() => { diff --git a/src/app/core/auth/auth.service.ts b/src/app/core/auth/auth.service.ts index 92e3aa3fb5..8d9605782a 100644 --- a/src/app/core/auth/auth.service.ts +++ b/src/app/core/auth/auth.service.ts @@ -22,6 +22,8 @@ import { NativeWindowRef, NativeWindowService } from '../../shared/services/wind export const LOGIN_ROUTE = '/login'; +export const REDIRECT_COOKIE = 'dsRedirectUrl'; + /** * The auth service. */ @@ -261,7 +263,8 @@ export class AuthService { * Redirect to the login route */ public redirectToLogin() { - this.router.navigate(['/login']); + // Hard redirect to login page, so that all state is definitely lost + this._window.nativeWindow.location.href = LOGIN_ROUTE; } /** @@ -272,8 +275,10 @@ export class AuthService { .first() .subscribe((redirectUrl) => { if (isNotEmpty(redirectUrl)) { - // Clear url + // Clear redirect url this.setRedirectUrl(undefined); + this.storage.remove(REDIRECT_COOKIE); + const urlTree: UrlTree = this.router.parseUrl(redirectUrl); const g: UrlSegmentGroup = urlTree.root.children[PRIMARY_OUTLET]; const segment = '/' + g.toString(); @@ -283,7 +288,13 @@ export class AuthService { }; this.router.navigate([segment], navigationExtras); } else { - this.router.navigate(['/']); + // override the route reuse strategy + this.router.routeReuseStrategy.shouldReuseRoute = () => { + return false; + }; + this.router.navigated = false; + const url = decodeURIComponent(this.router.url); + this.router.navigateByUrl(url); } }) @@ -301,13 +312,19 @@ export class AuthService { * Get redirect url */ getRedirectUrl(): Observable { - return this.store.select(getRedirectUrl); + const redirectUrl = this.storage.get(REDIRECT_COOKIE); + if (isNotEmpty(redirectUrl)) { + return Observable.of(redirectUrl); + } else { + return this.store.select(getRedirectUrl); + } } /** * Set redirect url */ setRedirectUrl(url: string) { + this.storage.set(REDIRECT_COOKIE, url); this.store.dispatch(new SetRedirectUrlAction(isNotUndefined(url) ? url : '')); } } diff --git a/src/app/core/auth/authenticated.guard.ts b/src/app/core/auth/authenticated.guard.ts index 2438254582..42c39b403c 100644 --- a/src/app/core/auth/authenticated.guard.ts +++ b/src/app/core/auth/authenticated.guard.ts @@ -60,7 +60,6 @@ export class AuthenticatedGuard implements CanActivate, CanLoad { .take(1) .subscribe((authenticated) => { if (!authenticated) { - console.log('set redirect ', url); this.authService.setRedirectUrl(url); this.store.dispatch(new RedirectWhenAuthenticationIsRequiredAction('Login required')); }