Override the Default Login to provide Customized Identities in Windows Azure Mobile Services

It is very easy to override the default login feature (accessible by /login/[provider] endpoints) of the Windows Azure Mobile Services and customize it according to the need of your app. In this blog post, I am going to discuss how to do that, in particular, we want to be able to do the following:

  1. Add custom claims to the identity (the ability to provide authorization after authentication). In this example, we will add custom claims to the facebook identity.
  2. Add a new oAuth identity provider (in addition to the ones supported by the Windows Azure Mobile Services). In this example, we will add Foursquare as the new identity provider.
  3. Add a simple classical identity provider (login by username and password).
  4. Add support for multiple apps using the same backend. It is necessary, if you have a public API exposed and other people are making apps using your backend.

In this post, I am going to use the oAuth flow described in my previous blog post, which is:

  1. the app verifies the identity of the user elsewhere, i.e., native facebook app, and acquire an access_token,
  2. this access_token is used to login to Windows Azure Mobile Services.

But, the examples are easily extendable to any standard oAuth flow.

Adding Custom Claims

Each endpoint in Windows Azure Mobile Services has access to the user object. A call to its asynchronous user.getIdentities(…) function will produce similar result like the following:

By default, Windows Azure Mobile Services gives you 2 claims for facebook, namely userId and accessToken.

In this example, we are going to add 2 more claims role and device, indicating the role of the user (either admin or user) and the device from which the user is trying to access the backend.

Let’s start by creating a custom API called login with POST permission to everyone. After that, add a route called facebook. The code will look like the following:

With this code, the facebook function, described above, can  be called by HTTP POST /api/login/facebook (as opposed to the default HTTP POST /login/facebook). We will add another property called device in addition to the default access_token to the request body. However, when we override the client SDK, we will provide the value depending on the SDK being used.

Here is how we are going to implement the new login endpoint:

  1. Call facebook and get the facebook app id and user id from the access token, and check the app id with the registered facebook app id in the Windows Azure Mobile Services. If they do not match, generate a 401 unauthorized.
  2. If, however, they match, generate and send back a JSON Web Token (JWT) so that it can be used for subsequent API calls (similar to what the default login will give you).

Thanks to many awesome developers, there are code available in the Web to generate a JWT that the Windows Azure Mobile Services will understand. Let’s pick one of those and modify it to include claims (in /service/shared directory):

As you can see that the JWT has a claim called urn:microsoft:credentials that is used for custom claims. After that, let’s implement the previously described facebook function. In this function, we are going to use a library called async to call the facebook API parallel to get the facebook app id and user id from access_token. Once we have the info, we are going to check if the facebook app id is actually the one registered with our Windows Azure Mobile Services. If everything checks well, then we will create a JWT and send it back as a response in the standard response format of the default login. The code looks like the following:

To test if the claims are added to the identity or not, let’s write a simple API endpoint (called test with the GET permission to Only Authenticated Users). This endpoint will response the contents of the user object and the identities object.

And it should produce a response like the following:

As you can see that your custom claims are added to the identities.

(PS : You may need to install async node module to run the example code.)

Adding A New OAuth Identity Provider

With the method shown in the previous section, any identity provider can be added as long as the identity provider has endpoints to request a user_id and a app_id from the access_token. Although, any identity provider will have such endpoints for the user_id, but not all of them will have one for the app_id. In this example, we will add Foursquare as an identity provider because it has no public endpoint that returns an app_id from the access_token, so that we can generalize. The following method can also be added to the previous example to provide an additional layer of security.

The idea is simple. Since both server and client knows the client secret (you will get a client_secret once you register an app with the identity provider),  before sending the access_token we are going to encrypt it using the client_secret . The server will always expect an encrypted access_token and will decrypt it before using it. We implemented the idea for foursquare and the code is following:

I have also included an endpoint for encrypting the access_token for testing purpose, but ideally you would do it in the client:

