Skip to content

Instantly share code, notes, and snippets.

@atultherajput
Created January 17, 2019 13:25
Show Gist options
  • Save atultherajput/45481b69fc13719612f597e11eafb416 to your computer and use it in GitHub Desktop.
Save atultherajput/45481b69fc13719612f597e11eafb416 to your computer and use it in GitHub Desktop.
JWT refresh token in Angular 6 Interceptor with Ngrx
import { Injectable } from '@angular/core';
import {
HttpRequest,
HttpHandler,
HttpEvent,
HttpInterceptor
} from '@angular/common/http';
import { Observable, BehaviorSubject } from 'rxjs';
import { filter, take, switchMap } from 'rxjs/operators';
import { SigninModuleState } from '../../signin/store/models/signin.model';
import { Store } from '@ngrx/store';
import { SIGNIN_STORE } from '../../signin/store/reducer/signin.reducer';
import * as SigninActions from '../../signin/store/actions/signin.actions';
import { JWTUtil } from '../../shared/utils/jwt-util';
@Injectable()
export class HttpJwtInterceptor implements HttpInterceptor {
private jwtToken: any = {
accessToken: "",
refreshToken: ""
}
private refreshTokenInProgress = false;
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(
null
);
constructor(private store: Store<SigninModuleState>, private jwtUtil: JWTUtil) {
this.store
.select(SIGNIN_STORE)
.subscribe((data: SigninModuleState) => {
console.log(data)
if (this.jwtToken.accessToken == "" || this.jwtToken.accessToken != this.getAccessToken(data)) {
this.jwtToken.accessToken = this.getAccessToken(data);
this.jwtToken.refreshToken = this.getRefreshToken(data);
this.refreshTokenSubject.next(this.jwtToken.refreshToken);
}
})
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
console.log("PRE INTERCEPT: ", request.url);
if (request.url.includes("api/signin") || request.url.includes("api/token/refresh")) {
console.log("Login or refresh API!")
console.log("POST INTERCEPT: ", request.url);
return next.handle(request);
}
this.refreshTokenInProgress = this.isRefreshTokenInProgress(this.jwtToken.accessToken);
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
console.log("Return Refresh Token In Progress!")
return this.refreshTokenSubject.pipe(
filter(result => result !== null),
take(1),
switchMap(() => next.handle(this.addAuthenticationToken(request)))
);
} else {
console.log("In else block. Setting refreshTokenSubject to null!")
// Set the refreshTokenSubject to null so that subsequent API calls will wait until the new token has been retrieved
this.refreshTokenSubject.next(null);
return next.handle(this.addAuthenticationToken(request));
}
}
private getAccessToken(data: SigninModuleState): string {
if (data && data.loginContext) {
return data.loginContext.accessToken;
} else {
return "NOT_AVAILABLE";
}
}
private getRefreshToken(data: SigninModuleState): string {
if (data && data.loginContext) {
return data.loginContext.refreshToken;
} else {
return "NOT_AVAILABLE";
}
}
addAuthenticationToken(request: HttpRequest<any>) {
// Get access token from Local Storage
const accessToken = this.jwtToken.accessToken;
// If access token is null this means that user is not logged in
// And we return the original request
if (!accessToken) {
console.log("Token not found!")
return request;
}
// We clone the request, because the original request is immutable
console.log("Returning cloned request with bearer token!")
let newRequest = request.clone({
setHeaders: {
Authorization: "Bearer " + accessToken
}
});
console.log("POST INTERCEPT: ", newRequest.url);
return newRequest;
}
isRefreshTokenInProgress(accessToken: string) {
if (this.jwtUtil.isExpired(accessToken)) {
console.log("Token expire. Dispatching new token action!")
// Set the refreshTokenSubject to null so that subsequent API calls will wait until the new token has been retrieved
this.refreshTokenSubject.next(null);
this.store.dispatch(new SigninActions.RefreshToken(this.jwtToken));
return true;
}
else {
return false;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment