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

MSAL Angular SPA+ .NET API通过OBO认证Cosmos DB权限问题

问题解决方案

一、解决“用户未同意”问题(无需管理员同意)

要让用户自行授权访问Cosmos DB,需调整SPA和后端的权限配置:

1. SPA端MSAL配置修改

在登录请求和资源映射中添加Cosmos DB的委托权限scope:

MsalModule.forRoot(
    new PublicClientApplication({
        auth: {
            clientId: "obscured9",
            authority: "obscured",
            redirectUri: "http://localhost:4200",
        },
        cache: {
            cacheLocation: "localStorage",
            storeAuthStateInCookie: isIE,
        },
    }),
    {
        interactionType: InteractionType.Popup,
        authRequest: {
            scopes: ["access_as_user", "https://cosmos.azure.com/user_impersonation"], // 添加Cosmos用户模拟权限
        },
    },
    {
        interactionType: InteractionType.Popup,
        protectedResourceMap: new Map([
            ["Enter_the_Graph_Endpoint_Here/v1.0/me", ["user.read"]],
            ["https://localhost:7162", ["api://obscured/API"]],
            ["https://你的Cosmos账户域名.documents.azure.com", ["https://cosmos.azure.com/user_impersonation"]], // 映射Cosmos资源
        ]),
    }
),

2. 后端On-Behalf-Of流程调整

请求Cosmos DB的专属scope,且不要对令牌做冗余编码:

var token = _tokenResolver.GetToken(); // 来自SPA的用户令牌
// 替换为Cosmos DB的权限scope
string[] scopes = { "https://cosmos.azure.com/user_impersonation" };

string appKey = "obscured";
string clientId = "obscured";

var app = ConfidentialClientApplicationBuilder.Create(clientId)
    .WithClientSecret(appKey)
    .WithTenantId("obscured")
    .Build();
UserAssertion userAssertion = new UserAssertion(token, "urn:ietf:params:oauth:grant-type:jwt-bearer");
// 使用await避免同步调用导致的死锁
var result = await app.AcquireTokenOnBehalfOf(scopes, userAssertion).ExecuteAsync();

// 直接传入原始access token,无需双重Base64编码
var credentials = new AzureKeyCredential(result.AccessToken);
_cosmosClient = new CosmosClient("https://你的Cosmos账户域名.documents.azure.com:443/",
    credentials,
    new CosmosClientOptions
    {
        AllowBulkExecution = true,
        ApplicationName = "obscured",
        ConnectionMode = ConnectionMode.Direct,
        ConsistencyLevel = ConsistencyLevel.Session,
        RequestTimeout = new TimeSpan(0, 0, 400),
        Serializer = serializer,
        MaxRetryAttemptsOnRateLimitedRequests = 10,
        MaxRetryWaitTimeOnRateLimitedRequests = new TimeSpan(0, 0, 120)
    });

await CreateDatabaseAndContainerIfNotExistsAsync();
_isLoaded = true;

3. Azure AD应用注册配置

在Azure AD应用的API权限页面,添加Azure Cosmos DB的user_impersonation委托权限,并确认该权限的谁可以同意设置为“管理员和用户”(确保用户能自行授权)。


二、解决管理员同意后的403 RBAC错误

错误信息显示主体缺少Microsoft.DocumentDB/databaseAccounts/readMetadata权限,这是Cosmos DB的RBAC权限问题,需在Cosmos DB门户配置:

  1. 进入你的Cosmos DB账户,打开**访问控制(IAM)**页面
  2. 点击添加角色分配:
    • 角色选择:推荐Cosmos DB Account Reader(包含元数据读取权限),若需读写数据可选择Cosmos DB Built-in Data Reader/Data Contributor
    • 分配对象:选择Azure AD用户、组或服务主体,搜索错误中提到的主体ID5c4d3d80-546b-471b-bba3-de92008fc398对应的用户/主体
    • 保存角色分配,等待权限生效(通常需数分钟)

关键注意事项

  • 禁止对Cosmos的access token做双重Base64编码,AzureKeyCredential直接接收原始令牌即可
  • On-Behalf-Of流程必须请求目标资源(Cosmos DB)的scope,而非自身API的scope,否则令牌无法访问Cosmos
  • 若公司政策禁止用户自行同意部分权限,需联系管理员在Azure AD应用中为该权限授予用户范围的同意

内容的提问来源于stack exchange,提问作者Lukáš Václavek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 23:00:07