Share via


Resource tokens in Azure Cosmos DB

APPLIES TO: NoSQL MongoDB Cassandra Gremlin Table

Resource tokens are credentials that can provide specific access to containers, partitions keys, or items. They can be fine-tuned to grant specific permissions on a per-user basis and work directly with the REST API for Azure Cosmos DB. Resource tokens provide an alternative to authentication using primary or secondary keys configured for read/write or read-only access.

Important

Microsoft recommends that you use the most secure authentication flow available. The authentication flow described in this procedure requires a very high degree of trust in the application, and carries risks that are not present in other flows. You should only use this flow when other more secure flows, such as managed identities, aren't viable.

For Azure Cosmos DB, Microsoft Entra authentication is the most secure authentication mechanism available. Review the appropriate security guide for your API:

The native Azure Cosmos DB client libraries handle resource token generation and management directly. However, if you use REST, you must construct the request/authentication headers yourself. For more information on creating authentication headers for REST, see access control on Azure Cosmos DB resources in REST.

Prerequisites

  • An existing Azure Cosmos DB account
  • .NET 8 SDK (or later)

Create a user and permission

First, you must create a user using the Azure Cosmos DB for NoSQL SDK. Then, you can create a permission for the user.

Note

Many APIs, like Cassandra and Gremlin, do not expose an interface through their native SDKs to create resource tokens. To use resource tokens, you must use the NoSQL SDKs to interface with your account endpoint regardless of the API you selected.

  1. Obtain the NoSQL endpoint and one of the account's read-write keys from your existing account.

  2. Add the 3.x version of the Microsoft.Azure.Cosmos package to your .NET project.

    dotnet add package Microsoft.Azure.Cosmos --version 3.*
    
  3. Add a using block for the Microsoft.Azure.Cosmos namespace.

    using Microsoft.Azure.Cosmos;
    
  4. Create a new client specifying your account NoSQL endpoint and a read-write key.

    CosmosClient client = new(
        accountEndpoint: "<account-nosql-endpoint>",
        authKeyOrResourceToken: "<account-read-write-key>"
    );
    

    Note

    You must use the NoSQL endpoint for your account that typically is in this format: https://<account-name>.documents.azure.com:443/.

  5. Get your database and container objects.

    Database database = client.GetDatabase("<database-name>");
    Container container = database.GetContainer("<container-name>");
    
  6. Create a new user within the database specifying the name of the user.

    User user = await database.CreateUserAsync("demo-user");
    
  7. Create a new permission for the user specifying the permission mode (Read or All), a unique identifier, the scoped container, and an optional partition key scope.

    PermissionProperties permissionProperties = new(
        id: "read-permission",
        permissionMode: PermissionMode.All,
        container: container,
        resourcePartitionKey: new PartitionKey("partition-key-value")
    );
    Permission permission = await user.CreatePermissionAsync(permissionProperties);
    

Obtain a resource token

Now, use the NoSQL SDK again to get a resource token from the account.

PermissionResponse response = await permission.ReadAsync();
string resourceToken = response.Resource.Token;

Use the resource token

Finally, you can use the native SDK for your API to use the resource token.

using Microsoft.Azure.Cosmos;

CosmosClient client = new(
    accountEndpoint: "<account-nosql-endpoint>",
    authKeyOrResourceToken: "<resource-token>"
);

Container container = client.GetContainer("<database-name>", "<container-name>");

var iterator = container.GetItemQueryIterator<dynamic>("SELECT * FROM c");

while (iterator.HasMoreResults)
{
    foreach (var item in await iterator.ReadNextAsync())
    {
        Console.WriteLine(item);
    }
}