Angular 10 应用程序不会在跨域请求中发送 JWT 刷新令牌
Posted
技术标签:
【中文标题】Angular 10 应用程序不会在跨域请求中发送 JWT 刷新令牌【英文标题】:Angular 10 application won't send JWT refresh token on cross-origin request 【发布时间】:2021-04-19 23:01:11 【问题描述】:我们在同一台开发机器的不同端口上有一个 Angular 前端和一个 Web 服务。 Web 服务配置为允许从 localhost 和托管 Angular 应用程序的端口访问。
我们正在使用 JWT 身份验证,它适用于针对 Web 服务的初始身份验证。我们收到一个身份验证令牌并将其存储在 Angular 本地存储和一个刷新令牌中,该令牌存储为设置了 HttpOnly 的 cookie。目前,我们处于一个开发环境中,客户端或 Web 服务均未启用 SSL。
当我们的身份验证令牌过期时,问题就来了。我们的应用程序发送更新令牌的请求,但该请求没有刷新令牌 cookie。
我们尝试在 Angular 中设置代理,将 API 请求从 Angular 域转发到 Web 服务。在这种情况下,刷新令牌 cookie 被转发到 Web 服务,我们得到新的令牌。不幸的是,在构建和部署应用程序后,这将不起作用,我们需要能够在未启用 SSL 的环境中部署和开发。
这是我们的 Angular 应用程序中处理发送刷新令牌的相关代码。下面是授权服务中调用的方法。
public refreshToken()
return this.http.post(this.appConfigService.getGrouperWebServiceUrl()+'/auth/refresh', )
.pipe(
map((res: LoginResponse) =>
this.setSession(res);
return res;
)
);
POST 请求被 Angular 拦截器拦截。
intercept(req: HttpRequest < any > , next: HttpHandler):
Observable < HttpEvent < any >>
// ...
if (req.url.indexOf('refresh') !== -1)
console.log("token interceptor: refresh");
return next.handle(this.configureRefresh(req));
// ...
configureRefresh(req: HttpRequest < any > )
return req.clone(
withCredentials: true
);
以下是使用 Angular 代理的刷新请求的原始请求,因此该请求似乎来自与 Web 服务相同的来源。请注意,refreshToken cookie 包含在请求中。
POST /proxy/auth/refresh HTTP/1.1
Host: localhost:4200
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 2
Origin: http://localhost:4200
Connection: keep-alive
Referer: http://localhost:4200/userHome
Cookie: refreshToken=/*token redacted*/
以下是不使用代理的原始刷新请求。请注意,请求中不包含 refreshToken cookie。
POST /auth/refresh HTTP/1.1
Host: localhost:8081
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json
Content-Length: 2
Origin: http://localhost:4200
Connection: keep-alive
Referer: http://localhost:4200/userHome
当我们进行跨域请求时,如何让 refreshToken cookie 包含在请求标头中?
我们确实看到了这个回复https://***.com/a/46412839/8517076,但它似乎没有帮助。我们已经在 Web 服务中设置了推荐的标头。
【问题讨论】:
我们现在已经在安全环境(SSL、有效证书等)中对此进行了测试,但浏览器仍然拒绝在刷新请求时发送 cookie。我们彻底被难住了。 任何人都可以在这里提供任何见解吗?如果没有,我想我认为这不能完成?我还没有找到任何人将所有这些部分放在一起的例子。人们建议将刷新令牌存储在设置了 httpOnly 的 cookie 中。但在我看到一个真实的例子之前,我猜这是不可能的,除非网络应用程序和网络服务在同一个服务器和端口上。 【参考方案1】:您的 localhost 连接必须是安全的 (https)。 这是必需的!
您需要按照here 的描述创建 SSL 证书并在您的 Angular 应用程序中使用。
在我的例子中,当我使用 SSL 证书重新启动我的 Angular 应用程序时,refresh_token 会自动在请求标头中发送(作为“cookie”属性)。
【讨论】:
以上是关于Angular 10 应用程序不会在跨域请求中发送 JWT 刷新令牌的主要内容,如果未能解决你的问题,请参考以下文章