开启withCredentials:true后HttpOnly Refresh Token Cookie未随请求发送求助
我为C# API实现了基于Refresh/Access Token的请求认证机制,但React前端发起刷新请求时,HttpOnly类型的Refresh Token Cookie未出现在请求头中,导致接口返回400错误提示“refresh token not present”。
登录流程(已确认正常)
用户调用登录接口时,响应Payload返回Access Token,同时浏览器通过Set-Cookie设置HttpOnly的Refresh Token Cookie,代码如下:
Response.Cookies.Append( key: refreshTokenKey, value: _jwtTokenManager.GenerateToken(account.Id, TokenType.Refresh), options: new CookieOptions { HttpOnly = true, Secure = true, SameSite = SameSiteMode.None }); return Ok(response);
已通过浏览器响应头的Set-Cookie字段确认Cookie设置成功。
问题复现
React端通过Axios发送刷新请求时,接口返回400状态码,提示Refresh Token不存在:
const refresh = async () => { const response = await axios.get(`/Accounts/refresh/${account?.id}`, { withCredentials: true }) console.log(response) setAccount(previousState => ({ ...previousState, accessToken: response.data.accessToken })); return response.data.accessToken }
后端刷新接口代码
[HttpGet("refresh/{id:guid}")] public IActionResult RefreshAccessToken (string id) { string cookiesHeader = Request.Headers["Cookie"]; Console.WriteLine("Cookie Header: " + cookiesHeader); Request.Cookies.TryGetValue(refreshTokenKey, out string refreshToken); if (string.IsNullOrEmpty(refreshToken)) { return BadRequest("refresh token not present"); } if (_jwtTokenManager.VerifyToken(refreshToken, TokenType.Refresh) == false) { return BadRequest("refresh token not valid"); } string newAccessToken = _jwtTokenManager.GenerateToken(id, TokenType.Access); return Ok(new { accessToken = newAccessToken }); }
CORS配置
builder.Services.AddCors(options => { options.AddPolicy(name: PolicyName, policy => { policy.WithOrigins("https://localhost:3000").AllowAnyMethod().AllowAnyHeader().AllowCredentials(); }); });
请求未携带HttpOnly的Refresh Token Cookie,无法定位问题,求帮忙排查。
排查方向:
补全Cookie的Domain/Path设置:
登录接口设置Cookie时未指定Domain和Path,浏览器可能将Cookie绑定到登录接口的具体路径,导致刷新接口请求时不会携带。建议在CookieOptions中添加Path = "/";若前后端域名不同,需指定共用的根域名作为Domain值。验证Secure Cookie的传输环境:
已设置Secure = true,意味着Cookie仅通过HTTPS传输。需确认后端API是否同样使用HTTPS协议,若后端为HTTP,浏览器会拒绝发送Secure Cookie。检查SameSite配置兼容性:
SameSite = SameSiteMode.None需配合Secure = true使用,这部分已满足,但部分旧浏览器对None的支持存在问题,可查看浏览器控制台是否有相关警告。确认CORS策略的生效顺序:
需确保app.UseCors(PolicyName)在中间件管道中的位置正确——应放在app.UseRouting()之后、app.UseAuthorization()之前,否则CORS策略不会生效。直接验证浏览器Cookie存储:
在浏览器开发者工具的Application -> Cookies中,检查Refresh Token是否存在,以及它的Domain、Path、Secure、HttpOnly属性是否符合预期。若Cookie不存在或属性异常,说明登录接口的Set-Cookie逻辑存在问题。
内容的提问来源于stack exchange,提问作者Bradley

