Enhanced users feature in Azure Mobile Services

In the last post I talked about the ability to get an access token with more permissions to talk to the authentication provider API, so we made it that feature more powerful. Last week we released a new update to the mobile services that makes some of that easier. With the new (preview) enhanced users feature, expanded data about the logged in user to the mobile service is available directly at the service itself (via a call to user.getIdentities), so there’s no more need to talk to the authentication provider APIs to retrieve additional data from the user. Let’s see how we can do that.

To opt-in to this preview feature, you’ll need the Command-Line Interface. If you haven’t used it before, I recommend checking out its installation and usage tutorial to get acquainted with its basic commands. Once you have it installed, and the publishing profile for your subscription properly imported, we can start with that. For this blog post, I created a new mobile service called ‘blog20131216’, and as a newly created service, it doesn’t have any of the preview features enabled, which we can see with the ‘azure mobile preview list’ command, which lists the new feature we have:

C:\temp>azure mobile preview list blog20131216
info: Executing command mobile preview list
+ Getting preview features
data: Preview feature Enabled
data: --------------- -------
data: SourceControl No
data: Users No
info: You can enable preview features using the 'azure mobile preview enable' command.
info: mobile preview list command OK

A sample app

Let’s see how the feature behaves before we turn the feature on. As usual, I’ll create a simple app which will demonstrate how this works, and I’ll post it to my blogsamples repository on GitHub, under AzureMobileServices/UsersFeature. This is an all in which we can log in to certain providers, and call a custom API or a table script. Here’s the app:

001-TestApp

The API implementation does nothing but return the result of the call to user.getIdentities in its response.

  1. exports.get = function (request, response) {
  2.     request.user.getIdentities({
  3.         success: function (identities) {
  4.             response.send(statusCodes.OK, identities);
  5.         }
  6.     });
  7. };

And the table script will do the same (bypassing the database):

  1. function read(query, user, request) {
  2.     user.getIdentities({
  3.         success: function (identities) {
  4.             request.respond(200, identities);
  5.         }
  6.     });
  7. }

Now, if we run the app, login with all providers and call the API and table scripts, we get what we currently receive when calling the getIdentities method:

Logged in as Facebook: <my-fb-id>
API result: {
"facebook": {
"userId": "Facebook: <my-fb-id> ",
"accessToken": " <the long access token> "
}
}
Logged out
Logged in as Google: <my-google-id>
Table script result: {
"google": {
"userId": "Google: <my-google-id> ",
"accessToken": " <the access token> "
}
}
Logged out
Logged in as MicrosoftAccount: <my-microsoft-id>
API result: {
"microsoft": {
"userId": "MicrosoftAccount: <my-microsoft-id> ",
"accessToken": " <the very long access token> "
}
}

So for all existing services nothing really changes.

Enabling the users feature

Now let’s see what starts happening if we enable that new preview feature.

Caution: just like the source control preview feature, the users feature cannot be disabled once turned on. I'd strongly suggest you to try the feature in a test mobile service prior to enabling it in a service being used by an actual mobile application.

In the Command-Line interface, let’s enable the users feature:

C:\temp>azure mobile preview enable blog20131216 Users
info: Executing command mobile preview enable
+ Enabling preview feature for mobile service
info: Result of enabling feature:
info: Successfully enabled Users feature for Mobile Service 'blog20131216'
info: mobile preview enable command OK

And just like that (after a few seconds), the feature is enabled:

C:\temp>azure mobile preview list blog20131216
info: Executing command mobile preview list
+ Getting preview features
data: Preview feature Enabled
data: --------------- -------------
data: Users Yes
data: SourceControl No
info: You can enable preview features using the 'azure mobile preview enable' command.
info: mobile preview list command OK

Time now to run the same test as before. And the result is a lot more interesting. For Facebook:

Logged in as Facebook: <my-fb-id>
API result: {
"facebook": {
"id": " <my-fb-id> ",
"username": " <my-facebook-username> ",
"name": "Carlos Figueira",
"gender": "male",
"first_name": "Carlos",
"last_name": "Figueira",
"link": https://www.facebook.com/ <my-facebook-username> ,
"locale": "en_US",
"accessToken": " <the-long-access-token> ",
"userId": "Facebook: <my-fb-id> "
}
}

And Google:

Logged in as Google: <my-google-id>
Table script result: {
"google": {
"family_name": "Figueira",
"given_name": "Carlos",
"locale": "en",
"name": "Carlos Figueira",
"picture": "https://lh3.googleusercontent.com/ <some-path>/<some-other-path>/<yet-another-path>/<and-one-more-path> /photo.jpg",
"sub": " <my-google-id>",
"accessToken": " <the-access-token> ",
"userId": "Google: <my-google-id> "
}
}

And Microsoft:

Logged in as MicrosoftAccount: <my-microsoft-id>
API result: {
"microsoft": {
"id": " <my-microsoft-id> ",
"name": "Carlos Figueira",
"first_name": "Carlos",
"last_name": "Figueira",
"link": "https://profile.live.com/",
"gender": null,
"locale": "en_US",
"accessToken": " <the very long access token> "
"userId": "MicrosoftAccount: <my-microsoft-id> "
}
}

So that’s basically what we get now “for free” with this new feature… One more thing – I didn’t include Twitter in the example, but it works just as well as the other providers: you’ll get information such as the screen name in the user identities.

User.getIdentities change

One thing I only showed but didn’t really talk about: the call to user.getIdentities is different than how it was previously used. It’s a change required to support the new functionality, and the synchronous version may eventually be deprecated. In order to give you more information about the users, we’re now storing that information in a database table, and retrieving that data is something we cannot do synchronously. What we need to change in the scripts then is to pass a callback function to the users.getIdentities call, and when that data is retrieved the success callback will be invoked. Changing the code to comply with the new mode is fairly straightforward, as the code below shows. Here’s the “before” code:

  1. exports.get = function (request, response) {
  2.     var identities = request.user.getIdentities();
  3.     // Do something with identities, send response
  4. }

And with the change we just need to move the remaining of the code to a callback function:

  1. exports.get = function (request, response) {
  2.     request.user.getIdentities({
  3.         success: function (identities) {
  4.             // Do something with identities, send response
  5.         }
  6.     });
  7. }

The synchronous version of user.getIdentities will continue working in mobile services where the users feature is not enabled (since we can’t break existing services), but I strongly recommend changing your scripts to use the asynchronous version to be prepared for future changes.

Wrapping up

As I mentioned this is a preview feature, which means it’s something we intend on promoting to “GA” (general availability) level, but we’d like to get some early feedback so we can better align it with what the customers want. Feel free to give us feedback about this feature and what we can do to improve it.