Gaurav Mantri's Personal Blog.

Consuming Windows Azure Service Management API in a Windows 8 Application

In this blog post, we’re going to talk about how to write a Windows 8 application which consumes Windows Azure Service Management REST API (http://msdn.microsoft.com/en-us/library/windowsazure/ee460799.aspx). Unlike my other post on Windows 8 and Windows Azure Mobile Service, I’ll try to be less dramatic :). I built a small Windows 8 application which lists the storage accounts in a subscription as a proof of concept. Since I’m more comfortable with XAML/C# than HTML5/JavaScript, I built this application using the former though in the course of exploring for this project, I did build a small prototype using HTML5/JS. I’ve included relevant code snippets of that as well.

X509 Certificates

As you know, Windows Azure Service Management REST API makes use of X509 certificate based authentication. When I started looking into it, first thing I found was that there’s no direct support for X509 certificates in .Net API for Windows 8 applications. I almost gave up on this when Mike Wood (http://mvwood.com/ & http://twitter.com/mikewo), a Windows Azure MVP pointed me to this documentation on MSDN for building Windows 8 applications: http://msdn.microsoft.com/en-us/library/windows/apps/hh465029.aspx. Well, what followed next is non-stop coding of various trials and errors :).

In short, there’s no direct support for X509 certificates in the core API (like what you have available in standard .Net API) but it does allow you to install an existing PFX certificate in your application certificate store. This is accomplished via ImportPfxDataAsync (C#) / importPfxDataAsync (JavaScript) method in Windows.Security.Cryptography.Certificates.CertificateEnrollmentManager class. Here’s the code snippet to do the same:

C#:


                await Windows.Security.Cryptography.Certificates.CertificateEnrollmentManager.ImportPfxDataAsync(
                    encodedString,
                    TextBoxPfxFilePassword.Password,
                    ExportOption.NotExportable,
                    KeyProtectionLevel.NoConsent,
                    InstallOptions.None,
                    "Windows Azure Tools");

JavaScript:


            Windows.Security.Cryptography.Certificates.CertificateEnrollmentManager.importPfxDataAsync(certificateData2, "", Windows.Security.Cryptography.Certificates.ExportOption.exportable,
                Windows.Security.Cryptography.Certificates.KeyProtectionLevel.noConsent, Windows.Security.Cryptography.Certificates.InstallOptions.none, "My Test Certificate 1")

Here encodedString is Base64 encoded PFX file data, something like:

image

and the password is the password for your PFX certificate file.

When you call this method, the application should install a certificate in your application certificate store. You can check it by going into the “AC/Microsoft/SystemCertificates/My/Certificates” folder under your application package directory. The package directory is created under your user account’s “AppData/Local/Packages” folder as shown in the screenshot below:

image

Please note that name of the file will be the thumbprint of the certificate.

That’s pretty much to it as far as working with PFX files are concerned. However, there are some important issues to understand when these certificates are used to authenticate REST API calls. I spent about 24 – 48 hours trying to make this work. Please see “Special Considerations” section below for those.

Consuming REST API

Consuming REST API was rather simple! If you’re using C# you would make use of HttpClient in System.Net.Http namespace, and if you’re using JavaScript you would make use of WinJS.xhr function which is essentially a wrapper around XMLHttpRequest. Here’s the code snippet to do the same:

C#:


        private const string x_ms_version_name = "x-ms-version";
        private const string x_ms_version_value = "2012-03-01";
        Uri requestUri = "https://management.core.windows.net/[your subscription id]/services/storageservices";

        public static async Task<string> ProcessGetRequest(Uri requestUri)
        {
            HttpClientHandler aHandler = new HttpClientHandler();
            aHandler.ClientCertificateOptions = ClientCertificateOption.Automatic;
            HttpClient aClient = new HttpClient(aHandler);
            aClient.DefaultRequestHeaders.Add(x_ms_version_name, x_ms_version_value);
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, requestUri);
            var result = await aClient.GetAsync(requestUri, HttpCompletionOption.ResponseContentRead);
            var responseBody = await result.Content.ReadAsStringAsync();
            return responseBody;
        }

JavaScript:


                             var uri = "https://management.core.windows.net/[your subscription id]/services/storageservices";
                             WinJS.xhr({ url: uri, headers: { "x-ms-version": "2012-03-01" } })
                                 .done(
                                    function (/*@override*/ request) {
                                        var responseData = request.responseText;
                                    },
                                    function (error) {
                                        var abc = error.message;
                                    });


That’s pretty much to it. If your request is successful, you will get response data back as XML which you can parse and use it in your application.

Special Considerations

It sounds pretty straight forward but unfortunately it is not so. I spent nearly 24 – 48 hours trying to figure this whole thing out. I was able to install the certificate correctly but then when I invoked the REST API using C# code, I was constantly getting 403 error back from the service. I ended up on this post on MSDN forums: http://social.msdn.microsoft.com/Forums/sv/winappswithcsharp/thread/0d005703-0ec3-4466-b389-663608fff053 and it helped me immensely.

Based on my experience, here are some of the things you would need to take into consideration:

Ensure that “Client Authentication” is enabled as one of the certificate purpose

image

Your certificate must have this property enabled (as shown in the screenshot above) if you wish to use this certificate in your Windows 8 application. Please note that when consuming REST API in your non Windows 8 applications, it is not required that this property is set.

Ensure that the certificate has “OID” specified for it

image 

Based on the MSDN forum thread above, this is a bug with Microsoft.

image

HttpClient and WinJS.xhr are not the same

I started with building a XAML/C# application (because of comfort level) and no matter what I tried, I could not make the REST API call work. It was only later I was made aware of the 2 issues above. However I took the certificate which was giving me problems (because of 2 issues above) and built a simple HTML5/JavaScript application and it worked like a charm. You would still need to have “Client Authentication” enabled in your certificate but not the OID one when consuming Service Management API through JavaScript.

It may very well be an intermediate thing (because of OID bug mentioned above) but I thought I should mention it here.

Try avoiding “Publish Profile File” if you’re consuming REST API in XAML/C# application

Publish Profile File, as you know is an XML file containing information about all your subscriptions (Subscription Id etc.) and Base64 encoded PFX certificate content. It’s a great way to get access to all your subscriptions. The reason I’m saying you should avoid it here is because what I found is that the PFX certificate from which the content is generated currently missing OID in there. So till the time Microsoft fixes this issue, please go individual certificate route if you’re developing using C#/XAML. If you’re building using HTML5/JavaScript, you can write something which will import this file as based on my testing it works. Just remember that the password for the certificate is an empty string. So specify an empty string (“”) for the password parameter in your call to importPfxDataAsync method.

Recommend that you create a new management certificate if you’re consuming REST API in C#/XAML application

Again this is because of the issues I mentioned above. You will need to check if the certificates you have in place today do not have the 2 issues I mentioned above. You can use “makecert” utility for creating a new certificate. I was recommended the following syntax for creating a new certificate.


makecert -r -pe -n "CN=[Your Certificate Common Name]" -b 09/01/2012 -e 01/01/2099 -eku 1.3.6.1.5.5.7.3.2 -ss My

Run this in “Developer Command Prompt” on a Windows 8 machine to create a new certificate which will get automatically installed in your computer’s certificate store. You can export that certificate using “certmgr” utility.

The App!!!

Finally, the application! My moment of glory :). It’s really a simple application. Some of the application screenshots are included below. The source code of the application can be downloaded from here. [This reminds me I need to stop doing this and start posting the code on GitHub :)]

Landing page with no subscriptions saved

image

Add subscription page

image

Landing page with saved subscriptions

image

Storage accounts list page

image

A few things about this application:

  • I wrote this application in a few hours time (after spending like 2 days trying to figure everything else out), so the code is not perfect :).
  • There’s a glitch currently in the application where if you add 2 subscriptions with different certificates, one of the subscription will not work. I haven’t figured it out just yet :). For this application I would recommend that you use same certificate for all your subscriptions.
  • The application saves the subscription id and friendly name in JSON format in application’s local settings and is not encrypted.

Acknowledgement

I’m grateful to Jeff Sanders from Microsoft for promptly responding to my questions on MSDN forums and offline as well. I’m equally grateful to Harin Sandhoo from Applied IS, who basically provided me with everything I needed to make this thing run in a XAML/C# app. Also many thanks to Mike Wood for letting me know about working with certificates in Windows 8. Without Mike’s help, I would have given up working on this thing. Lastly, thanks to Patriek van Dorp for asking a question about consuming Windows Azure Service Management API in a Windows 8 App. That pushed me into thinking about building this application.

Summary

To summarize, once we have figured out the issues with the certificates and using them to consume REST API, it was relatively easy to build the application. Documentation for Windows 8 development needs to improve a lot, IMHO. But I think this would happen over a period of time as the technology matures.

If you find any issues in my code or this blog post, feel free to let me know through comments or via email and I will fix them ASAP.

I sincerely hope that you will find this information useful.

So long and stay tuned!!!


[This is the latest product I'm working on]