Adding A Simple Classical Identity Provider

The same process can easily be extended to provide classical identity (identity by username and password). Just check the username and password in the database and for a successful match generate a JWT. This process is described more comprehensively in here, including registration.

Adding Support For Multiple Apps (Expose Your Own API)

If you want to have your API publicly available for everyone (or a selected group) to use your backend, you need the support of multiple apps in your login. You can extend the same idea easily to have this feature. This is the oAuth flow we are going to implement today:

  1. The identity is still provided by an external server, i.e., facebook, and the 3rd party has an app registered with facebook, through which it gets the access_token from facebook.
  2. The 3rd party register the facebook app with your backend (save the app_id and app_secret).
  3. Similar to previous sections, the 3rd party send the facebook access_token for login and with that your backend is going to get an app_id and user_id from facebook.
  4. Then you check the app_id is registered with your backend or not, and depending on that either generate a JWT for login or a 401 unauthorized. (You can add another layer of security by encrypting the access_token with the app_secret. But, in that case, you have to pass the app_id when calling the login endpoint, so that the backend knows which app_secret to use for decryption.)

You may also want to add the app_id to your custom claims. The login script is following:

To recap, in this post, we learned how to add custom claims to Windows Azure Mobile Services user’s identities, and we extend the idea to implement, an authentication by an additional identity provider,  the classical username/password based identity, and the support of multiple apps for a public API. The full code can be cloned from github.

(PS : As the post was getting bigger, I skipped few trivial steps. Feel free to ask questions if anything is unclear.)

(PPS : I will soon add some client SDK codes in the github repository to access these modifications. Basically, in the client SDK you need to change the login endpoint url and may need to add extra variables like device, app_id in the request body for calling the new login endpoints. Checkout this and this links for client codes for similar modifications.)

About these ads

Tagged: , , , , , , , , , , , , , , , , , , , , , ,

5 thoughts on “Override the Default Login to provide Customized Identities in Windows Azure Mobile Services

  1. Thiago July 16, 2014 at 11:31 am Reply

    First of all really great article. =D
    I’m using a similar approach but i have one preoccupation with this method. How can i match if the UserID sent is the same that is in the Token, to validate in future API call?

    Thanks

  2. Faisal R. July 16, 2014 at 12:04 pm Reply

    Yes, you can do that. If you decode a standard jwt sent by azure (without this customization) you will see that the claims are encrypted. Basically, in the createZumoJwt method you have to encrypt the claims that azure can decode later. I need to dig deep to find out how. I will do that once I have some free time. So, Keep tuned. In the meantime, if you can figure out how let me know. Alternatively, foreach request you can call facebook to verify (this method seems waste of resources, but it also takes care of the case when the user revoke access to the app from facebook.

    • Thiago July 17, 2014 at 5:47 am Reply

      Great, i will try to find a solution. =D can you send me your email?
      Thans

  3. Faisal R. July 20, 2014 at 12:16 am Reply

    Hi Thiago-
    You do not have to worry about it :) Here is why:

    If you look into the createZumoJwt method, you see that it requires the client secret. And based on the secret, and the token info (b1 and b2 in the algorithm) it generates a signature (b3). If the signature doesn’t match with the data the request will be rejected as unauthorized. Since the hacker will not know the client secret, even if he knows the algorithm to generate jwt, he will not be able to make a correct token. The createZumoJwt method was created by following the algorithm written in the .net sdk for mobile service (where you can just create the jwt from the client). Take a look at this for more confidence: [link]

    Finally, do this:
    1. Get 2 jwt for 2 different users.
    2. For the 1st jwt find the signature (the characters after the last dot .), and replace it with the signature of the 2nd jwt.
    3. Make a api call, and you should get a “Error: The authentication token has an invalid signature.”

  4. Alexander September 2, 2014 at 10:53 pm Reply

    cannot thank you enough for this article!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: