使用角度拦截器刷新令牌

时间:2020-02-26 12:17:23

标签: angular angular-http-interceptors

如果当前api给401或令牌到期错误,我想基于刷新令牌获得新的令牌。

下面的代码是我的拦截器

当我尝试在catch错误部分中调用api(API.refreshToken)时,浏览器立即将其取消。就像下面的图片

https://ibb.co/VBYGZwy

我的代码如下。

import { Injectable } from "@angular/core";
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor,
  HttpClient,
  HttpHeaders,
  HttpErrorResponse
} from "@angular/common/http";
import { Observable, BehaviorSubject } from "rxjs";

import { helpers } from "chart.js";
import { API } from "../constants/apiConstants";
import { AuthService } from "../services/auth.Service";
import { Router } from "@angular/router";
import { catchError, flatMap } from "rxjs/operators";
import { switchMap } from "rxjs-compat/operator/switchMap";

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  private refreshTokenInProgress = false;
  // Refresh Token Subject tracks the current token, or is null if no token is currently
  // available (e.g. refresh pending).
  private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(
    null
  );
  constructor(
    private _auth: AuthService,
    private _router: Router,
    private httpClient: HttpClient
  ) {}

  intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    // add authorization header with basic auth credentials if available
    let token = this._auth.getLocalStorageItem("accesstoken");
    if (token) {
      let helpersData = {};
      helpersData[API.idToken] = `${this._auth.getLocalStorageItem(
        "identityToken"
      )}`;

      if (request.url.includes("refreshtoken")) {
        helpersData[API.refereshTokenHeader] = this._auth.getLocalStorageItem(
          "refreshToken"
        );
      } else {
        helpersData[API.authorization] = token;
        helpersData[API.appclientidKey] = API.appClientIdValue;
        helpersData[API.userpoolIdKey] = API.userpoolIdValue;
      }
      request = request.clone({
        setHeaders: helpersData
      });
    }

    return next.handle(request).pipe(
      catchError(error => {
        // NOTE: We don't want to refresh token for some requests like login or refresh token itself
        // So we verify url and we throw an error if it's the case
        console.log("error", error);
        console.log("request", request);
        if (this.refreshTokenInProgress) {
          console.log("in refresh token on");
          // 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
          return this.refreshTokenSubject
            .filter(result => result !== null)
            .take(1)
            .switchMap(() => next.handle(this.addAuthenticationToken(request)));
        } else {
          this.refreshTokenInProgress = true;
          console.log("in refresh token off");
          // Set the refreshTokenSubject to null so that subsequent API calls will wait until the new token has been retrieved
          this.refreshTokenSubject.next(null);
          //Generate params for token refreshing
          // Call auth.refreshAccessToken(this is an Observable that will be returned)
          return this.httpClient
            .get<any>(API.refreshToken)
            .catch((err: any) => {
              console.log("catch error", err);
              this.refreshTokenInProgress = false;
              this._auth.logout();
              return Observable.throw(error);
            })
            .pipe((resData:any) => {
                console.log("rdata", resData);
                // If reload successful update tokens
                if (resData.status == 200) {
                  let rData = resData.data.AuthenticationResult;
                  //Update tokens
                  this._auth.setLocalStorageItem(
                    "accesstoken",
                    rData.AccessToken
                  );
                  this._auth.setLocalStorageItem(
                    "identityToken",
                    rData.IdToken
                  );
                  //Clone our fielded request ant try to resend it
                  this.refreshTokenInProgress = false;
                  this.refreshTokenSubject.next(token);
                  return next.handle(this.addAuthenticationToken(request));
                } else {
                  //Logout from account
                  this._auth.logout();
                  return Observable.throw(error);
                }
              });
        }
        //   return Observable.throw("not user found");
      })
    );
  }
  addAuthenticationToken(request) {
    // Get access token from Local Storage
    let helpersData = {};
    helpersData[API.authorization] = this._auth.getLocalStorageItem(
      "accesstoken"
    );
    helpersData[API.idToken] = `${this._auth.getLocalStorageItem(
      "identityToken"
    )}`;
    // If access token is null this means that user is not logged in
    // And we return the original request
    // if (!token) {
    //     return request;
    // }
    // We clone the request, because the original request is immutable
    return request.clone({
      setHeaders: helpersData
    });
  }
}

0 个答案:

没有答案