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 刷新令牌的主要内容,如果未能解决你的问题,请参考以下文章

跨域资源共享错误 (CORS) Angular 10

Cookie不会在跨源请求中发送

chat.facebook.com 在跨域策略文件响应的末尾不发送零字节

OPTIONS 方法在跨域请求(CORS)中的应用

明年找到好工作:面试题打卡第二天

明年找到好工作:面试题打卡第二天