A while back my colleague Josh Twist had a great series of posts about Azure Mobile Services (or “Zumo”, as he called). This was when the service was in its infancy, and some things changed, but the content is still excellent. One of the topics was about caching authentication tokens, so that the application wouldn’t need to authenticate the user every time, instead relying on a cached version of the authentication token obtained via one of the calls to the LoginAsync method in the client. And in the following post, he talked about how to handle the case when those tokens were expired using service filters. It is a great post, but the example uses an old (and now unsupported) version of the client SDK for managed code, so I decided to post an updated version of it.
As I mentioned before, the “service filters” which existed in the initial client SDK were replaced by the HttpClient primitives, most notably the HttpMessageHandler class (or its subclass DelegatingHandler, which is more commonly used). Since there was already a good HTTP pipeline with a type which did exactly what the original service filters did, it didn’t make sense to have two, so the service filters were dropped. As a side note, the original client SDK for mobile services didn’t use the HttpClient primitives because they were not released as a portable library; when it did, we changed the mobile services client SDK to use it.
So on to the code. The AuthHandler inherits from the DelegatingHandler class, and when it’s SendAsync method is called, it first sends the message along to the rest of the pipeline, and if it gets an unauthorized response (401), it first tries to log in to the mobile service, then resends the request with the appropriate authentication header set. This handler also calls a delegate that saves the user information, so that the application will have it the next time it’s launched. One last thing which is worth noting is that, since the request can be sent multiple times, my implementation is cloning it, as the request body may not be read more than once.
Now to the application to test it out. The client is created passing an instance of the AuthHandler class defined above. Since the handler needs a reference to the client (to be able to log in if the token has expired), the client is then passed on to the handler after it’s created. Maybe not the cleanest of the designs, but it solves the chicken-and-egg problem which we have (client needs handler in its constructor; handler also needs a client). When the client calls the operation on the table, the handler will be invoked and re-login the user if necessary.
If you want to test this yourself, you don’t really need to wait for 30 days (the default expiration of the authentication tokens issued by the mobile services) to see if it works. Since the tokens are signed with the mobile service master key, if that key is changed, then all the cached tokens will become invalid. Be careful that any systems or apps which are using that master key will stop working.
To do that, first run the app once to get a token and save it on the application storage. Once that is done, go to your mobile service dashboard page, and select the “manage keys” option in the bottom.
At that point, select the “regenerate” option, and that will change the key used by the service.
Now if you run the application again, if the client tries to use the cached token the request will fail with an unauthorized (401) response, and the handler will initiate another login action for the client.
And that’s the implementation for caching and revalidating tokens in the current Azure Mobile Services managed SDK.