You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用客户端密钥获取适配StorageManagementClient的MSAL令牌及scope取值问题

Azure存储管理API MSAL认证问题解决方案

正确Scope值

你当前使用的是Microsoft.Azure.Management.Storage库,属于Azure资源管理器(ARM)的管理面接口,对应的MSAL客户端凭证流Scope值为https://management.azure.com/.default。

对应规则:ADAL中的resource参数值末尾追加/.default,即可得到MSAL客户端凭证流的Scope值,你ADAL代码中使用的resource是https://management.azure.com/,因此对应MSAL Scope就是https://management.azure.com/.default。

你之前尝试的Scope错误原因如下:

  • https://graph.microsoft.com/.default:用于调用Microsoft Graph接口,和ARM管理接口无关
  • https://storage.azure.com:用于调用Azure存储的数据平面接口(比如上传下载Blob),不适用于存储账户的管理操作
  • User.Read:属于Microsoft Graph的委托权限,不支持服务主体的客户端凭证流
  • 未加/.default后缀的资源地址:不符合MSAL客户端凭证流的规范要求,会直接触发异常

需要调整的配置项

  1. API权限配置
    你当前配置的Azure Storage\user_impersonation是存储数据平面的委托权限,仅适用于用户登录场景下的存储数据操作,不满足服务主体管理存储账户的需求:
  • 进入应用注册的「API权限」页,删除原有配置的Azure Storage权限
  • 添加「Azure 服务管理」的应用权限,权限名称为user_impersonation
  • 点击「授予管理员同意」完成权限激活
  1. RBAC角色分配
    进入你的Azure订阅/对应资源组的「访问控制(IAM)」页,将当前应用注册对应的服务主体添加为「存储账户贡献者」或「参与者」角色,否则即使认证成功也没有权限操作存储资源
  2. 可选优化配置
    你当前开启的「允许公共客户端流」是为桌面/移动等无密钥的公共客户端场景准备的,你使用客户端密钥的机密客户端流不需要该配置,可手动关闭,不影响现有逻辑运行。

修正后的核心代码

仅需要调整Scope数组的定义即可:

var authorityUri = new Uri($"https://login.microsoftonline.com/{TenantId}");
var app = Microsoft.Identity.Client.ConfidentialClientApplicationBuilder
    .Create(ApplicationId)
    .WithClientSecret(PrimaryClientSecretValue)
    .WithAuthority(authorityUri)
    .Build();
// 仅修改此行即可
string[] scopes = new string[] { "https://management.azure.com/.default" };

AuthenticationResult result = null;
result = app.AcquireTokenForClient(scopes)
    .ExecuteAsync()
    .ConfigureAwait(false)
    .GetAwaiter()
    .GetResult();

var appSecretCredentials = new Microsoft.Rest.TokenCredentials(result.AccessToken, result.TokenType);
var storageManagementClient = new Microsoft.Azure.Management.Storage.StorageManagementClient(appSecretCredentials);
storageManagementClient.SubscriptionId = SubscriptionId;

var allStorageAccountsResponse = storageManagementClient.StorageAccounts
    .ListWithHttpMessagesAsync()
    .ConfigureAwait(false)
    .GetAwaiter()
    .GetResult();

var allStorageAccountsList = allStorageAccountsResponse.Body.ToArray();

Console.WriteLine("Storage account list");
foreach (var currStorageAccount in allStorageAccountsList)
    Console.WriteLine(currStorageAccount.Name);

内容的提问来源于stack exchange,提问作者David Luxford

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 20:36:03