近日,微软身份验证库(MSAL)Flutter版本(msal_auth 3.5.0)被发现存在一项关键缺陷:在多租户(multi‑tenant)配置下,acquireToken 返回的租户ID(tenant ID)不再是客户端应用所指定的目标租户ID,而是用户所属的主租户(home tenant)ID。这一行为直接违背了OAuth 2.0多租户设计规范,可能导致后端服务权限校验、资源隔离及审计日志等环节出现严重逻辑错误。
问题概述
MSAL Flutter是微软为Flutter开发者提供的跨平台身份验证库,支持Azure AD和Microsoft账户登录。在多租户场景中,应用程序通常将authority设置为common或organizations,允许任意Azure AD租户的用户登录。此时,正确的流程应返回用户实际登录的目标租户ID(即客户端应用请求的租户ID或用户所属组织的租户ID),而非用户主账号所属的“家租户”ID。
然而,自msal_auth 3.5.0版本发布后,多位开发者报告,调用acquireToken后从result.tenantId获取到的始终是home tenant ID。例如,一个租户A中的用户尝试登录租户B的应用时,返回的tenantId依然是租户A的ID。这一行为在3.4.x及更早版本中并不存在。
影响范围与潜在风险
该bug主要影响采用多租户架构的Flutter企业级应用、SaaS平台及B2B协作工具。以下是几个典型的受损场景:
-
资源访问权限错误:后端API若依赖tenantId判断用户所属租户并分配资源(如SharePoint站点、数据库分区),则可能将用户错误地映射到其home tenant的资源,导致数据泄露或功能不可用。
-
跨租户身份混淆:在多租户组织中,外部合作者(Guest用户)登录后,系统可能将其识别为home tenant成员,从而授予不当权限。
-
审计与合规失效:基于租户ID的日志系统会记录错误来源,导致安全事件溯源困难,甚至违反数据主权法规(如GDPR)。
-
第三方集成失效:与Azure AD B2B、Microsoft Graph API等依赖正确tenantId的组件交互时,身份令牌(token)中的
tid声明与客户端获取的ID不一致,可能触发验证失败。
官方承认与社区反馈
该问题已在MSAL Flutter GitHub仓库(issue #2142)中被正式记录。微软开发团队确认了该复现步骤,并指出问题源自3.5.0版本对Token缓存键(cache key)计算逻辑的重构——该重构意外地使用了home_account_id而非client_info中的目标租户ID。微软承诺将在下一个补丁版本(3.5.1)中修复,但截至发稿尚未公布具体发布时间表。
部分开发者尝试透过本地补丁恢复旧版行为:通过修改msal_flutter的源代码,将缓存键的租户部分强制设为result.tenantId的原始取值。然而,此类修补在库升级时会被覆盖,且可能引入新的缓存冲突。
临时规避方案
针对受影响的生产环境,微软建议采取以下措施:
-
降级至3.4.0版本:这是目前最可靠的方案,只需在
pubspec.yaml中锁定版本即可。但需注意3.4.0可能缺少后续的安全更新。 -
手动从id token中提取租户ID:在
AuthenticationResult返回后,忽略其tenantId属性,转而解析idToken.raw中的tid声明。代码示例:final tid = JwtDecoder.decode(result.idToken)['tid']; -
调整后端验证逻辑:暂时放宽对
tenantId的完全信任,结合iss(issuer)字段的URL路径来推断租户(例如https://login.microsoftonline.com/{tenant}/v2.0),但这会增加复杂性和维护成本。
行业建议
此次事件再次凸显了身份验证库在多租户场景下的脆弱性。对于依赖MSAL Flutter的企业,建议:
- 建立预发布环境的集成测试,尤其针对跨租户登录、访客用户等边界场景。
- 在代码中显式声明对返回角色的检查,避免盲目信任库的版本更新。
- 关注GitHub issue及官方更新,在3.5.1发布后尽快验证修复效果。
截至本文创作时,MSAL Flutter 3.5.0已累计超过2000次下载,受影响应用可能已达数百个。开发者应尽快评估自身应用是否处于风险中,并根据业务紧急程度选择降级或手动修复。微软预计在两周内推出修复版,届时我们将第一时间跟进报道。