Working with the Azure DocumentDB REST API Authorization headers

[DocumentDB](https://docs.microsoft.com/en-us/azure/documentdb/" target="_blank) is Azure's NoSQL offering that provides an exception service when it comes to working with non relational data. I've recently had a request to work on a project that uses DocumentDB but relies solely on the REST API to interact with the service.

This is absolutely fine, since every service on Azure is built on top of a corresponding REST Api. Even the SDKs seem to be thin wrappers around the REST Api hiding away all the "ugliness" and complexity. Why did I say ugliness and complexity?

Because if you ever had to work with the Azure REST API and had to go through the Authorization HTTP Header hell, you'll know what I'm talking about. I've done it once before with the Azure Storage APi and this time with DocumentDB. Oh, and in case you thought that solving the problem for one service, would solve it for the other ones, think again. Each Azure service has it's own authorization header requirements!

The goal of this post is to give you an idea how to generate an authorization header that you can use to execute raw HTTP calls. For example, if you have an Angular/React/Aurelia SPA that you want to use with DocDB. Every call requires an Authorization Header, so let's get cracking

Use Node.js to create the Authorization Header

The code is based on the official documentation on [managing access to DocumentDB resources](https://docs.microsoft.com/en-us/rest/api/documentdb/access-control-on-documentdb-resources" target="_blank). However, there are a few important omissions from the instructions that had me spinning for a bit until I worked it/them out.

A generic piece of code that can generate an Authorization Header for all our DocumentDB REST interactions is attached below:

The important bit is in the getAuthorizationTokenUsingMasterKey() method. You'll notice that the code has a hard dependency on the Crypto.JS library and an optional dependency on moment.js. I like moment.js for all my date/time interactions but you're free to handcraft your own dates as you see fit.

The easiest way to run the code is to load it on VS Code. You'll also need to:

  1. Install Node.js if not already present on your machine
  2. Clone the repository
  3. Run npm restore at the root of the repo
  4. Update the master key to your DocumentDB
  5. In VS Code, hit Run or Debug

Things that you need to know about

  1. The authorization header lasts for 15mins. The time is (now-1)mins to (now+14)mins = 15mins total. After that, you'll get an HTTP 403 error because your Authorization token will have expired.
    {"code":"Forbidden","message":"The authorization token is not valid at the current time. Please create another token and retry (token start time: Thu, 29 Dec 2016 23:06:51 GMT, token expiry time: Thu, 29 Dec 2016 23:21:51 GMT, current server time: Fri, 30 Dec 2016 00:19:16 GMT).\r\nActivityId: d300e774-bb79-4317-a5df-6dec7e2174ce"}

  2. The x-ms-date HTTP header is very important and needs to conform with the [RFC1123](http://www.csgnetwork.com/timerfc1123calc.html" target="_blank) format, i.e Mon, 15 Jun 2009 20:45:30 GMT

  3. The date parameter and x-ms-date header values need to be identical. If not, you'll receive the following HTTP 401 error:
    { "code": "Unauthorized", "message": "The input date header is invalid format. Please pass in RFC 1123 style date format.\r\nActivityId: 0299a1ab-ffc9-4cab-8772-53ca051021bb" }


    If this is not unintuitive then I don't know what is! I spent a lot of time trying to work out why my header was not in the "right format" until I figured out what was wrong.

  4. The HTTP verb needs to match, both in the HTTP request and the getAuthorizationTokenUsingMasterKey() verb parameter. If you need to send a GET request, then make sure that this is consistent.

  5. Make sure you read through the documentation to ensure that you're creating the right URI for the resource you want to interact with (i.e dbs, colls, docs etc). Each URI is different!

  6. The AuthorizationHeader needs to match the resource you're working with. For example, if you need to create a new Collection under a "demodb" database, then the parameters passed to the getAuthorizationTokenUsingMasterKey() should look like this:
    getAuthorizationTokenUsingMasterKey("POST", "dbs/demodb", "colls", dateWithTimeZone, masterKey);
    And your HTTP endpoint should look like this:
    https://cmtest.documents.azure.com:443/dbs/demodb/colls

    with an appropriate json payload, e.g. {"id": "mynewcollection"}

  7. There's an x-ms-version header that you need to supply with your HTTP calls. You can find more information on the different API versions [here](https://docs.microsoft.com/en-us/rest/api/documentdb/" target="_blank) but for clarity I've attached them below. You'll most likely want to go with the latest one:

  • 2016-07-11
  • 2015-12-16
  • 2015-08-06
  • 2015-06-03
  • 2015-04-08
  • 2014-08-21

With these caveats in mind, you can now call this code to retrieve the Authorization Header which can then be used to interact with the database. A typical HTTP call to retrieve all databases should look like this on [Fiddler](https://www.telerik.com/download/fiddler" target="_blank) (which I found invaluable in my quest to conquer DocDB's REST API)

Get all databases example

Give me teh codez

A full working solution can be found in my GitHub repo here [https://github.com/cmatskas/DocumentDBAuthorization](https://github.com/cmatskas/DocumentDBAuthorization" target="_blank). Feel free to fork or download and take it for a spin. There's also a C# version but I thought the Node.js solution was more appropriate in this instance.

The REST API for DocumentDB is a great way to interact with your NoSQL database and although the documentation is rough around the edges, once you get going, it becomes a lot easier. As always, feel free to email me or leave a comment below if you have any questions


  • Share this post on