Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Authentication after migrating to App Services Mobile App: uid vs sid

I've migrated form Azure Mobile Services to the new App Services Mobile App, and I'm using the new AMS 2.0.0-beta on the client-side.

I have two providers (currently) implemented for OAuth 2.0: Google and Twitter.

Previously, I was able to get the provider token via a claim in the principal on the server, and there would be a uid (unique id) claim that would be either "Google:123456789" or "Twitter:123456789010" (or however many alphanumerics). I believe the MobileServiceClient.UserId also exposed this as well.

Now, after I've migrated to the new App Services Mobile App (and I'm using the Preview Portal now, which for the most part is pretty awesome), there is no longer a uid claim, but rather a single sid (session id) claim, something like: "sid:ABCDEFGHIJKLMNOPQRSTUVWXYZ", no matter which provider I log in with. When I looked on the client-side at the MobileServiceClient.UserId value, it also gives this "sid" value.

The point is that previously the uid token could uniquely identify a user. Now it is the same for all users across all providers!

How can I get the provider token with the App Services Mobile App that I was previously able to get with Azure Mobile Services?

Also, could anyone point me to the source code for the Azure Mobile Services 2.0.0-beta? Is it open source? I can't seem to find it on GitHub.

Edit: Here is a screenshot of the User on the server side: enter image description here


1 Answers

Ok, after re-reading the migration documentation for the umpteenth time, I've revisited one of my earlier steps and found it to have an invalid assumption. In the documentation, it mentions considerations for authentication, including the following block of code:

ServiceUser user = (ServiceUser) this.User;

FacebookCredentials creds = (await user.GetIdentitiesAsync()).OfType< FacebookCredentials >().FirstOrDefault();

string mobileServicesUserId = creds.Provider + ":" + creds.UserId;

Now, I was unable to find "GetIdentitiesAsync", and ServiceUser has an Identities enumerable property, so I was going with that. (It was, after all, providing very similar information as the pre-migration version of ServiceUser.) However, this method apparently gets more data than is already present in the Identities enumeration.

I still can't find GetIdentitiesAsync, but after some digging around in the the class browser, I was able to find a singular version of the extension method called GetIdentityAsync in the Microsoft.Azure.Mobile.Server.AppService.ServiceUserExtensions (it's the only method there). I tracked this down to the Microsoft.Azure.Mobile.Server.AppService namespace, added a using statement and tried out the following code:

var hmm2 = await serviceUser.GetIdentityAsync<GoogleCredentials>();

I'm leaving the variable named "hmm2" because I have the following screenshot:

debug inspection of serviceUser.GetIdentityAsync

The green box on the right with the numbers is the unique identifier I was getting before the migration! So to get the uid, one would need to call this extension method against all provider credentials. When the non-null credentials are found, then it can use the nameidentifier claim to get the provider's unique identifier for the user.

I am hoping that once App Services is production ready, we have a little bit more concise way of getting the non-null provider credentials, but for now this works!

Edit: Here is my code now that is working on the server-side (the client side MobileServiceClient.UserId does not work. You have to return information from the server):

var serviceUser = (Microsoft.Azure.Mobile.Server.Security.ServiceUser)Thread.CurrentPrincipal;

try
{
    var googleCreds = await serviceUser.GetIdentityAsync<GoogleCredentials>();
    if (googleCreds != null && googleCreds.Claims != null)
    {
        _CurrentProvider = "Google";
        var nameClaim = googleCreds.Claims.Single(x => x.Key.Contains("nameidentifier"));
        _CurrentProviderKey = nameClaim.Value;
        return;
    }

    var twitterCreds = await serviceUser.GetIdentityAsync<TwitterCredentials>();
    if (twitterCreds != null && twitterCreds.Claims != null)
    {
        _CurrentProvider = "Twitter";
        var nameClaim = twitterCreds.Claims.Single(x => x.Key.Contains("nameidentifier"));
        _CurrentProviderKey = nameClaim.Value;
        return;
    }

    throw new NotSupportedException("The OAuth Provider is not supported.");
}
catch (Exception ex)
{
    throw new InvalidOperationException("There was an error updating the authentication provider. InnerException: " + ex, ex);
}

Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!