Skip to content
Snippets Groups Projects
Commit 1c6d2421 authored by Alex ORLUC's avatar Alex ORLUC
Browse files

FEAT #16148 TIME 1:30 fix handle 401 error

parent bdd0f59b
No related branches found
No related tags found
No related merge requests found
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpHandler, HttpInterceptor, HttpRequest, HttpClient, HttpErrorResponse } from '@angular/common/http'; import { HttpHandler, HttpInterceptor, HttpRequest, HttpClient, HttpErrorResponse } from '@angular/common/http';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { catchError, switchMap } from 'rxjs/operators'; import { catchError, filter, switchMap, take } from 'rxjs/operators';
import { NotificationService } from './notification/notification.service'; import { NotificationService } from './notification/notification.service';
import { AuthService } from './auth.service'; import { AuthService } from './auth.service';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { Observable, of } from 'rxjs'; import { BehaviorSubject, Observable } from 'rxjs';
@Injectable() @Injectable()
export class AuthInterceptor implements HttpInterceptor { export class AuthInterceptor implements HttpInterceptor {
...@@ -41,6 +41,11 @@ export class AuthInterceptor implements HttpInterceptor { ...@@ -41,6 +41,11 @@ export class AuthInterceptor implements HttpInterceptor {
method: ['PUT'] method: ['PUT']
} }
]; ];
private isRefreshing = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(
null
);
constructor( constructor(
public translate: TranslateService, public translate: TranslateService,
public http: HttpClient, public http: HttpClient,
...@@ -60,9 +65,29 @@ export class AuthInterceptor implements HttpInterceptor { ...@@ -60,9 +65,29 @@ export class AuthInterceptor implements HttpInterceptor {
}); });
} }
logout() { private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
this.authService.logout(false, true); if (!this.isRefreshing) {
this.notificationService.error(this.translate.instant('lang.sessionExpired')); 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> { intercept(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
...@@ -84,43 +109,7 @@ export class AuthInterceptor implements HttpInterceptor { ...@@ -84,43 +109,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) { if (this.byPassHandleErrors.filter(url => request.url.indexOf(url.route) > -1 && url.method.indexOf(request.method) > -1).length > 0) {
return next.handle(request); return next.handle(request);
} else if (error.status === 401) { } else if (error.status === 401) {
console.debug('Auth error', request.url); return this.handle401Error(request, next);
return this.http.get('../rest/authenticate/token', {
params: {
refreshToken: this.authService.getRefreshToken()
}
}).pipe(
switchMap((data: any) => {
console.debug('Attempt get token ... !', request.url);
// 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 of(false);
}
})
);
}
),
catchError(err => {
// Disconnect user if bad token process
if (err.status === 401) {
console.debug('Refresh token failed !', request.url, this.router.url);
this.logout();
}
return of(false);
})
);
} else if (error.error.errors === 'User must change his password') { } else if (error.error.errors === 'User must change his password') {
return this.router.navigate(['/password-modification']); return this.router.navigate(['/password-modification']);
} else { } else {
......
...@@ -102,6 +102,25 @@ export class AuthService { ...@@ -102,6 +102,25 @@ export class AuthService {
this.localStorage.remove('MaarchCourrierRefreshToken'); this.localStorage.remove('MaarchCourrierRefreshToken');
} }
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(false, true);
this.notify.error(this.translate.instant('lang.sessionExpired'));
return of(false);
})
);
}
async logout(cleanUrl: boolean = true, forcePageLogin: boolean = false) { async logout(cleanUrl: boolean = true, forcePageLogin: boolean = false) {
if (['cas', 'keycloak', 'azure_saml'].indexOf(this.authMode) > -1 && !forcePageLogin) { if (['cas', 'keycloak', 'azure_saml'].indexOf(this.authMode) > -1 && !forcePageLogin) {
this.SsoLogout(cleanUrl); this.SsoLogout(cleanUrl);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment