Using Google Services in UWP C# Apps – Part 2

By February 7, 2017Cloud Platform, News
Google-Cloud-Platform-UWP-App-Profile-Images

We previously looked at how you can use the WebAuthenticationBroker to allow end users to authorize a UWP app to access their Google account information. In this post we’ll complete the sample by describing how to authorize a UWP app to access Google Cloud Product services.

To demonstrate this, we’ll recreate the ASP.NET MVC sample that logins in a user, grabs their profile image, and uploads that image to Google Storage.

However, just like in our previous sample, we don’t have any helper libraries we can use, because as of this writing the Google Cloud SDK does not yet natively support UWP. Fortunately, we can always access the services via REST, so let’s get to it.

Authorization Workflow

Just like in our MVC sample, we need a way to authorize our app to access the services in our GCP account so that it can make the appropriate changes, in this case, uploading an image to Google Storage.

However, unlike our MVC sample, we are unable to use the same Web Server OAuth Workflow because it would require that we issue a POST containing the client secret, and this request could be hijacked by a malicious user, compromising our security.

Instead, we need to use a different OAuth workflow for Service Accounts which uses a JSON Web Token (JWT) to authorize the request. The JWT contains the scope of your request, and needs to be signed with your private key, which is issued when you create credentials in the Google API Console.

Recall that when you create a Service Account in the console (in this case we want to use the option for P12), you are immediately served a file containing your private key.

Google-Cloud-Platform-Create-Service-Account

This is the only time that key is available, so be sure to keep that key safe, or you will have to delete it and create a new one.

Once you’ve created the JWT, having signed it with your private key, you simply POST this request to the Google authorization endpoint, and you will be returned a response containing a Bearer token that you can use to make authorized requests to the scopes you requested in the JWT.

Before we look at the code, let’s take a moment to review an important consideration regarding security for your app.

Security Considerations

Because the request needs to be signed, your app must have access to the file containing your private key, in this case the P12 file issued when you created the Service Account you’ll be using to authenticate your app.

Although you can simply include this file in your app, you probably don’t want to do this for any scenario other than testing locally. Distributing your app with the key file means anyone could use it to sign requests on behalf of your app!

A slightly better idea may be to embed the file as a resource into your app, so that it’s not freely available as a separate file. This is what we’re doing in this example. However, a malicious user could certainly still decompile your app and retrieve the key that way. Encryption and obfuscation is probably a good idea, especially in specific scenarios, such as internal business apps, where you can control access to devices where your app is deployed.

Ideally, however, you probably want to setup a proxy web service to handle requests to the GCP service, and use the server authentication from our previous example to perform the GCP service operations. This way your server can be authorized entirely outside your app, protecting your key from being stolen and giving you full control of your apps content workflow.

That being said, I am not a security expert by any means, and would love to hear thoughts from how to best protect a UWP app from others in the comments. This sample is meant only to serve as a simple example of accessing GCP in a UWP app, so please use with care.

Now that we understand the workflow and security needs, let’s dive into the code!

Creating a JWT in UWP Apps

The trickiest part of putting this sample together was definitely creating the JWT token, because the token has to be signed, and cryptography isn’t something I personally know a lot about.

Fortunately, I found a helpful sample from developer Ilya Melamed who wrote a post about Authenticating with Google Service Account in C# (JWT). This sample is for the full .NET framework (such as WPF apps) and many of the classes used are not available for UWP. However, it was a useful starting point which I used to expand to UWP.

X509Certificate2

The key part of Ilya’s sample is the use of the X509Certificate2 class which can load the P12 key file from Google. Although UWP does not have this class natively in the framework, there is a nuget package available which adds these classes: System.Security.Cryptography.X509Certificates

With this we’ll be able to open the P12 key and use it to sign our JWT, so in my sample project I’ve added that key file as an embedded resource:

Google-Cloud-Platform-p12-key

To open the file we extract it from the assembly as a stream, and read the contents as bytes:

This will eventually be passed to the X509Certificate2 constructor, which accepts those bytes and the password, which is “notasecret” for GCP certificates:

Now that we have a way to sign our token, let’s create it!

Creating the Token

The header is the same for all requests, indicating the type and signing algorithm:

Next we need to create the claimset, which contains our client ID, requested scopes, and other details described in the Google OAuth documentation:

These components of the JWT then need to be Base64 encoded:

And finally, we use the certificate we opened to sign the token, putting it all together to get the final JWT:

Now that we have our token, we can issue a POST to the Google authorization endpoint:

And if we did everything right, we’ll get back the access token for our app, which we’ll use to authorize subsequent requests to our GCP services.

Here’s the complete GoogleJsonWebTokenHelper class for UWP:

 

Uploading an Image

Now that we have the token we can proceed to issue a simple POST request with the image contents we retrieve from the user, including the token in the header:

The result is an image uploaded to the storage bucket, which we use to refresh the list, and now have a new profile image added to the ListView:

Google-Cloud-Platform-UWP-App-Profile-Images

Retrieving the items from Google storage is done similarly to our MVC sample; we simply query the rest API, sending the same bearer token we already retrieved:

In this case, StorageModel is just a simple C# class that encapsulates the JSON result from the call:

That’s all there is to it!

Wrapping Up

Although the Google Cloud SDK doesn’t yet have native support for UWP apps, it is still possible to perform any of the various operations for both Service and User accounts using plain old REST commands. Authorizing your app to access GCP Services via Service Account takes a bit more work, and you do want to be careful with your certificates, but it’s absolutely possible with a little extra work.

Hopefully we’ll start to see some UWP support in the coming months, but in the meantime, as always I hope this was helpful, and thanks for reading!

The following two tabs change content below.