Access control in the Azure Cosmos DB SQL API

Azure Cosmos DB is a fully managed NoSQL database service for modern app development. This article covers the SQL API for Azure Cosmos DB. Access to resources in the SQL API is governed by a master key token or a resource token. To access a resource, the selected token is included in the REST authorization header, as part of the authorization string.

Master key tokens

The master key token is the all access key token that allows users to have full control of Cosmos DB resources in a particular account. The master key is created during the creation of an account. There are two sets of master keys, the primary key and the secondary key. The administrator of the account can then exercise key rotation using the secondary key. In addition, the account administrator can also regenerate the keys as needed. For instructions on regenerating and rolling keys, see Secure access to data in Azure Cosmos DB.

Resource tokens

Resource tokens are created when users in a database are set up with access permissions for precise access control on a resource, also known as a permission resource. A permission resource contains a hash resource token constructed with the information regarding the resource path and access type a user has access to. The permission resource token is time bound and the validity period can be overridden. When a permission resource is acted upon on (POST, GET, PUT), a new resource token is generated. For information on permissions and resource tokens, see Operations on Cosmos DB Permissions.

Authorization header

All REST operations, whether you're using a master key token or resource token, must include the authorization header with the authorization string in order to interact with a resource. The authorization string has the following format:

type={typeoftoken}&ver={tokenversion}&sig={hashsignature}  

An authorization string looks like this example:

type=master&ver=1.0&sig=5mDuQBYA0kb70WDJoTUzSBMTG3owkC0/cEN4fqa18/s=  

The parts enclosed in brackets are as follows:

  • {typeoftoken} denotes the type of token: master, resource, or aad(if you are using Azure Cosmos DB RBAC).

  • {tokenversion} denotes the version of the token, currently 1.0.

  • {hashsignature} denotes the hashed token signature or the oauth token if you are using Azure Cosmos DB RBAC.

The authorization string should be encoded before adding it to the REST request to ensure that it contains no invalid characters. Ensure that it's Base64 encoded using MIME RFC2045. Also, the master key used in the hashsignature should be decoded using MIME RFC2045 as it's Base64 encoded. If you see any issues with authorization, see how to Diagnose and troubleshoot unauthorized exceptions.

Constructing the hashed token signature for a master token

The hash signature for the master key token can be constructed from the following parameters: Verb, ResourceType, ResourceLink, and Date.

  1. The Verb represents the HTTP verb of your request. Possible values are: get, post, put, patch, delete

Note:: The values must be lowercase.

  1. The ResourceType portion of the string identifies the type of resource that the request is for. Possible values are:
    • Database operations: dbs
    • Container operations: colls
    • Stored Procedures: sprocs
    • User Defined Functions: udfs
    • Triggers: triggers
    • Users: users
    • Permissions: permissions
    • Item level operations: docs

Note: The values are case sensitive and must be lowercase.

  1. The ResourceLink portion of the string is the identity property of the resource that the request is directed at. The ResourceLink value is dependent on the operation you are trying to execute. Each operation will have its own corresponding ResourceLink following this convention:
    • If the operation is performed against a specific resource then the value is the link to that resource. Examples:

      • For Get Database use: dbs/{databaseId}
      • For Get Document use: dbs/{databaseId}/colls/{containerId}/docs/{docId}
    • If the operation is performed against a set of resources (List, Create, Query) then the value is the link of the parent resource. Examples:

      • For Create Document use: dbs/{databaseId}/colls/{containerId}
      • For Create Stored Procedure use: dbs/{databaseId}/colls/{containerId}
      • For Create a Container use: dbs/{databaseId}
      • For Create Database use: "" -> an empty string since Databases do not have a parent resource

Note: The resource names that are being referenced as part of the ResourceLink value are case sensitive and must match the casing of how they were declared in the database. The other components must be lowercase.

  1. The Date portion of the string is the UTC date and time the message was sent (in "HTTP-date" format as defined by RFC 7231 Date/Time Formats), for example, "Tue, 01 Nov 1994 08:12:31 GMT".

    In C#, it can be obtained by using the "R" format specifier on the DateTime.UtcNow value.

    This same date(in same format) also needs to be passed as x-ms-date header in the request.

Note: The value is case sensitive and must be all lowercase.

To compute the signature we use the SHA256 based Hash-based Message Authentication Code (HMAC) function with the CosmosDB Key as the secret.

The payload for the hashing function is based on the 4 components presented above using the following format: "{verb}\n{resourceType}\n{resourceLink}\n{date}\n\n" (note the extra new line at the end of the payload).

The Base64 encoded result of the function will be used as the signature when constructing the Authorization header for the call.

Example [C#] for a valid Authorization header:

    httpClient.DefaultRequestHeaders.Clear();
    httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
    httpClient.DefaultRequestHeaders.Add("authorization", auth); //generated using method below
    httpClient.DefaultRequestHeaders.Add("x-ms-date", requestDateString);
    httpClient.DefaultRequestHeaders.Add("x-ms-version", "2018-12-31");

Example [C#] method to generate a valid Authorization signature:

To see complete samples for Cosmos DB REST API visit Cosmos DB REST API Samples repo on GitHub

  
string GenerateMasterKeyAuthorizationSignature(HttpMethod verb, ResourceType resourceType, string resourceLink, string date, string key)
{
    var keyType = "master";
    var tokenVersion = "1.0";
    var payload = $"{verb.ToString().ToLowerInvariant()}\n{resourceType.ToString().ToLowerInvariant()}\n{resourceLink}\n{date.ToLowerInvariant()}\n\n";

    var hmacSha256 = new System.Security.Cryptography.HMACSHA256 { Key = Convert.FromBase64String(key) };
    var hashPayload = hmacSha256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(payload));
    var signature = Convert.ToBase64String(hashPayload);
    var authSet = WebUtility.UrlEncode($"type={keyType}&ver={tokenVersion}&sig={signature}");

    return authSet;
}
  

Example [Node.js]:

  
var crypto = require("crypto");  
  
function getAuthorizationTokenUsingMasterKey(verb, resourceType, resourceId, date, masterKey) {  
    var key = new Buffer(masterKey, "base64");  
  
    var text = (verb || "").toLowerCase() + "\n" +   
               (resourceType || "").toLowerCase() + "\n" +   
               (resourceId || "") + "\n" +   
               date.toLowerCase() + "\n" +   
               "" + "\n";  
  
    var body = new Buffer(text, "utf8");  
    var signature = crypto.createHmac("sha256", key).update(body).digest("base64");  
  
    var MasterToken = "master";  
  
    var TokenVersion = "1.0";  
  
    return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);  
}  
  

Example Encoding:

Argument Value
Verb GET
Resource Type "dbs"
Resource Link "dbs/ToDoList"
Date Thu, 27 Apr 2017 00:51:12 GMT
Key dsZQi3KtZmCv1ljt3VNWNm7sQUF1y5rJfC6kv5Jiwv
W0EndXdDku/dkKBp8/ufDToSxLzR4y+O/0H/t4bQtVNw==
Key Type master
Token Version 1.0
Output Authorization String type%3dmaster%26ver%3d1.0%26sig%3dc09PEVJr
gp2uQRkr934kFbTqhByc7TVr3OHyqlu%2bc%2bc%3d

Constructing the hash signature for a resource token

Resource tokens must be generated by an intermediate server. The server serves as the master-key guardian and generates time-constrained tokens for untrusted clients, such as web browsers.

This server performs the following steps:

  1. Handles incoming client requests for new tokens.

  2. Verifies client identity in an application-specific way.

  3. If the client authenticates successfully, it uses the Cosmos DB interfaces (SDK or REST) to generate a new time-limited token and returns it to the client.

See Also