You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firefox中React Fetch未携带Cookie的Discord OAuth2问题

授权流程

  • React 应用(localhost:端口1)中通过window.location.href跳转到后端 OAuth2 授权端点(localhost:端口2/api/oauth2/authorization/discord)
    代码实现:
    async function onSubmit() {
        try {
            window.location.href =
              "http://test.local:port2/api/oauth2/authorization/discord";
        } catch (error) {
            console.log(error)
        }
    }
    
  • 向test.local发送GET请求,后端返回HTTP 302重定向至Discord授权页,同时携带Set-Cookie响应头
    响应头内容:
    HTTP/1.1 302 
    Vary: Origin, Access-Control-Request-Method, Access-Control-Request-Headers
    Set-Cookie: oauth2_auth_request=long_cookie_value; Path=/; Max-Age=180; Expires=Sun, 29 Jan 2023 14:13:47 GMT; SameSite=None
    X-Content-Type-Options: nosniff
    X-XSS-Protection: 0
    Cache-Control: no-cache, no-store, max-age=0, must-revalidate
    Pragma: no-cache
    Expires: 0
    X-Frame-Options: DENY
    Location: https://discordapp.com/oauth2/authorize?response_type=code&client_id=...&redirect_uri=http://localhost:5173/login
    Content-Length: 0
    Date: Sun, 29 Jan 2023 14:10:47 GMT
    Keep-Alive: timeout=60
    Connection: keep-alive
    
  • 用户看到Discord登录页面
  • 在浏览器中直接访问http://test.local:port2,可确认Cookie已正确设置
  • 用户登录Discord后,Discord重定向至http://localhost:端口1/login?code=...&state=...
  • React应用发送fetch请求到后端的code回调端点:
    代码实现:
    fetch(
      `http://test.local:port2/api/login/oauth2/code/discord?code=${searchParams.get("code")}&state=${searchParams.get("state")}`,
      {
        credentials: "include",
      }
    )
      .then((res) => res.json())
      .then((data) => console.log(data))
    
    请求头内容:
    GET /api/login/oauth2/code/discord?code=...&state=... HTTP/1.1
    Host: sss.test:8081
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:108.0) Gecko/20100101 Firefox/108.0
    Accept: */*
    Accept-Language: pl,en-US;q=0.7,en;q=0.3
    Accept-Encoding: gzip, deflate
    Referer: http://localhost:5173/
    Origin: http://localhost:5173
    Connection: keep-alive
    Pragma: no-cache
    Cache-Control: no-cache
    

结果对比

  • 预期结果:fetch请求需携带步骤2中设置的oauth2_auth_request Cookie,以验证授权流的两次请求来自同一源
  • 实际结果:Cookie未被携带

观察结果

  • 直接在浏览器地址栏访问http://test.local:port2/api/login/oauth2/code/discord?code=...&state=...时,Cookie会被正常携带
    请求头内容:
    GET /api/login/oauth2/code/discord?code=...&stat=... HTTP/1.1
    Host: sss.test:8081
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:108.0) Gecko/20100101 Firefox/108.0
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
    Accept-Language: pl,en-US;q=0.7,en;q=0.3
    Accept-Encoding: gzip, deflate
    Connection: keep-alive
    Cookie: oauth2_auth_request=long_cookie_value
    Upgrade-Insecure-Requests: 1
    Pragma: no-cache
    Cache-Control: no-cache
    
  • 前端与后端同域名时,整个流程可正常工作

环境与配置说明

  • 仅开发环境使用HTTP,后续将切换至HTTPS
  • 因Chrome会阻止非安全环境下的SameSite=None Cookie,故在Firefox中测试
  • Spring Security CORS配置:
    ...
                .cors()
                    .configurationSource(request => {
                        final CorsConfiguration config = new CorsConfiguration().applyPermitDefaultValues();
                        config.setAllowCredentials(true);
                        config.setAllowedOrigins(List.of("http://localhost:5173"));
                        return config;
                    })
    ...
    
  • 前端需从该fetch请求的响应中获取JWT Token,用于后续接口认证

内容的提问来源于stack exchange,提问作者Wojciech Drzewiecki

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 21:01:36