Angular interceptor token refresh token user service. Thanks to: https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/
import { Injectable, Injector } from '@angular/core'; | |
import { HttpErrorResponse, HttpHandler, HttpInterceptor, HttpRequest, HttpEvent, HttpClient, HttpHeaders } from '@angular/common/http'; | |
import { Observable } from 'rxjs/Observable'; | |
import { ErrorObservable } from 'rxjs/Observable/ErrorObservable'; | |
import { EmptyObservable } from 'rxjs/Observable/EmptyObservable'; | |
import { BehaviorSubject } from 'rxjs/BehaviorSubject'; | |
import { catchError, filter, take, switchMap, finalize } from "rxjs/operators"; | |
import { APIURL } from "../app/constants"; | |
import { UserService } from "./user/user.provider"; | |
@Injectable() | |
export class TokenInterceptor implements HttpInterceptor { | |
isRefreshingToken: boolean = false; | |
tokenSubject: BehaviorSubject<string> = new BehaviorSubject<string>(null); | |
constructor(private injector: Injector, private userService: UserService) { } | |
private setAuthHeader(request) { | |
return request.clone({ url: APIURL + request.url, setHeaders: { Authorization: `Bearer ${this.userService.token}` } }); | |
} | |
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | |
return next.handle(this.setAuthHeader(request)) | |
.pipe( | |
catchError((error, ca) => { | |
if (error instanceof HttpErrorResponse) { | |
switch ((<HttpErrorResponse>error).status) { | |
case 401: | |
return this.handle401Error(request, next) | |
default: | |
return ErrorObservable.create(error); | |
} | |
} else { | |
return ErrorObservable.create(error); | |
} | |
}) | |
) | |
} | |
handle401Error(req: HttpRequest<any>, next: HttpHandler) { | |
if (!this.isRefreshingToken) { | |
this.isRefreshingToken = true; | |
// Reset here so that the following requests wait until the token | |
// comes back from the refreshToken call. | |
this.tokenSubject.next(null); | |
const http = this.injector.get(HttpClient); | |
return http.get('/auth/RefreshToken', { headers: new HttpHeaders().set('Authorization', `Bearer ${this.userService.token}`) }) | |
.pipe( | |
switchMap((newToken: string) => { | |
if (newToken) { | |
this.userService.setToken(newToken) | |
this.tokenSubject.next(newToken) | |
return next.handle(this.setAuthHeader(req)); | |
} | |
// If we don't get a new token, we are in trouble so logout. | |
this.userService.logout() | |
console.log('Could not refresh token 1') | |
return EmptyObservable.create(); | |
}), | |
catchError(error => { | |
// If there is an exception calling 'refreshToken', bad news so logout. | |
this.userService.logout() | |
console.log('Could not refresh token 2') | |
return EmptyObservable.create(); | |
}), | |
finalize(() => { | |
this.isRefreshingToken = false; | |
}) | |
) | |
} else { | |
return this.tokenSubject | |
.pipe( | |
filter(token => token != null), | |
take(1), | |
switchMap(token => { | |
return next.handle(this.setAuthHeader(req)); | |
}) | |
) | |
} | |
} | |
} |
import { Injectable, Injector } from '@angular/core'; | |
import { Subject } from "rxjs/Subject"; | |
import { HttpClient } from "@angular/common/http"; | |
@Injectable() | |
export class UserService { | |
token: string | |
events: Subject<string> = new Subject<string>() | |
constructor(private injector: Injector) { | |
this.token = localStorage.getItem('token'); | |
} | |
init() { | |
if (!this.token) return Promise.reject('No token'); | |
return Promise.resolve(); | |
} | |
setToken(token: string) { | |
this.token = token; | |
localStorage.setItem('token', token) | |
} | |
logout() { | |
const http = this.injector.get(HttpClient); | |
http.get(`/auth/Logout?token=${this.token}`).subscribe() | |
this.token = null; | |
localStorage.clear() | |
this.events.next('logout') | |
} | |
} |
This comment has been minimized.
This comment has been minimized.
Fixed. The path is wrong. It should be from “rxjs/observable/EmptyObservable“; |
This comment has been minimized.
This comment has been minimized.
not logging out on refresh token failure. when refresh token service returns 401, control is not going to error block. |
This comment has been minimized.
This comment has been minimized.
Hi, Do you have complete code for 'refresh token on 401 error' implementation for Angular 5? When i tried i was getting into cyclic errors. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This comment has been minimized.
Do I need to add anything in system-config.ts for below error ?