/
auth.interceptor.ts
91 lines (83 loc) · 3.13 KB
/
auth.interceptor.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { Injectable } from "@angular/core";
import {
HttpEvent,
HttpInterceptor,
HttpHandler,
HttpRequest,
HttpErrorResponse
} from "@angular/common/http";
import { throwError, Observable, BehaviorSubject, of } from "rxjs";
import { catchError, filter, finalize, take, switchMap } from "rxjs/operators";
import { paths } from "../const";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
private AUTH_HEADER = "Authorization";
private token = "secrettoken";
private refreshTokenInProgress = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(
null
);
intercept(
req: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (!req.url.includes(paths.auth)) {
return next.handle(req);
}
console.warn("AuthInterceptor");
if (!req.headers.has("Content-Type")) {
req = req.clone({
headers: req.headers.set("Content-Type", "application/json")
});
}
req = this.addAuthenticationToken(req);
return next.handle(req).pipe(
catchError((error: HttpErrorResponse) => {
if (error && error.status === 401) {
// 401 errors are most likely going to be because we have an expired token that we need to refresh.
if (this.refreshTokenInProgress) {
// If refreshTokenInProgress is true, we will wait until refreshTokenSubject has a non-null value
// which means the new token is ready and we can retry the request again
return this.refreshTokenSubject.pipe(
filter(result => result !== null),
take(1),
switchMap(() => next.handle(this.addAuthenticationToken(req)))
);
} else {
this.refreshTokenInProgress = true;
// Set the refreshTokenSubject to null so that subsequent API calls will wait until the new token has been retrieved
this.refreshTokenSubject.next(null);
return this.refreshAccessToken().pipe(
switchMap((success: boolean) => {
this.refreshTokenSubject.next(success);
return next.handle(this.addAuthenticationToken(req));
}),
// When the call to refreshToken completes we reset the refreshTokenInProgress to false
// for the next time the token needs to be refreshed
finalize(() => (this.refreshTokenInProgress = false))
);
}
} else {
return throwError(error);
}
})
);
}
private refreshAccessToken(): Observable<any> {
return of("secret token");
}
private addAuthenticationToken(request: HttpRequest<any>): HttpRequest<any> {
// If we do not have a token yet then we should not set the header.
// Here we could first retrieve the token from where we store it.
if (!this.token) {
return request;
}
// If you are calling an outside domain then do not add the token.
if (!request.url.match(/www.mydomain.com\//)) {
return request;
}
return request.clone({
headers: request.headers.set(this.AUTH_HEADER, "Bearer " + this.token)
});
}
}