Azure Mobile Services provides a really easy way to integrate social login into web, mobile, and desktop applications. At Magenic, we’re using it in our client apps for the Modern Apps Live! conference demo application called MyVote. The web application and the native mobile clients share a common Web API backend deployed to a Web Role on Azure Cloud Services. For most of the Web API methods, we only want to allow calls from users who have successfully authenticated with Azure Mobile Services. Let’s dig into what it takes to develop a Web API authentication handler that verifies claims issued by Azure Mobile Services.
Scenario
This authentication method applies to the following scenario:
- Azure Mobile Services is set up for Social Authentication. See here for instructions.
- Users authenticate on the client (browser) side using the Azure Mobile Services JavaScript SDK. The latest SDK at the time of this writing is version 1.1.3, and can be found here.
- You have ASP.NET Web API services that you want to expose only to users who have authenticated with Azure Mobile Services.
Normally we are authenticating users on the same system that issues credentials - think standard ASP.NET membership stuff. In this case, our Web API system needs to trust credentials issued by a third party.
Method
Here is a quick refresher on login with Azure Mobile Services:
1 2 3 4 5 6 7 8 9 10 11 |
|
When a user successfully logs in with Azure Mobile Services, the client.currentUser
field is set. This in turn exposes a mobileServiceAuthenticationToken
field, which is a JSON Web Token (JWT). JWT is an emerging standard for representing authentication information. It is used by many OAuth implementations, including Azure Mobile Services.
In order to verify that users have truly authenticated with Azure Mobile Services, we will rely on a ”shared secret” known only to Azure Mobile Services and to us. The JWT issued to the user is cryptographically signed by Azure Mobile Services using the Master Key unique to our service instance. We have access to this key via the management portal, and we can use it in our Web API code to verify that a JWT was truly issued and signed by our Azure Mobile Services instance.
Here’s a quick diagram that sums it up:
The standard for a client to present a JWT for authentication to a server is to set the request’s Authorization header to “Bearer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
On the server side, authentication is implemented in Web API via a delegating handler. The process begins here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
In the SendAsync
override, we attempt to validate the JWT. If it is valid, we call MyVoteAuthentication.SetCurrentPrincipal
which sets HttpContext.Current.User
. This allows us to simply add the [Authorize]
attribute to Web API controllers or actions where we want to require Azure Mobile authentication. Note the _masterKey
field that is included in the JsonWebToken
contructor call. This is the Azure Mobile Services Master Key (shared secret) that we trust as the cryptographic signer of valid JWTs.
The relevant bit inside JsonWebToken
that validates the signature follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
I borrowed liberally from the Windows Live SDK sample for this. There is one gotcha - the JWT spec indicates that a claims “exp” member should be expressed as a double, but Azure Mobile Services uses an integer.
You can find all of the JWT authentication-related code in the MyVote GitHub repository, in the MyVote.AppServer.Auth namespace.
WARNING: Do not expose your Azure Mobile Services Master Key! For example, DON’T put the key in appSettings
in your Web.config and then host your code on GitHub. You should rely on the secure configuration facility supplied by your hosting environment. If your Web API is hosted in Azure via Web Sites or Cloud Services, you can securely set appSettings
values from within the management portal.