How to implement Shared Access Signatures using Azure Mobile Services and Node.js
This post will provide essential skills to enable you to use shared access signatures to upload photos as blobs. Azure mobile services using node.JS.
This is supporting documentation for an upcoming MSDN article around the creation of a raspberry pi application that is fitted with the camera and capable of uploading images to the cloud.
This same code can be used for virtually any client application that wishes to upload images to the cloud.
The end result of this post is to provide client applications a shared access signature, which is a secure and efficient way to enable client applications to upload files to the cloud.
Here are the high-level steps of this post:
Provisioning an Azure Storage Account
- Recording the account name, account key, and container name
Provisioning an Azure Mobile Service
- Adding Node.js code to it
Testing with a REST client
Related Psots
PROVISIONING AN AZURE STORAGE ACCOUNT
If a client is to upload a file storage, we need to provision a storage account
The storage account will have a name, key, and container for blobs
Hit "+" to create a new storage account.
Figure 1: Creating a new storage account
Click Quick Create
Figure 2: Choosing QUICK CREATE
Type in a unique URL.
Choose a region that you are consistent with. Mobile Services that we will provision will need the same region.
Figure 3: Specifying URL, location, etc
It will take less than 1 minute to provision.
Figure 4: Viewing progress
Click MANAGE ACCESS KEYS. We will need this later for Azure Mobile Services.
Figure 5: Managing Access Keys
Drill into the service by hitting
Figure 6: Verifying online
Choose CONTAINERS.
Figure 7: Choosing CONTAINERS
Select CREATE A CONTAINER
Provide a container name and write it down. You will need it later.
Figure 8: Providing a container name and access
Note the container name
Figure 9: Validating container creation
RECORDING THE ACCOUNT NAME, ACCOUNT KEY, AND CONTAINER NAME
Take note of the information (account name, access key, container name, etc).
Figure 10: Recording Access Keys
PROVISIONING AN AZURE MOBILE SERVICE
Provision an Azure Mobile Service account
It will be used to respond to client devices that want to upload files
It will provide a Shared Access Signature
- A shared access signature provides delegated access to resources in your storage account. This means that you can grant a client limited permissions to your blobs, queues, or tables for a specified period of time and with a specified set of permissions, without having to share your account access keys
- This allows clients to upload to storage directly on a secure fashion
Navigator mobile services and click the + to provision a new service
Figure 11: Creating a new Mobile Service
Make sure to select CREATE
Figure 12: Creating a new Mobile Service
Enter the URL for the new mobile service
We will not initially be using the database so you can select whatever you want there
Figure 13: Providing a URL, Database, etc
Provision a new SQL Database or use an existing one
We will not initially use a database so it doesn?t matter much right now.
Figure 14: Indicating database settings
It will take a few moments to provision.
Figure 15: Verifying creation of mobile service
CREATING THE NODE.JS BACKEND
Drill into to the service by hitting ->
Figure 16: Verifying mobile service is ready
From the menu below choose API
Figure 17: Creating a custom API (for get requests)
Provide a new API name. This is the API name used by clients in their web request. Leave permissions to their default values.
Figure 18: Providing an API name
Verify that you have provisioned a new API. Click the right arrow (->) to drill into the API just created.
Figure 19: Verifying API
To note is the default code below. We will replace it with our own code that returns a shared access signature
Figure 20: Viewing default API code
Here is what the code looks after you paste in the code provided below
Node.js in Azure Mobile Services 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 var azure = require('azure'); var qs = require('qs'); var blobService; // used to communicate with blob storage service var containerName; // container must exist to support photo uploads var accountName; // storage account name (you create at portal) var accountKey; // storage account key (generated for you) var blob = 'sassample' var BlobConstants = azure.Constants.BlobConstants; var ServiceClient = azure.ServiceClient; var CloudBlobClient = azure.CloudBlobClient; // Issued by Raspberry Pi // https://[you put yours here].azure-mobile.net/api/photos // With headers = "X-ZUMO-APPLICATION: [get the mobile servies app key from the portal]" // Header contains your "application key" /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // Entry point here // // /////////////////////////////////////////////////////////////////////////////////////////////////////////////// exports.get = function(request, response) { // These are part of "App Settings" in the configuration section // of your service. Shouldn't be hard-coded into this Node.js script containerName = request.service.config.appSettings.PhotoContainerName; accountName = request.service.config.appSettings.AccountName; accountKey = request.service.config.appSettings.AccountKey; // Connect to the blob service blobService = azure.createBlobService(accountName, accountKey, accountName + '.blob.core.windows.net'); createContainer(); createPolicies(); var sasResponse = GetSAS(); return request.respond(201, sasResponse); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // // /////////////////////////////////////////////////////////////////////////////////////////////////////////////// function GetSAS() { var startDate = new Date(); var expiryDate = new Date(startDate); expiryDate.setMinutes(startDate.getMinutes() + 15); var sharedAccessPolicy = { AccessPolicy: { Permissions: azure.Constants.BlobConstants.SharedAccessPermissions.WRITE, Start: startDate, Expiry: expiryDate } }; var blobService = azure.createBlobService(accountName, accountKey, accountName + '.blob.core.windows.net'); var blobname = genRandNum() + '.jpg'; var signature = blobService.generateSharedAccessSignature(containerName, blobname, sharedAccessPolicy); var sharedAccessSignature = new azure.SharedAccessSignature(blobService.storageAccount, blobService.storageAccessKey); blobService.authenticationProvider = sharedAccessSignature; sharedAccessSignature.permissionSet = [signature]; console.log('baseUrl = ' + signature.baseUrl); console.log('path = ' + signature.path); console.log('queryString = ' + encodeURIComponent(signature.queryString)); console.log('queryString = ' + signature.queryString); var sasResponse = { 'sasUrl': signature.baseUrl + signature.path + '?' + qs.stringify(signature.queryString), 'photoId': blobname, 'expiry':expiryDate }; return sasResponse; } /////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // // Purpose: Generate a random number to use in the filename // // /////////////////////////////////////////////////////////////////////////////////////////////////////////////// var genRandNum = function() { return Math.floor(Math.random() * 90000) + 10000; } Figure 21: Pasting in code
Return back to the portal main menu and choose MANAGE KEYS, as seen in the lower right corner of the diagram below.
Figure 22: Retrieving the application key
Take note that the application keys below. Clients will use these to connect to the service. Save this application key to be used later when we use a rest-based client to test our mobile service.
Figure 23: Getting the applications
STORING CONFIDENTIAL INFORMATION INSIDE APP SETTINGS
App settings is a safe and convenient way to avoid hardcoded in your node.JS scripts
It is similar to the configuration file for a web application
We will use it to store our storage account information, such as the computer name, storage account name, and access keys
ADDING APP SETTINGS
Choose CONFIGURE from the menu below
Figure 24: Configuring App Settings
Notice the app settings provided below
This information comes from the previously provisioned storage account. This information is available from the Azure storage account portal
Putting it here avoids hard coding it into our mobile service application
Figure 25: Specifying App Settings
TESTING WITH A REST CLIENT
We are now ready to begin testing our freshly created service.
There are any number of rest-based client applications to test with
The one below is a Google Chrome extension called advanced rest client
It is free and works well for testing purposes
Figure 26: Using Advanced REST Client
HOW TO USE ADVANCED REST CLIENT
Notice that there are five pieces to this
This is the URL by clients who used to request the shared access signature
- Notice the first part of the URL is the name of the mobile service
- The last part of the URL is the actual API name we provided
The request type will be GET
There needs to be one header entry is seen below.
- X-XUMO-APPLICATION is the key
- The value here is the application key for the mobile service we created
Click send to call into the mobile service API
View the shared access signature returned by the service.
- Client applications that received this signature can then upload blobs to the specified storage account
- The scenario might be a client application that wants to upload a photo using a shared access signature
Figure 27: Verifying the Shared Access Signature
Conclusion
This post illustrated all the needed steps to be able to call into a mobile services API. . It even demonstrated how to test the API using the Google Chrome extension, Advanced REST client.
You are required to provision both a Azure storage account as well as an Azure mobile service.
This post is useful for those who wish to upload blobs to Azure storage. having a shared access signature makes it easy for client applications to directly upload into Azure storage.
This post is part of a larger article coming in MSDN magazine, where we enable a raspberry pi device to upload photos to Azure storage services.