HttpInterceptor in Angular 4.3 : Re-send request in interceptor after jwt refresh

I would like to know how can I re-send the request with httpinterceptor after verification on error ?

I check if there is an error (to refresh my JWT token), and after the refresh I would like to submit again the fail request.

httpinterceptor.js :

import { Observable } from 'rxjs';
import { Injectable, Inject, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse } from '@angular/common/http';
import { UserService } from "./user/services/user.service";
import { Router } from "@angular/router";

@Injectable()
export class AngularInterceptor implements HttpInterceptor {
    public userService;

    constructor(private router: Router,
                private injector: Injector) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        const clonedRequest = req.clone();

        this.userService = this.injector.get(UserService);

        return next.handle(req)
            .do(event => {
                if (event instanceof HttpResponse) {
                    //normal request
                    console.log(event);
                }
            })
            .catch((res) => {
                console.log('catch error');

                if (res.status === 401 || res.status === 403) {
                    this.userService.refreshToken().subscribe((data: any) => {
                        this.userService.token = data.token;

                        localStorage.removeItem('data-app');

                        localStorage.setItem('data-app', JSON.stringify({token: data.token}));

                        next.handle(clonedRequest).do(event => {
                            console.log('in handle');
                            if (event instanceof HttpResponse) {
                                console.log('rexecuted done !');
                            }
                        });
                    });

                    this.userService.logOut();
                } else if (res.status === 500) {
                    console.log('token invalid');

                    return Observable.throw(res);
                } else {
                    return Observable.throw(res);
                }
            });
    }
}

Upvotes: 3

Views: 4543

Answers (2)

Leonid Dashko
Leonid Dashko

Reputation: 4154

I don't use JWT, but my example can be helpful for the case when you need to re-send initial request after login modal window (which appears when user session is expired) has been closed:

import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Injectable} from "@angular/core";
import {Observable, Subscriber} from "rxjs/Rx";
import {LoginModalComponent} from "@app/shared/components/login-modal/login-modal.component";
import {BsModalService} from "ngx-bootstrap";
import 'rxjs/add/operator/do';
import 'rxjs/add/operator/catch';

@Injectable()
export class HttpAuthInterceptor implements HttpInterceptor {

  constructor(private modalService: BsModalService) {
  }

  private isAuthError(error: any): boolean {
    return error instanceof HttpErrorResponse && error.status == 401;
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const initialRequest = request.clone();

    return next.handle(request)
      .catch((error) => {
        if (!this.isAuthError(error)) {
          return Observable.throwError(error);
        }

        return new Observable((subscriber: Subscriber<any>) => {
          this.modalService.show(LoginModalComponent, {ignoreBackdropClick: true, keyboard: false});

          this.modalService.onHide.subscribe(event => {
            next.handle(initialRequest).subscribe(
              response => subscriber.next(response),
              error => subscriber.error(error),
              () => subscriber.complete()
            );
          });
        });
      });
  }
}

Upvotes: 0

Solved

with the helpful post https://stackoverflow.com/a/45944426/5453732

import { Observable } from 'rxjs';
import { Injectable, Inject, Injector } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { UserService } from "./user/services/user.service";

@Injectable()
export class AngularInterceptor implements HttpInterceptor {
    public userService;

    constructor(private injector: Injector) {
    }

    private applyCredentials = function (req) {
        return req.clone({
            headers: req.headers.set('Authorization', 'Bearer ' + localStorage.getItem('data-app'))
        });
    };

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

        this.userService = this.injector.get(UserService);

        return next.handle(this.applyCredentials(req))
        /*.do(event => {

            if (event instanceof HttpResponse) {
                console.log(event);
            }
        })*/
            .catch((res) => {
                console.log('Token refresh');

                if (res.status === 401 || res.status === 403) {
                    return this.userService.refreshToken().first().flatMap((data: any) => {
                        if (data.token !== '') {
                            localStorage.removeItem('data-app');
                            localStorage.setItem('data-app', data.token);

                            this.userService.token = localStorage.getItem('data-app');
                        } else {
                            this.userService.logOut();

                            return Observable.throw(res);
                        }

                        return next.handle(this.applyCredentials(req));
                    });
                } else if (res.status === 500) {
                    this.userService.logOut();
                }

                return Observable.throw(res);
            });
    }
}

Upvotes: 5

Related Questions