public virtual async Task <string> GetTokenAsync(SasTokenGenerationModel model)
        {
            if (model.Claims.Any(c => c.Type == "token"))
            {
                var tenant   = model.Claims.FindFirstOrEmptyValue("tenant");
                var resource = model.Claims.FindFirstOrEmptyValue("resource");
                var path     = model.Claims.FindFirstOrEmptyValue("prefix");
                var purpose  = model.Claims.FindFirstOrEmptyValue("purpose");

                var tokens = model.Claims.Where(k => k.Type == "token").Select(t => t.Value).ToList();

                if (path.IsPresent())
                {
                    var blob = model.Blob;
                    if (blob == null)
                    {
                        var account = await _storage.GetStorageAccountAsync(tenant, purpose);

                        var container = account.CreateCloudBlobClient()
                                        .GetContainerReference(await _containers.GetContainerNameAsync(tenant, purpose, resource));
                        blob = container.GetBlockBlobReference(path);
                    }

                    await blob.LoadTokensAsync(tokens);

                    await blob.SaveTokensAsync(tokens);
                }
                else
                {
                    var account = await _storage.GetStorageAccountAsync(tenant, purpose);

                    var container = account.CreateCloudBlobClient()
                                    .GetContainerReference(await _containers.GetContainerNameAsync(tenant, purpose, resource));

                    await container.FetchAttributesAsync();

                    if (container.Metadata.ContainsKey("token"))
                    {
                        tokens.AddRange(container.Metadata["token"].Split(','));
                    }

                    container.Metadata["token"] = string.Join(",", tokens);

                    await container.SetMetadataAsync();
                }
            }

            var body = string.Format("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.{0}",
                                     Base64UrlEncode(string.Format("{{{0}}}", string.Join(",", model.Claims.GroupBy(o => o.Type).OrderBy(o => o.Key).Select(GetStringProperty)))));

            var keys = await _keyProvider.Value;

            using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String(keys.Primary)))
            {
                var signature = Base64UrlEncode(hmacSha256.ComputeHash(Encoding.UTF8.GetBytes(body)));
                return(string.Format("{0}.{1}", body, signature));
            }
        }
        protected virtual async Task <string> GetTokenIdsAsync(string tenant, string purpose, string resource, string prefix)
        {
            IDictionary <string, string> md;

            var account = await _storage.GetStorageAccountAsync(tenant, purpose);

            var blobClient    = account.CreateCloudBlobClient();
            var blobContainer = blobClient.GetContainerReference(await _containers.GetContainerNameAsync(tenant, purpose, resource));

            if (prefix.IsPresent())
            {
                var blob = blobContainer.GetBlockBlobReference(prefix);
                await blob.FetchAttributesAsync();

                md = blob.Metadata;
            }
            else
            {
                await blobContainer.FetchAttributesAsync();

                md = blobContainer.Metadata;
            }
            string tokens;

            md.TryGetValue("token", out tokens);
            return(tokens);
        }