Permissions in Azure DocumentDB

Azure DocumentDB is a fully managed document database in the Microsoft Azure platform. I provided an introduction to DocumentDB in a previous post. As with any publically available resource it is essential that appropriate security measures are taken to avoid unwanted access to DocumentDB resources. To support this, all operations against a DocumentDB resource must be authenticated.

Authentication

Like many Internet services, DocumentDB uses HMAC authentication in which a secret account key is hashed with various entropy-inducing properties of a request and the subsequent base-64 encoded hash is sent with the operation. The DocumentDB service then uses the same key and properties to generate a hash that it compares with the one sent. The operation is authenticated successfully if the two match, otherwise there is an authentication failure and the operation is rejected.

Like the Azure Storage Service, DocumentDB provides two equally-privileged account keys to allow regular key rollover to facilitate key regeneration and rollover. That is, the key not being used currently can be regenerated to provide a new value and this can be swapped in for the current key on a periodic basis.

The problem with HMAC authentication is that the account key typically provides full administrative privileges to the service – so great care must be taken to ensure that it is never compromised. This specifically means it should never be provided in a client or mobile application, where it could be compromised. A common solution for Internet services that need to provide broad but secure access to resources is the use of a shared-access key that is generated using the account key to provide restricted access to a resource for those in possession of the shared-access key – without the need to share the account key with them. This shared-access key could be provided on an as needed basis through some web service. eBook downloads are often downloaded using a shared-access key provided as part of the query string.

Users

DocumentDB supports the creation of users inside a database, and these users may be restricted to read-only operations against one or more resources in the database.

The User class is declared:

 public sealed class User : Resource {
 public string PermissionsLink { get; }
}

PermissionsLink is the self-link of any permissions associated with the user.

The following example creates a User:

 User user = new User {
 Id = username
 };
 
ResourceResponse<User> response =
 await documentClient.CreateUserAsync(
 database.SelfLink, user);
user = response;
 

Permissions

DocumentDB supports the concept of a permission on a resource. The Permission class is declared:

 public class Permission : Resource {
 public string ResourceLink { get; set; }
 [JsonConverter(typeof (StringEnumConverter))]
 public PermissionMode PermissionMode { get; set; }
 public string Token { get; }
}

ResourceLink is the self-link specifying the resource to which the Permission applies. PermissionMode is an enum, with values Read and All, which specifies the extent of the permission. Read restricts this permission to provide read-only access to the resource while All allows any access to the resource. The Token is generated by passing the self-link of a user and a Permission object, specifying the ResourceLink and PermissionMode, into the DocumentClient.CreatePermissionAsync() method.

The generated Token is a resource key that can be used instead of the account key to provide the user either read-only permission or all permissions on a specific resource (or its descendants). For example, a resource key allowing read-only access to a document collection also allows read access to documents in the collection. With the REST API, it can be used in place of the account key in the Authentication header for those operations that support the use of resource keys. For the .NET API, the resource key can be used to create a DocumentClient object that can be used to provide access for those resources for which the user has permission. Note that, unlike the account key, the resource key can be used without any knowledge of the DocumentDB account name.

The following example creates a permission and associates it with the specified user, providing read-only access to the specified resource for that user.

 RequestOptions requestOptions = new RequestOptions() {
 ResourceTokenExpirySeconds = 7200
};
 
String albumsResourceLink =
 "dbs/YxM9AA==/colls/YxM9ANCZIwA=/";
 
Permission permission = new Permission() {
 Id = "SomePermission",
 ResourceLink = albumsResourceLink,
 PermissionMode = PermissionMode.Read
};
 
ResourceResponse<Permission> permissionResponse =
 await theDocumentClient.CreatePermissionAsync(
 user.SelfLink, permission, requestOptions);
permission = permissionResponse;
 

The resource token is contained in the Permission object returned by CreatePermissionAsync() . By default, the resource token is valid for 1 hour but can be modified, with a maximum value of 5 hours. The default can be overridden by passing a RequestOption parameter, with the desired value of ResourceTokenExpiry (in seconds), into the CreatePermissionAsync() method call.

The following is an example of a resource token:

type=resource&ver=1&sig=zQuark+N32pVb+i2ompsTg==;LongKey==

DocumentClient

The DocumentClient class has several constructors supporting various ways to provide either an account key or one or more resource keys.

 public DocumentClient(Uri serviceEndpoint,
 string authKeyOrResourceToken, …);
 public DocumentClient(Uri serviceEndpoint,
 SecureString authKey, …);
 public DocumentClient(Uri serviceEndpoint,
 IDictionary<string, string> resourceTokens, …);
 public DocumentClient(Uri serviceEndpoint,
 IList<Permission> permissionFeed, …);

The first and second methods support the simple use of either an account key or a resource key to create the DocumentClient. The final two support the provision of several resource keys allowing the resulting DocumentClient object to be used to authenticate operations against multiple resources. In one form it takes a dictionary of resource keys while in the other it takes a list of permissions in the form of a feed.

Summary

Azure DocumentDB provides two type of keys to authenticate operations performed on it - account keys and resource keys. The account key is simplest but since it is the administrator key its loss may have significant consequences. It should never be shared in a client or mobile application due to the high risk of it being compromised. A resource key is an authentication token that  provides time-limited access to a specific user for a specified set of DocumentDB resources. These restrictions make it suitable for sharing with client or mobile applications.