繁体   English   中英

Angular JWT 拦截器切换承载令牌用于刷新

[英]Angular JWT interceptor switch bearer token for refresh

我已经实现了 JWT 和刷新令牌流。 过去实现这个时,我做的有点不同,主要是刷新令牌是在正文中发送的。

但是现在我做了不同的事情,我必须通过授权 header 发送访问令牌,但是我的拦截器代码不想切换不记名令牌。 我该如何解决,如果我想刷新,我实际上使用刷新令牌作为不记名令牌而不是已过期的访问令牌?

intercept(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    const token = this.userService.getJWTToken();
    if (token) {
      request = this.addToken(request, token);
    }

    return next.handle(request).pipe(
      catchError((error) => {
        if (error instanceof HttpErrorResponse && error.status === 401) {
          return this.handle401Error(request, next);
        } else if (error.status !== 0) {
          return throwError(error);
        }
      })
    );
  }

private addToken(request: HttpRequest<any>, token: string): HttpRequest<any> {
    return request.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`,
      },
    });
  }

  private handle401Error(
    request: HttpRequest<any>,
    next: HttpHandler
  ): Observable<HttpEvent<any>> {
    if (!this.isRefreshing) {
      this.isRefreshing = true;
      this.refreshTokenSubject.next(null);

      //This is what I've tried, to switch out the tokens
      request = this.addToken(request, this.userService.getRefreshToken());

      //this.userService.refreshToken() is a POST request, where I want the refresh token as the bearer token, instead of the access token
      return this.userService.refreshToken().pipe(
        switchMap((token: TokenDTO) => {
          this.isRefreshing = false;
          this.refreshTokenSubject.next(token.accessToken);
          return next.handle(this.addToken(request, token.accessToken));
        })
      );
    } else {
      return this.refreshTokenSubject.pipe(
        filter((token) => token != null),
        take(1),
        switchMap((accessToken) =>
          next.handle(this.addToken(request, accessToken))
        )
      );
    }
  }

我还尝试在发布请求中将 HTTP header 设置为授权持有者令牌

public refreshToken(): Observable<TokenDTO> {
    const headers = new HttpHeaders({
      'Content-Type': 'application/json',
      Authorization: `Bearer ${this.getRefreshToken()}`,
    });

    return this.httpClient
      .post<TokenDTO>(`${this.hostname}/users/refreshToken`, {}, headers)
      .pipe(
        tap((tokens: TokenDTO) => {
          this.saveTokens(tokens);
        })
      );
  }

您不应将访问令牌替换为不记名令牌来刷新它,而是使用您的刷新令牌调用专用令牌端点来获取新的访问令牌。 有时,根据设置,您可能还会取回新的刷新令牌。

您不应在Authorization header 中使用刷新令牌。 这意味着您不应仅根据刷新令牌的值来授权请求。 如果你这样做,那么任何窃取刷新令牌的人都可以使用它来获取新的访问令牌,刷新令牌是发布新令牌所需的数据。 但是您应该以另一种方式授权客户端(您的应用程序)。 例如,您可以使用 HTTP 基本身份验证并通过客户端的 ID 和密码,或者使用更复杂的东西。 像双向 TLS。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM