Angular: refresh token only once

最后都变了- 提交于 2021-02-10 06:41:39

问题


I'm using JWT with refresh token strategy as authentication and I have an interceptor in my Angular client that sends the token as a header.

I check for expiration before sending, and refresh the token with my refreshToken if needed.

The problem is when sending 2 (or more) requests, both trying to refresh the token. I need a function that sends req for refresh token and when called multiple times at once, makes only 1 http req to the server for refresh and returns the new updated token to all who called it.

This is my interceptor:

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const authService = this.inj.get(AuthService);
    const token = authService.getToken();

    // if no token or this is a refresh token req
    if (!token || req.url.split('/').pop() === 'refreshToken') {
      return next.handle(req);
    }

    const decoded = jwt.decode(token);

    // if token expired
    if (decoded.exp < (Date.now() / 1000)) {
      return authService.refreshJWTToken().concatMap((newToken) => {
        const clonedReq = req.clone({
          headers: req.headers.set('Authorization', 'JWT ' + newToken)
        });
        return next.handle(clonedReq);
      });
    }

    const clonedReq = req.clone({ headers: req.headers.append('Authorization', 'JWT ' + token) });
    return next.handle(clonedReq);
  }

The function that I need is authService.refreshJWTToken();

I know it's something that has to do with Observables operators but I'm a bit new to this.


回答1:


Alright I got it after reading this: https://www.intertech.com/Blog/angular-4-tutorial-handling-refresh-token-with-new-httpinterceptor/

My function looks like this (also handling the req):

handleRefreshToken(req: HttpRequest<any>, next: HttpHandler): Observable<any> {
  const authService = this.inj.get(AuthService);

  if (!this.isRefreshingToken) {
    this.isRefreshingToken = true;

    // Reset here so that the following requests wait until the token
    // comes back from the refreshToken call.
    authService.tokenSubject.next(null);

    return authService.doRefreshToken()
      .switchMap((newToken: string) => {
        authService.tokenSubject.next(newToken);
        return next.handle(this.addToken(req, newToken));
      })
      .catch(err => {
        authService.logout();
        return Observable.throw(err);
      })
      .finally(() => {
        this.isRefreshingToken = false;
      });
  } else {
    return authService.tokenSubject
      .filter(token => token != null)
      .take(1)
      .switchMap(token => {
        return next.handle(this.addToken(req, token));
      });
  }
}

Thanks to Vadim (the vagin) Siomin for the help!



来源:https://stackoverflow.com/questions/47868771/angular-refresh-token-only-once

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!