If you went through the hands on lab for using ACS on your Windows Phone 7 application, you already know that saving the user the hassle to re-authenticate all the times entails a security tradeoff. Here there’s what I wrote in the lab’s instructions:
Saving a token on the phone’s storage is not very secure. The isolated storage may prevent other applications from stealing the persisted token, but it does not prevent somebody with physical access to the device to eventually get to it. Any form of encryption would not solve the issue if the decryption key resides on the phone, no matter how well it is hidden. You could require the user to enter a PIN at every application run, and use the PIN to decrypt the token, however the approach presents obvious usability and user acceptance challenges.
While we wait for a better solution to emerge, it may be of some consolation considering that saving token is much better than saving direct credentials such as a username/password pair. A token is typically scoped to be used just with a specific service, and it has an expiration time: this somewhat limits what an attacker can do with a token, whereas no such restrictions would be present should somebody acquire username and password.
Well, guess what: a better solution is emerging, and as of yesterday you can get a sneak peek of it with the Windows Phone Developer Tools 7.1
The solutions happens to be very simple, too: in a nutshell, it consists in making DPAPI available on the device.
In “Mango” you have access to ProtectedData, which you may recognize as the class that provides you access to DPAPI for encrypting and decrypting data via static methods Protect and Unprotect.
The ProtectedData class available on the device differs from the one in “big .NET” in the way in which it handles the scope.
- In .NET you can choose to encrypt your data with the machine key or with the current user key. See MSDN.
- On the device every application gets its own key, which is created on first use. Calls to Protect and Unprotect from the application code will implicitly use the application key, ensuring that all data remain private to the app itself: in fact, the scope parameter is not even present in the method’s signature. For what I understand, the key will survive subsequent application updates.
Back to the problem of saving tokens on the device: how do we modify the flow in the current samples in order to take advantage of this new feature?
Very straightforward. In step 12 of task 5 of the ACS+WP7 lab you hook up your app to a store façade, RequestSecurityTokenResponseStore, which is responsible for persisting in isolated storage the RSTR messages received from ACS (you can find it in SL.Phone.Federation/RequestSecurityTokenResponseStore). All you need to do is ensuring that you use Protect and Unprotect when putting stuff in and out of isolated storage.
Note: Why the entire RSTR instead of just the token? Mainly because we can extract the expiration from directly from there, whereas the token itself may be encrypted for the destination service hence opaque to the client. We use that info just as an optimization – we can save a roundtrip to the service if we already know that the token expired – but the service is still on point for validating incoming tokens hence errors on this are not too costly.
As we progressively refresh our ACS+WP7 content to take advantage of the new Mango features (with its occasional road bumps) we’ll incorporate those new features, but I wanted to make sure that you know ASAP how to mitigate the token-persistence-on-the-device problem. Don’t you feel better already?