From 92404352826eeb34f7d15b96f66dfcc1bb847bc2 Mon Sep 17 00:00:00 2001 From: Alex ORLUC <alex.orluc@maarch.org> Date: Fri, 5 Feb 2021 11:00:53 +0100 Subject: [PATCH] FIX #16148 TIME 0:20 improve handle 401 --- .../app/service/auth-interceptor.service.ts | 81 +++++++++---------- src/frontend/app/service/auth.service.ts | 19 +++++ 2 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/frontend/app/service/auth-interceptor.service.ts b/src/frontend/app/service/auth-interceptor.service.ts index 6d0a6ddb1d..495f51af71 100644 --- a/src/frontend/app/service/auth-interceptor.service.ts +++ b/src/frontend/app/service/auth-interceptor.service.ts @@ -1,10 +1,9 @@ import { Injectable } from '@angular/core'; import { HttpHandler, HttpInterceptor, HttpRequest, HttpClient, HttpErrorResponse } from '@angular/common/http'; -import { Observable } from 'rxjs'; +import { BehaviorSubject, Observable } from 'rxjs'; import { Router } from '@angular/router'; -import { catchError, switchMap } from 'rxjs/operators'; +import { catchError, filter, switchMap, take } from 'rxjs/operators'; import { NotificationService } from './notification.service'; -import { EMPTY } from 'rxjs'; import { SignaturesContentService } from './signatures.service'; import { AuthService } from './auth.service'; @@ -24,7 +23,18 @@ export class AuthInterceptor implements HttpInterceptor { } ]; - constructor(public http: HttpClient, private router: Router, public notificationService: NotificationService, public signaturesService: SignaturesContentService, public authService: AuthService) { } + private isRefreshing = false; + private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>( + null + ); + + constructor( + public http: HttpClient, + private router: Router, + public notificationService: NotificationService, + public signaturesService: SignaturesContentService, + public authService: AuthService + ) { } addAuthHeader(request: HttpRequest<any>) { @@ -37,9 +47,29 @@ export class AuthInterceptor implements HttpInterceptor { }); } - logout() { - this.authService.logout(); - this.notificationService.error('lang.sessionExpired'); + private handle401Error(request: HttpRequest<any>, next: HttpHandler) { + if (!this.isRefreshing) { + this.isRefreshing = true; + this.refreshTokenSubject.next(null); + + return this.authService.refreshToken().pipe( + switchMap((data: any) => { + this.isRefreshing = false; + this.refreshTokenSubject.next(data.token); + request = this.addAuthHeader(request); + return next.handle(request); + }) + ); + } else { + return this.refreshTokenSubject.pipe( + filter((token) => token != null), + take(1), + switchMap(() => { + request = this.addAuthHeader(request); + return next.handle(request); + }) + ); + } } intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> { @@ -62,42 +92,7 @@ export class AuthInterceptor implements HttpInterceptor { if (this.byPassHandleErrors.filter(url => request.url.indexOf(url.route) > -1 && url.method.indexOf(request.method) > -1).length > 0) { return next.handle(request); } else if (error.status === 401) { - return this.http.get('../rest/authenticate/token', { - params: { - refreshToken: this.authService.getRefreshToken() - } - }).pipe( - switchMap((data: any) => { - - // Update stored token - this.authService.setToken(data.token); - - // Update user info - this.authService.updateUserInfo(data.token); - - // Clone our request with token updated ant try to resend it - request = this.addAuthHeader(request); - - return next.handle(request).pipe( - catchError(err => { - // Disconnect user if bad token process - if (err.status === 401) { - this.logout(); - return EMPTY; - } - }) - ); - - } - ), - catchError(err => { - // Disconnect user if bad token process - if (err.status === 401) { - this.logout(); - } - return EMPTY; - }) - ); + return this.handle401Error(request, next); } else if (error.error.errors === 'Password expired : User must change his password') { return this.router.navigate(['/password-modification']); } else { diff --git a/src/frontend/app/service/auth.service.ts b/src/frontend/app/service/auth.service.ts index 3beff721e7..905e152350 100755 --- a/src/frontend/app/service/auth.service.ts +++ b/src/frontend/app/service/auth.service.ts @@ -47,6 +47,25 @@ export class AuthService { this.localStorage.remove('MaarchParapheurRefreshToken'); } + refreshToken() { + return this.http + .get<any>(`../rest/authenticate/token`, { params: { refreshToken: this.getRefreshToken() } }) + .pipe( + tap((data) => { + // Update stored token + this.setToken(data.token); + + // Update user info + this.updateUserInfo(data.token); + }), + catchError((error) => { + this.logout(); + this.notificationService.error('lang.sessionExpired'); + return of(false); + }) + ); + } + logout() { const refreshToken = this.getRefreshToken(); if (refreshToken === null) { -- GitLab