OIDC Client集成WSO2 APIM 3.2.0 iframe跨标签登出失效问题
Angular集成WSO2 API Manager 3.2.0 OIDC跨标签页同步登出修复
问题概述
Angular应用通过OIDC Client对接WSO2 API Manager 3.2.0实现身份认证,除登出流程外其余功能正常。
复现步骤
- 单浏览器标签页完成应用登录,登录成功后复制该标签页
- 在其中一个标签页执行登出操作,预期其余复制标签页同步完成登出,实际未触发同步登出逻辑
- 刷新复制出的标签页时,页面跳转至错误地址:
https://localhost:9443/authenticationendpoint/oauth2_error.do?oauthErrorCode=access_denied&oauthErrorMsg=Error+occurred+while+extracting+data+from+id+token,标签页无法自动触发登出
现有问题实现
TypeScript 代码
baseUrl = new URL(window.location.href); callbackURI = this.baseUrl.origin + '/slate/dashboard'; checkSessionURL = this.sanitizer.bypassSecurityTrustResourceUrl('https://localhost:9443/oidc/checksession' + '?client_id=' + localStorage.getItem('client_id') + '&redirect_uri=' + this.callbackURI); constructor(private sanitizer: DomSanitizer, private authService: AuthService) { } ngOnInit(): void { } ngAfterViewInit(): void { if (this.authService.isLoggedUser()) { this.checkSession(); } } isIFrame = (input: HTMLElement | null): input is HTMLIFrameElement => input !== null && input.tagName === 'IFRAME' /** * Invoke check session OIDC endpoint. */ checkSession(): void { setInterval(() => { const msg = localStorage.getItem('client_id') + ' ' + localStorage.getItem('sessionState'); const frame = document.getElementById('iframeOP'); if (this.isIFrame(frame) && frame.contentWindow) { frame.contentWindow.postMessage(msg, 'https://localhost:9443/oidc/checksession'); } }, 3000); }
HTML 模板代码
<iframe title='iframeOP' id='iframeOP' [src]="checkSessionURL" ></iframe>
故障根因
- 现有会话检查逻辑仅向OP iframe发送
postMessage,未绑定消息监听接收OP返回的会话状态,无法感知会话变更触发登出 - Check Session端点URL参数未做编码,iframe未配置必要的沙箱权限,导致WSO2侧参数解析失败、跨域通信异常
- 未利用浏览器同域
storage事件做跨标签页状态同步兜底,状态感知延迟高 - 本地登出逻辑未完整清理失效的OIDC凭证,刷新页面时携带无效id_token请求WSO2,触发id_token解析错误
修复方案
1. 补全Check Session消息监听逻辑
新增OP消息监听,收到会话变更、错误状态时立刻触发本地登出,同时在组件销毁时清理定时器、解绑事件避免内存泄漏:
// 新增类属性 private sessionCheckTimer?: number; private sessionCheckListener?: (e: MessageEvent) => void; private storageListener?: (e: StorageEvent) => void; ngAfterViewInit(): void { if (this.authService.isLoggedUser()) { this.bindSessionCheckListener(); this.bindStorageSyncListener(); this.checkSession(); } } ngOnDestroy(): void { if (this.sessionCheckTimer) clearInterval(this.sessionCheckTimer); if (this.sessionCheckListener) window.removeEventListener('message', this.sessionCheckListener); if (this.storageListener) window.removeEventListener('storage', this.storageListener); } /** * 绑定OP会话状态消息监听 */ bindSessionCheckListener(): void { this.sessionCheckListener = (e: MessageEvent) => { // 过滤非WSO2来源的非法消息 if (e.origin !== 'https://localhost:9443') return; const res = e.data?.trim(); // 会话变更/校验失败时触发本地登出 if (res === 'changed' || res === 'error') { this.authService.logoutLocal(); } }; window.addEventListener('message', this.sessionCheckListener); }
2. 修正Iframe与Check Session URL配置
对URL参数做编码,给iframe添加必要沙箱权限,同时隐藏iframe避免影响页面布局:
<iframe title='iframeOP' id='iframeOP' [src]="checkSessionURL" sandbox="allow-scripts allow-same-origin" style="display: none;" ></iframe>
修正TS中Check Session URL的拼接逻辑,避免特殊字符导致参数解析失败:
const clientId = encodeURIComponent(localStorage.getItem('client_id') || ''); const redirectUri = encodeURIComponent(this.callbackURI); this.checkSessionURL = this.sanitizer.bypassSecurityTrustResourceUrl( `https://localhost:9443/oidc/checksession?client_id=${clientId}&redirect_uri=${redirectUri}` );
3. 新增跨标签页存储事件监听兜底
同域下localStorage变更会向所有同域标签页触发storage事件,通过该机制可快速感知其他标签页的登出动作:
/** * 绑定跨标签页存储变更监听 */ bindStorageSyncListener(): void { this.storageListener = (e: StorageEvent) => { // 监听到凭证被清空时直接触发本地登出 if (['access_token', 'id_token', 'sessionState'].includes(e.key || '') && !e.newValue) { this.authService.logoutLocal(); } }; window.addEventListener('storage', this.storageListener); }
4. 完善本地登出逻辑
本地登出方法需按顺序执行以下操作,避免触发WSO2 id_token解析错误:
- 清理定时器、解绑所有事件监听
- 清空localStorage/sessionStorage中存储的所有OIDC凭证(client_id、sessionState、access_token、id_token、用户信息缓存)
- 跳转至应用登录页,不要携带失效凭证请求WSO2认证端点
注意:WSO2 API Manager 3.2.0对session_state格式校验严格,登录成功后需完整存储OP返回的原始session_state值,不得做截断、转义处理,否则Check Session接口会持续返回错误状态。
内容的提问来源于stack exchange,提问作者ONE_FE
相关产品推荐
相关产品推荐

