Skip to content

Instantly share code, notes, and snippets.

@tobbbe
Last active September 9, 2020 06:36
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tobbbe/08e01db92c32346b226333a3f952df22 to your computer and use it in GitHub Desktop.
Save tobbbe/08e01db92c32346b226333a3f952df22 to your computer and use it in GitHub Desktop.
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')
}
}
@roshenpo007
Copy link

roshenpo007 commented Dec 19, 2017

Do I need to add anything in system-config.ts for below error ?

Unhandled Promise rejection: (SystemJS) XHR error (404 Not Found) loading http://localhost:9190/node_modules/rxjs/Observable/ErrorObservable.js
   Error: XHR error (404 Not Found) loading http://localhost:9190/node_modules/rxjs/Observable/ErrorObservable.js

@roshenpo007
Copy link

Fixed. The path is wrong. It should be

from “rxjs/observable/EmptyObservable“;

@roshenpo007
Copy link

not logging out on refresh token failure. when refresh token service returns 401, control is not going to error block.

@harika13
Copy link

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