Azure应用服务托管Angular PWA时Service Worker导致Azure AD认证重定向循环
Azure应用服务托管Angular PWA 二次登录无限重定向问题
问题背景
- 应用部署形态:运行于Azure应用服务平台的Angular PWA,启用平台内置认证能力,默认对未认证请求返回
HTTP 302 Found,跳转至Azure AD授权端点完成身份校验 - 正常流程边界:首次访问场景下,Service Worker尚未加载、或被手动禁用时,全链路认证流程可正常执行
- 异常触发场景:会话超时、主动登出后重新登录时,会被反复重定向至
login.microsoftonline.com/<tenant>/oauth2/authorize?...授权页,多次尝试后控制台抛出CORS拦截报错:
Access to fetch at 'https://login.windows.net/<tenant>/oauth2/authorize?response_type=id_token&redirect_uri=https%3A%2F%2Fmy-site.azurewebsites.net%2F.auth%2Flogin%2Faad%2Fcallback&client_id=<cid>&scope=openid+profile+email&response_mode=form_post&nonce=34f9eab3fd89468cbe18a77dc0e73a75_20210407124243&state=redir%3D%252Fngsw.json%253Fngsw-cache-bust%253D0.7541325470022122' (redirected from 'https://my-site.azurewebsites.net/ngsw.json?ngsw-cache-bust=0.7541325470022122') from origin 'https://my-site.azurewebsites.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
核心异常观测
通过抓包对比Service Worker启用前后的/.auth/login/aad/callback回调请求行为,能抓到非常明显的行为差异:
未启用Service Worker的正常回调流程
Request headers: Host: my-site.azurewebsites.net Origin: https://login.microsoftonline.com Referer: https://login.microsoftonline.com/ Response headers: Location: https://my-site.azurewebsites.net/
该流程的逻辑为:Azure AD的表单POST回调正常抵达应用服务的认证回调端点,平台完成身份令牌校验、签发认证Cookie后,返回302跳转至应用首页。
启用Service Worker后的异常回调流程
Request headers: Host: login.windows.net Origin: <not there> Referer: https://login.microsoftonline.com/ Response headers: Location: https://login.microsoftonline.com/<tenant>/oauth2/authorize?response_type=id_token&redirect_uri=https%3A%2F%2Fmy-site.azurewebsites.net%2F.auth%2Flogin%2Faad%2Fcallback&client_id=<cid>&scope=openid+profile+email&response_mode=form_post&nonce=ed3797c5c85b4f1080faa31f3b597742_20210407085453&state=redir%3D%252F
出现这个偏差的根本原因是:Angular Service Worker默认会拦截所有同源请求,把本该直接走原生网络通道的认证回调、ngsw.json配置拉取请求纳入缓存判断逻辑,甚至错误代理跨域的授权跳转请求,最终导致请求头被篡改、跨域校验失败。
已尝试无效的调整
参考Angular社区已知的Service Worker导航请求相关问题,在Service Worker配置中添加"navigationRequestStrategy": "freshness",期望导航请求跳过缓存直连网络,调整后问题未得到改善。
根本原因与修复方案
根本原因
Angular Service Worker的默认路由拦截规则与Azure应用服务内置认证的302跳转逻辑存在两处核心冲突:
- Service Worker未将Azure认证端点(
/.auth/*)排除在拦截范围外,无差别拦截所有同源请求,导致回调请求被缓存逻辑篡改、甚至重定向到缓存的旧授权地址 - Service Worker对
ngsw.json这类触发302跳转的请求处理逻辑异常:当未认证用户拉取ngsw.json时,平台返回302跳转至AD授权页,SW没有正确透传跨域跳转链路,反而将跳转后的授权请求当成同源fetch请求处理,丢失必要的Origin请求头、跨域响应头,最终触发CORS拦截形成无限重定向循环
注:之前调整的navigationRequestStrategy: freshness仅对页面导航类请求生效,无法覆盖SW对API、静态资源类请求的拦截逻辑,因此无法解决问题
具体修复步骤
- 在
ngsw-config.json配置中,显式将所有/.auth/*路径加入Service Worker的放行列表,告知SW完全不要拦截、代理这些路径的请求,所有匹配该规则的请求直接走原生网络通道,配置示例:{ "assetGroups": [/* 原有静态资源缓存配置保持不变 */], "dataGroups": [ { "name": "azure-easy-auth-bypass", "urls": ["/.auth/*"], "cacheQueryOptions": { "ignoreVary": true } } ], "navigationRequestStrategy": "freshness" } - 若项目存在自定义Service Worker请求拦截逻辑,需在拦截逻辑最开头增加判断:只要请求路径匹配
/.auth/*、请求目标为AD授权域名(login.microsoftonline.com/login.windows.net),直接调用原生fetch方法放行请求,不要走任何缓存改写、代理逻辑 - 可在SW激活逻辑中增加临时校验:当检测到当前请求为
/.auth/login/aad/callback认证回调时,临时跳过本次缓存逻辑,验证是否为SW拦截导致的链路异常
内容的提问来源于stack exchange,提问作者Abhijeet Pandhe
相关产品推荐
相关产品推荐

