修改密码后Azure ChainedTokenCredential在本地开发环境验证失败
我完全理解你遇到的困扰——改密码后,Azure环境里的代码正常运行,但本地测试Function App时,ChainedTokenCredential搭配DefaultAzureCredential就抛出AADSTS50173错误,而且试了不少清缓存、重启的操作都没解决。咱们从错误根源和具体解决步骤来梳理:
错误原因分析
从报错信息里的AADSTS50173可以明确:你之前的身份授权令牌因为密码重置被吊销了,但本地的SharedTokenCacheCredential(DefaultAzureCredential会自动尝试的凭据来源之一)还保留着旧的缓存令牌,导致每次验证都用失效的令牌,触发报错。
针对性解决步骤
1. 清除Windows凭据管理器中的Azure缓存(关键步骤)
这一步是你之前可能没覆盖到的,SharedTokenCache的凭据会存在Windows凭据管理器里:
- 打开控制面板 → 用户账户 → 凭据管理器 → Windows凭据
- 找到所有包含
Microsoft Azure、Azure AD或Shared Token Cache的条目,全部删除这些旧凭据
2. 重新登录所有Azure相关工具
- 打开终端,运行
az login,输入你的新密码完成重新登录,确保Azure CLI获取到新的有效令牌 - 在VS Code中,打开Azure扩展,点击左侧边栏的账户图标,选择重新登录,用新密码完成验证
3. 验证并调试凭据获取逻辑
如果还是有问题,可以临时修改代码,强制使用交互式登录来确认新密码能正常工作:
def get_client(): from azure.identity import InteractiveBrowserCredential # 强制弹出浏览器进行交互式登录,确保用新密码获取令牌 credential = InteractiveBrowserCredential() storageurl = os.environ["STORAGE_ACCOUNT"] client = BlobServiceClient(storageurl, credential=credential) return client
运行这段代码后,会自动打开浏览器让你重新登录,若能正常连接存储账户,说明问题确实是旧缓存未清理干净。
4. 调整DefaultAzureCredential的尝试顺序(可选)
如果你不想依赖SharedTokenCacheCredential,可以在初始化DefaultAzureCredential时排除它,或者调整优先级:
from azure.identity import DefaultAzureCredential, ExcludeSharedTokenCacheCredential, ManagedIdentityCredential def get_client(): # 排除SharedTokenCacheCredential,避免旧缓存干扰 default_credential = DefaultAzureCredential(exclude_shared_token_cache_credential=True) credential_chain = ChainedTokenCredential(ManagedIdentityCredential(), default_credential) storageurl = os.environ["STORAGE_ACCOUNT"] client = BlobServiceClient(storageurl, credential=credential_chain) return client
关于DefaultAzureCredential的凭据来源说明
你提到的疑问很关键:DefaultAzureCredential会按固定顺序尝试多个凭据来源(不同SDK版本顺序略有差异),包括:
- 环境变量(EnvironmentCredential)
- 托管标识(ManagedIdentityCredential,本地环境会自动跳过)
- 共享令牌缓存(SharedTokenCacheCredential)
- VS Code扩展凭据(VisualStudioCodeCredential)
- Azure CLI凭据(AzureCliCredential)
- 交互式浏览器登录(InteractiveBrowserCredential)
之前你改密码后,共享令牌缓存里的旧令牌没有自动失效,而DefaultAzureCredential优先尝试了这个失效的缓存,导致报错。清除Windows凭据管理器里的相关条目,就能彻底移除这些旧缓存。
内容的提问来源于stack exchange,提问作者warnerm06

