The App: Token Flow

I thought I'd write this all down before I forget it. Really hard to remember it after stepping away for a second.

I'm using the Microsoft Azure Mobile App platform and I want to support a number of different identity providers and platforms.

This is basically how it works:

  1. My program calls LoginAsync on a MobileServiceClient (provided by MS and unique to each platform). As soon as I do this, control of the process is turned over to the MS libraries.
  • On the device, a web browser is launched.

  • The Mobile App service refers my request to the identity provider I chose (Google, Facebook, etc.)

  • The user logs into that service with their username and password specific to that service.

  • At this point, the identity provider returns an access_token which is fed to my backend server (running on the app service platform). Again, this is all automatic.

  • The service then returns a MobileServiceUser which contains a MobileServiceAuthenticationToken and a UserId. This information is then attached to each web request made by the app, so it's always available. This is the first time my device code begins to execute again (steps 2 through 5 happen transparently and out of our control).

  • This MobileServiceAuthenticationToken contains the identity provider name and what's called a "stable id" or sid. It has a few other bits that are important, but not in this discussion. The sid is Microsoft's hashed value of the identity provider's real id for the user. The sid should be consistent no matter what the user changes on their identity provider account. We can count on that to never change.

  • On the client, the MobileServiceUser UserId is simply the sid prefixed with the literal "sid:"

  • At this point, we are authenticated as far as the Azure Mobile App Service is concerned. But we don't have all the information we want.

  • Back under our control, the device then calls LoginAsync again, only this time we are calling a Custom Authentication controller that we designed on our backend. This controller requires an authenticated user - which we now are - so random anonymous requests will fail (which is what we want to keep nosy beggars at bay).

  • This backend controller accesses the user information (coming back from the device in the form of the MobileServiceAuthenticationToken). Now the backend has access to the sid.

  • The backend controller then makes a call to:

     `this.User.GetAppServiceIdentityAsync<GoogleCredentials>( this.Request )`
    

    which allows it to retrieve all of the information from the identity provider that the user has agreed to allow us to access. This would include email, name, URL to their photo, etc. (Google is just an example.) This call decodes the information in an authentication header that gets added on behalf of their identity provider, e.g. X-MS-TOKEN-GOOGLE-ACCESS-TOKEN

  • At this point, our controller creates a new MobileServiceAuthenticationToken that contains lots more information (claims) about the user and so on.

  • Now our authentication process is complete. We just have to remember that every time we authenticate, re-authenticate or refresh our tokens, we have to call our custom authentication controller to add those claims needed by our app.

A couple of additional considerations here:

  1. Azure Mobile App service automatically provides a refresh token of 72 hours, even if the identity provider you select has a shorter expiration time.
  • Since we are actually using a hybrid of the social identity provider and a custom identity provider, it can be quite confusing when it comes to refresh tokens, especially when they're expiring at different intervals. To deal with this, I set the re
  • In the Settings of the App Service, we've also set the WEBSITE_AUTH_HIDE_DEPRECATED_SID to true so that we are only getting the permanent id of the user.