Consuming Azure Cosmos DB REST API v3: troubleshoot the 401 error

REST API and Client SDK

Recently I had a need to create containers under a Cosmos database programmatically as well as to create and grants permissions for users. It turned out that the client SDK v3 for Cosmos DB REST API hasn’t had the necessary APIs yet. This means that I would have to use the REST API directly if I needed to get my job done quickly.

Why do I need the SDK anyway?

The SDK provides a user-friendly wrapper around the REST API. For someone who just started to try the REST API, its design is not straightforward at all. In order to consume the REST API, I need to build the authorization header as well as pass parameters in for all APIs correctly. The SDK is supposed to do all those things for me so that all I should care about is what containers I need and who has access to what, not the inner data model of Cosmos DB.

Troubleshoot the 401 Unauthorized error

To consume Cosmos DB’s REST API, I used the example at https://github.com/Azure/azure-cosmos-dotnet-v2/blob/master/samples/rest-from-.net/Program.cs. The trouble that was because I initially was so confused with what the endpoint, resource type, resource id, x-ms-version, and resource link should be set when I needed to call an API, e.g. the GET users API.

For the x-ms-version, the list of valid values are listed in https://docs.microsoft.com/en-us/rest/api/cosmos-db/. I needed to use the v3 version, so I set it to 2018-12-31.

The endpoint parameter should be set to https://{databaseAccount}.documents.azure.com/dbs/{databaseName}/. For example, if my Cosmos DB account is NdtCosmosAccount and I create a database named AppDb, endpoint will be https://NdtCosmosAccount.documents.azure.com/dbs/AppDb/
The key here is that even though the connection string to my database uses port 10255, the endpoint must not have the port included.

For the resource type parameter, because I wanted to GET all users, I set it to "users". The resource link parameter was also "users" because I’m getting all users

Initially, I used "AppDb" for resourceId but I got the 401 Unauthorized error. Neither the official documentation nor Google gave me a useful hint for what I was doing wrong. It was only when I looked closer to the error message returned (which admittedly what I should have done from the beginning!) that I discovered the culprit:

{"code":"Unauthorized","message":"The input authorization token can't serve the request. Please check that the expected payload is built as per the protocol, and check the key being used. Server used the following payload to sign: 'get\nusers\ndbs/AppDb\nfri, 09 aug 2019 11:15:28 gmt\n\n'\r\nActivityId: 857a30d4-02f2-4e42-afd7-b1e38dda56b8, Microsoft.Azure.Documents.Common/2.5.1"}

This means that the correct resource id must be "dbs/AppDb".

What’s next

I’m happy that I was able to finally consume Cosmos DB’s REST API, but given the trouble I had with it, I will wait for a new release of the SDK which has supports for those missing APIs then.