3

In my application, the authentication is based on JWT tokens. In order to invalidate them, I've placed a random secure string inside of the JWT and the exact same string stored in the database, associated with the user who owns the token. These two have to match for the JWT to be valid. When the user logs out, the API generates another random string and replaces the old one on the database, making the JWT invalid for that user because the string inside de JWT and the string of the database don't match.

For this to happen, I need an interceptor that makes a silent request BEFORE every request to the API to check if the random strings are equal. Based on this question, my interceptor works but behaves weird, making infinite requests and throwing the "too much recursion" error.

What am I doing wrong?

Interceptor

 import { TokenService }     from './token.service';
 import { Router }           from '@angular/router';
 import { HttpInterceptor,
     HttpRequest, 
     HttpHandler, 
     HttpEvent, 
     HttpClient,
     HttpHeaders }       from "@angular/common/http";
 import { Injectable }       from "@angular/core";
 import { Observable }       from "rxjs/Observable";
 import { SharedService }    from "./shared-service.service";
 import { CookieService }    from 'ngx-cookie-service';

 @Injectable()

export class AuthInterceptor implements HttpInterceptor {


constructor(private sharedService : SharedService,
            private httpClient : HttpClient,
            private router : Router,
            private cookieService : CookieService,
            private tokenService : TokenService)  {}

token:          string;
cd:             number;
isExpired:      boolean = false;
revog_token:    string;

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

// Check if token exists on cookies
if(this.tokenService.CheckToken()){
    if (req.url.match(/api\//)) { // Request to API
       console.log("API Request");
       this.CheckRevogToken(); // <-- THIS METHOD TRIGGERS THE "TOO MUCH RECURSION" ERROR

    }
    const cloned = req.clone({ headers:  req.headers.set("Authorization","Bearer "+ this.tokenService.GetToken()) });
    return next.handle(cloned);
}
else{
    return next.handle(req).catch((error, caught) => { 
    // If status code is  401 ==> Not authorized
    if(error.status == 401){
        alert("A sua sessão expirou! Será redirecionado para a página de autenticação");
    }else{
        console.log("Ocorreu um erro");
        return Observable.throw(error);
    }}) as any;
  }
}   


CheckRevogToken(){
    this.revog_token = this.tokenService.GetRevogFromDecodedToken();
    var headers = new HttpHeaders();
    headers.append('Content-Type', 'application/json');
    return this.httpClient.post("http://localhost:53448/api/check_revog_token", {cd: this.cd, revog_token: this.revog_token}, {headers:headers})
.subscribe(
    res => {
      console.log(res); 
    },
    err => {
      console.log("err: " +err);
      }
  )};
 }   

Error screenshot

Error screenshot

LuisMorais
  • 162
  • 4
  • 16
  • 1
    Why do you return the Observable of `this.httpClient.post()` even though you don't use it? Try to remove the `return` statement before. – JSON Derulo Aug 21 '18 at 09:29
  • 1
    It's because `CheckRevogToken` is also calling the http interceptor when you call this url : `http://localhost:53448/api/check_revog_token` that will also call another time the interceptor etc.. so you have to prevent it before the check token method – Julien METRAL Aug 21 '18 at 09:31
  • @D.Simon I'm in a middle of changes and that line is on a 'stand-by' to use it later. But, thanks anyway – LuisMorais Aug 21 '18 at 09:43
  • @JulienMetral Could look at that for weeks and be unable to notice that. Many thanks! – LuisMorais Aug 21 '18 at 09:45

1 Answers1

5

You have created infinite loop in your code:

  1. You start with: http://localhost:53448/api/... request

  2. Your HttpInterceptor catches it. Because url matches (/api\//) format, then this.CheckRevogToken() method is called

  3. In CheckRevogToken() you create a hearder, and post is to the following url:"http://localhost:53448/api/check_revog_token"

  4. Your post request is one more time caught by HttpInterceptor. Because url again matches (/api\//), then step 2 is repeated.

Tinki
  • 1,486
  • 1
  • 21
  • 32
  • Oh, now I see what is happening! Maybe if I change the endpoint of _/api/check_revog_token_ , the problem is solved... Many thanks! – LuisMorais Aug 21 '18 at 09:41