]>
Commit | Line | Data |
---|---|---|
ab398a05 | 1 | import { Observable, of, throwError as observableThrowError } from 'rxjs' |
db400f44 | 2 | import { catchError, switchMap } from 'rxjs/operators' |
ab398a05 | 3 | import { HTTP_INTERCEPTORS, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpErrorResponse } from '@angular/common/http' |
67ed6552 C |
4 | import { Injectable, Injector } from '@angular/core' |
5 | import { AuthService } from '@app/core/auth/auth.service' | |
ab398a05 RK |
6 | import { Router } from '@angular/router' |
7 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' | |
d592e0a9 C |
8 | |
9 | @Injectable() | |
10 | export class AuthInterceptor implements HttpInterceptor { | |
11 | private authService: AuthService | |
12 | ||
13 | // https://github.com/angular/angular/issues/18224#issuecomment-316957213 | |
ab398a05 | 14 | constructor (private injector: Injector, private router: Router) {} |
d592e0a9 C |
15 | |
16 | intercept (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | |
17 | if (this.authService === undefined) { | |
18 | this.authService = this.injector.get(AuthService) | |
19 | } | |
20 | ||
21 | const authReq = this.cloneRequestWithAuth(req) | |
22 | ||
23 | // Pass on the cloned request instead of the original request | |
24 | // Catch 401 errors (refresh token expired) | |
25 | return next.handle(authReq) | |
db400f44 | 26 | .pipe( |
ab398a05 RK |
27 | catchError((err: HttpErrorResponse) => { |
28 | if (err.status === HttpStatusCode.UNAUTHORIZED_401 && err.error && err.error.code === 'invalid_token') { | |
db400f44 | 29 | return this.handleTokenExpired(req, next) |
f43db2f4 C |
30 | } |
31 | ||
32 | if (err.status === HttpStatusCode.UNAUTHORIZED_401) { | |
ab398a05 | 33 | return this.handleNotAuthenticated(err) |
db400f44 C |
34 | } |
35 | ||
36 | return observableThrowError(err) | |
37 | }) | |
38 | ) | |
d592e0a9 C |
39 | } |
40 | ||
41 | private handleTokenExpired (req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | |
42 | return this.authService.refreshAccessToken() | |
db400f44 C |
43 | .pipe( |
44 | switchMap(() => { | |
45 | const authReq = this.cloneRequestWithAuth(req) | |
d592e0a9 | 46 | |
db400f44 C |
47 | return next.handle(authReq) |
48 | }) | |
49 | ) | |
d592e0a9 C |
50 | } |
51 | ||
52 | private cloneRequestWithAuth (req: HttpRequest<any>) { | |
53 | const authHeaderValue = this.authService.getRequestHeaderValue() | |
54 | ||
55 | if (authHeaderValue === null) return req | |
56 | ||
57 | // Clone the request to add the new header | |
58 | return req.clone({ headers: req.headers.set('Authorization', authHeaderValue) }) | |
59 | } | |
ab398a05 RK |
60 | |
61 | private handleNotAuthenticated (err: HttpErrorResponse, path = '/login'): Observable<any> { | |
62 | this.router.navigateByUrl(path) | |
63 | return of(err.message) | |
64 | } | |
d592e0a9 C |
65 | } |
66 | ||
67 | export const AUTH_INTERCEPTOR_PROVIDER = { | |
68 | provide: HTTP_INTERCEPTORS, | |
69 | useClass: AuthInterceptor, | |
70 | multi: true | |
71 | } |