使用itfoxtec-identity-saml2时Fetch请求触发SAML2跨域CORS问题
SAML2认证Fetch请求触发CORS错误,无法跳转至Azure AD的解决办法
问题场景
后端基于itfoxtec-identity-saml2库实现了SAML2认证流程:
- 直接在浏览器访问登录接口URL时,可正常跳转至Azure AD完成认证,之后返回后端完成服务器端登录
- 通过Chrome的Fetch请求调用该接口时,触发CORS错误,且完全不会跳转到login.microsoftonline.com
原代码示例
前端代码
doSamlRedirect =() => { // 直接在浏览器访问该URL可正常跳转至login.microsoftonline.com,完成认证后返回后端并在数据库中完成用户登录,但Fetch请求会触发CORS错误 const url = 'https://suite.mytestserver.us/auth/api/sso/login?tenant_name=fresh&client_id=client&grant_type=sso&user_type=user'; fetch(url, { method: 'GET', mode: 'cors', credentials: 'include', // 跨域请求中包含Cookie }) .then(response => { // 浏览器应自动跟随重定向,理论上无需显式处理CORS? }) // eslint-disable-next-line no-console .catch(error => console.error('Error:', error)); };
后端控制器代码
[Route("login")] public IActionResult Login([FromQuery] SamlLoginInfo info) { return externalAuthenticationService.RedirectToLogin(info); }
后端服务代码
public IActionResult RedirectToLogin(LoginInfo loginInfo) { var binding = new Saml2RedirectBinding(); // RelayStateQuery存储需要往返于身份提供商的信息 var roundTripInfo = new Dictionary<string, string> { { Constants.TenantName, (loginInfo as SamlLoginInfo).TenantName } }; binding.SetRelayStateQuery(roundTripInfo); config.SigningCertificate = null; var saml2Request = new Saml2AuthnRequest(config); return binding.Bind(saml2Request).ToActionResult(); // 此方法返回302重定向响应,由控制器发送至浏览器 }
问题分析与解决办法
Fetch请求属于AJAX跨域请求,浏览器会先发送OPTIONS预检请求,而后端SAML登录接口返回的是302重定向,不符合CORS规范的响应要求,导致预检失败触发CORS错误;同时Fetch请求默认不会自动跟随重定向到跨域第三方站点,这也是无法跳转的核心原因。
尝试配置.NET后端CORS规则但无法正确发送access-control-headers后,将前端代码改为直接使用页面跳转方式,问题解决:
doSamlRedirect =() => { const url = 'https://suite.mytestserver.us/auth/api/sso/login?tenant_name=fresh&client_id=client&grant_type=sso&user_type=user'; window.location.href = url; };
这种方式属于浏览器原生页面跳转,不属于AJAX跨域请求范畴,会直接触发后端返回的302重定向,正常跳转至Azure AD登录页面完成认证流程。
内容的提问来源于stack exchange,提问作者David Haner
相关产品推荐
相关产品推荐

