Azure / azure-sdk-for-net

This repository is for active development of the Azure SDK for .NET. For consumers of the SDK we recommend visiting our public developer docs at https://learn.microsoft.com/dotnet/azure/ or our versioned developer docs at https://azure.github.io/azure-sdk-for-net.
MIT License
5.49k stars 4.82k forks source link

[BUG] Azure Data Tables rejects Microsoft Entra authentication using Azure Cosmos DB for Table #47332

Open PeterButzelaar opened 5 hours ago

PeterButzelaar commented 5 hours ago

Library name and version

Azure.Data.Tables 12.9.1

Describe the bug

Note: this bug also existed for the Python package, but was resolved a few weeks ago.

You cannot use the Azure.Data.Tables package to authenticate to Azure Cosmos DB for Table using Managed Identity / RBAC against Entra.

Expected behavior

Using managed identity, I should be able to communicate with a CosmosDb table in Azure.

The following line of code should work without exception:

var tableServiceClient = new TableServiceClient(new Uri("https://mycosmosdb.table.cosmos.azure.com"), new DefaultAzureCredential());
var tableClient = tableServiceClient.GetTableClient("myTable");
await tableClient.GetEntityAsync<MyTableEntity>("pk", "rk");

Actual behavior

When using code the block, you will get a 401 odata error:

"odata.error":{"code":"Unauthorized","message":{"lang":"en-us","value":"Request blocked by Auth Provided AAD token is intended for [https://storage.azure.com]. This database account accepts tokens intended for [https://mycosmosdb.documents.azure.com, https://mycosmosdb.sql.cosmos.azure.com, https://mycosmosdbsqlx.cosmos.azure.com, https://cosmos.azure.com].\r\nActivityId: 885e33b1-cfea-4348-8371-dea70889b0ae, documentdb-dotnet-sdk/2.14.0 Host/64-bit MicrosoftWindowsNT/10.0.20348.0\nRequestID:885e33b1-cfea-4348-8371-dea70889b0ae\n"}}}

Workaround

The current workaround for me is to use this tokenprovider specifically for Cosmos:

class CosmosDbDefaultAzureCredential : DefaultAzureCredential
{
    public override AccessToken GetToken(TokenRequestContext requestContext, CancellationToken cancellationToken = new CancellationToken())
    {
        requestContext.Scopes[0] = "https://cosmos.azure.com/.default";
        return base.GetToken(requestContext, cancellationToken);
    }
}

Reproduction Steps

Prerequisite: the user has role Cosmos DB Built-in Data Contributor on the CosmosDb account. Role id = 00000000-0000-0000-0000-000000000002

Following code block should execute correctly.

var tableServiceClient = new TableServiceClient(new Uri("https://mycosmosdb.table.cosmos.azure.com"), new DefaultAzureCredential());
var tableClient = tableServiceClient.GetTableClient("myTable");
await tableClient.GetEntityAsync<MyTableEntity>("pk", "rk");

Environment

Ubuntu 24.04 .NET version 8.0.110

Jetbrains Rider 2024.3

github-actions[bot] commented 5 hours ago

@christothes @JonathanCrd

github-actions[bot] commented 5 hours ago

Thank you for your feedback. Tagging and routing to the team member best able to assist.