Thursday, April 30, 2015

CRM Mobile Helper Code, Refresh Tokens, and Xamarin

If you’re interested in mobile development in conjunction with Dynamics CRM you should take a look the the Mobile Development Helper Code for Dynamics CRM. So instead of using an approach where your are hitting the SOAP endpoint directly and manually constructing authentication headers you get partial re-implementation of the SDK classes in the form of a portable class library which provides a similar development experience as to what CRM developers are already used to. With a PCL you are set for cross platform development using Xamarin but the one potential caveat is that the Mobile Helper Code relies on OAuth for authentication to CRM. Again good for deployments when an app is specific to an organization but not so great for an one that might go into an app store due to the need to pre-register it with Active Directory. Kenichiro Nakamura from Microsoft has written several blog posts on getting started with Dynamics CRM and mobile development which I suggest you check out (Part 1, Part 2, & Part 3).

I wrote a small sample application using Xamarin on iOS which uses the Mobile Helper Code and OAuth to get a list of Account records from CRM and can update the latitude and longitude bases on the current location of the local device – think of being on site at the location and updating data based on current data pulled directly from the device. I’m not going to rehash the content of Kenichiro’s posts. You’ll still need the Active Directory Authentication Library and Json.NET (Part 1) and to register your app with Active Directory (Part 3) but I did have a few observations specific to an iOS implementation and also wanted to share some code around handling authentication and refresh tokens.

iOS Implementation

The Mobile Helper Code isn't on NuGet so you’ll need to download and build it yourself. It's called out in the in the code and on the MSDN download page but you’ll need to comment out or remove the using Windows.ApplicationModel statement and the EnableProxyTypes method in Microsoft.Xrm.Sdk.Samples.cs as it doesn't port to iOS and Android.

I've also found you’ll need to change the Linker behavior under the project’s iOS Build options to “Don’t link” in order for everything to work. I haven’t done exhaustive testing but there are a few instances where methods contained in the System namespace are invoked via reflection. Normally this wouldn't be a big deal but when the Xamarin linker goes through and analyzes the code (Linker: SDK Assemblies Only & All Assemblies) to remove unused functionality to reduce application size as a result it can’t account for this (which is documented). As such when a method like Guid.Parse is invoked via reflection the app crashes because Guid.Parse isn't present in the final compiled output. I’m not a Xamarin expert but this issue only presents itself when deploying to an actual device and not on the iOS simulator. An alternative to changing the Linker behavior would be to eliminate the use of reflection and call the methods directly so the Xamarin linker includes the correct code in the final build.

The other piece I hadn’t seen done anywhere yet was using refresh tokens to prevent users from having to re-enter their credentials every time the app was launched. At a high level after initially entering the username and password an Access Token with a corresponding Expiration Date and a Refresh Token are returned back to the calling application. The Access Token is good for a limited amount of time (like 1 hour) after which it is no longer valid. Once it’s expired you can either force the user to log in again or use the Refresh Token to get another Access Token silently in the background.

So here is what an implementation using refresh tokens might look like. The idea would be to check if an Access Token has already been saved and if it is still valid. If there is no saved Access Token the app will be directed to the login screen. If the Access Token exists but is expired a new Access Token will be obtained using the Refresh Token. If the Access Token exists and is still valid no additional effort is required.

Here are a few shots of the application:



The entire project can be downloaded here: