如何修复来自第一个http请求的刷新访问令牌,该令牌给出GET 401错误

时间:2019-04-30 12:37:50

标签: javascript angular typescript oauth-2.0

问题在于,access token过期并且我单击任何键时,访问令牌都不会刷新。但是,当我第二次单击时,它会刷新。对于第一次单击,我得到“ GET 401 error”。对我来说,实际的问题是在interceptor中的任何HTTP请求之前获取访问令牌。

我尝试switchMap的代码等待访问令牌,但这没有用。 您有什么想法我该如何解决?

export class DevelopmentInterceptor implements HttpInterceptor {
    constructor(
        private authService: AuthService,
        private router: Router,
        private toastr: ToastrService,
        private translate: TranslateService
    ) { }

intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const headers = new HttpHeaders({
        'Content-Type': 'application/json; charset=utf-8',
        'Authorization': `Bearer ${this.authService.getAccessToken()}`
    });
    let apiReq = null;
    if (req.url.indexOf('i18n') >= 0) {
        apiReq = req;
    } else if (req.url.indexOf('token') >= 0) {
        apiReq = req.clone({ url: environment.authServerUrl + `${req.url}` });
    } else if (req.url.indexOf('sign-up') >= 0) {
        apiReq = req.clone({ url: environment.signupUrl });
    } else if (req.url.indexOf('api/users') >= 0 || req.url.indexOf('api/roles') >= 0 || req.url.indexOf('api/permissions') >= 0) {
        apiReq = req.clone({ headers: headers, url: environment.authServerUrl + `${req.url}` });
    } else {
        apiReq = req.clone({ headers: headers, url: environment.backenUrl + `${req.url}` });
    }

    if (req.url.endsWith('token')) {
        return next.handle(apiReq).catch((err: any) => { //<--if error use a catch
            if (err instanceof HttpErrorResponse) {
                return this.handleError(err);
            }
        });
    } else {
        return this.authService.checkExpiry().switchMap( (result) => {
            if (result) {
                return next.handle(apiReq)
                    .catch((err: any) => { // <--if error use a catch
                        if (err instanceof HttpErrorResponse) {
                            return this.handleError(err);
                        }
                    });
            }
        } )
    }
}

private handleError(err: Response | any) {
        ...
    }
}

public checkExpiry() : Observable<any> {
    if (!this.cookieService.get('user_id')) {
        this.removeTokens();  // not logged in
        return Observable.of(true);
    } else if (!this.cookieService.check('access_token')) {
        if (this.cookieService.check('refresh_token')) {
            if (this.secondsTillExpiry('refresh_token') > 0) {
                return this.refreshAccessToken().switchMap((data:any) => {
                    if (data) {
                        this.saveTokenInCookies(data);
                        this.updateExpiration(data);
                        return Observable.of(true);
                    }
                })
            } else {
                this.router.navigate(['/login']);
                this.removeTokens();
                return Observable.of(true);
            }
        }
    } else if (this.cookieService.check('access_token') ) {
        return Observable.of(true);
    }
}



public secondsTillExpiry(tokenMode: string): any {
    if (tokenMode == 'access_token') {
        return  ((new Date(1970, 0, 
                 1).setSeconds(jwt_decode(this.getAccessToken()).exp)) - 
                 (Math.round(Date.now()) / 1000));
    } else  if (tokenMode == 'refresh_token') {
        return  ((new Date(1970, 0, 
                 1).setSeconds(jwt_decode(this.getRefreshToken()).exp)) - 
                 (Math.round(Date.now()) / 1000));
      }
    }

private refreshAccessToken(): Observable<Object> {
    const params = 'refresh_token=' + this.getRefreshToken() + 
'&grant_type=refresh_token';
    return this.http.post(this.authUrl, params, this.getOptions());

}

1 个答案:

答案 0 :(得分:0)

您还可以在CanActivate中发送任何请求之前检查过期令牌,如果它是有效令牌,则可以将用户导航到所需的路由,否则它将被重定向到login 这是处理此问题的示例

  canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
let accesstoken: string = next.queryParams.accesstoken;
if (this.authService.IsAuthenticated) {
  let user = this.authService.GetUser(); 
  let CurrentDate = new Date();
  let date = CurrentDate.getFullYear() + "-" + (CurrentDate.getMonth() + 1) + "-" + CurrentDate.getDate();
  if (user.expire_date) {
    if (Date.parse(date) <= Date.parse(user.expire_date)) {
      if (accesstoken) {
        // if token in url, redirect to url without token :)
        if (user.uuid == accesstoken)
          this.router.navigateByUrl(window.location.pathname);
        // if new token is not the same of current one, Register with new token
        else {
          return this.authService.checkAccess(accesstoken).pipe(
            map(data => {
              if (data === true) {
                if (accesstoken) {
                  this.router.navigateByUrl(window.location.pathname);
                }
                return true;
              } else {
                this.router.navigate(['/login']);
                return false;
              }

            })
          );
        }
      }
      return true;
    }
    else if (Date.parse(date) > Date.parse(user.expire_date)) {
      this.router.navigate(['/login']);
      return false;
    }
  }
}
else {
  this.router.navigate(['/login']);
  return false;
}

}

您应该根据您的代码进行处理