Angular JWT 拦截器切换承载令牌以进行刷新
Posted
技术标签:
【中文标题】Angular JWT 拦截器切换承载令牌以进行刷新【英文标题】:Angular JWT interceptor switch bearer token for refresh 【发布时间】:2022-01-13 00:41:53 【问题描述】:我已经实现了 JWT 和刷新令牌流。过去我实现这个的时候,我做的有点不同,主要是刷新令牌是在正文中发送的。
但是现在我做了不同的事情,我必须通过 Authorization 标头发送访问令牌,但是我的拦截器代码不想切换不记名令牌。我该如何解决,如果我想刷新,我实际上使用刷新令牌作为承载令牌而不是已过期的访问令牌?
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 标头设置为授权持有者令牌
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);
)
);
【问题讨论】:
【参考方案1】:您不应使用不记名令牌替换访问令牌来刷新它,而是使用您的刷新令牌调用专用令牌端点来获取新的访问令牌。有时,根据设置,您可能还会取回新的刷新令牌。
【讨论】:
嗯,这正是我想要做的,也许我措辞不好。我打算使用刷新令牌向刷新令牌端点发出请求,从那里我得到一个新的访问令牌和一个新的刷新令牌。然后我保存新的访问令牌并使用它。或者你是说我之前的项目中的实现,我在正文中添加了刷新令牌是正确的? 很难理解到底是什么问题 :-) 我的意思是你过去的项目听起来有点不对劲。刷新令牌不应作为请求中的授权标头发送,也不应发送到 idp 以外的任何其他服务。 那么,实际发送和刷新令牌的最佳方式是什么? 当今一个流行的选择是使用 BFF 模式来管理令牌,这也比尝试在 Angular 中管理令牌提供更好的安全性。 blog.bitsrc.io/…【参考方案2】:您不应在 Authorization
标头中使用刷新令牌。这意味着您不应仅根据刷新令牌的值来授权请求。如果您这样做,那么任何窃取刷新令牌的人都可以使用它来获取新的访问令牌!刷新令牌是发布新令牌所需的数据,但您应该以另一种方式授权客户端(您的应用程序)。例如。您可以使用 HTTP Basic 身份验证并传递客户端的 ID 和密钥,或者使用更复杂的东西,例如双向 TLS。
【讨论】:
以上是关于Angular JWT 拦截器切换承载令牌以进行刷新的主要内容,如果未能解决你的问题,请参考以下文章
Angular 6 - 为啥生产构建中缺少承载令牌? (在开发版本中工作正常)