Token Based Authentication in a Cordova App
Any web based service that provides a mobile client requires some form of authentication before the user can access their permitted resources. The simplest approach is to require the user to enter their username and password for every session (or after the session expires). Simple to implement, but not the most friendly approach. User’s are notorious for forgetting their login credentials more so now than ever as more and more services require login ids and their own passwords.
A better approach is to use token based authentication whereby user is issued a signed token that they can then use to access their data from the online service. This introduces its own security challenges but this can be mitigated quite nicely with proper server side measures such as serving your entire site in HTTPS only. Of course, token based approach requires that your back-end implements an API that is suitably protected and accessible only through authenticated clients. But that’s a given and I’m not going to delve into that in this post.
Tokens however have a validity period attached to them after which they expire and are no longer useful. One way to extend their validity is to refresh them using a separate request typically provided through a separate API endpoint. Once this is setup, you can create a background task in your mobile app that would periodically keep refreshing your token so that it stays valid for prolonged periods of time providing user with a seamless experience a la Facebook app.
This is where the problems start. Creating a background task is typically achieved through a service which is a special kind of task (in Android at least) that remains active throughout the power cycle of your device. This means even when your soft turn off your device, the service runs in the background periodically refreshing the access token. Drains the battery a little, but who cares as long as your app provides the necessary user experience?
With this approach in mind, I started implementing a background service in my Cordova app. Searching the web, I found a few Cordova plugins for this and out of these, I chose the most popular one. Now the author does warn that some app stores may not certify apps that use the plugin and that it is only for enterprise apps, meaning apps that are distributed outside of legitimate app stores and run within a controlled environment. I still went ahead and tried it. Unfortunately my experience has not been all too great. Try as hard as I may, the background task fails to run even in my Android emulator.
Then there’s another limitation, on Android, for the background task to run reliably, the platform requires you to create a notification to the user highlighting to them that the task that they just closed is indeed still active. Quite rightly so too as the user needs to be informed that there’s a process that is draining their precious power bank, no matter however minuscule that consumption may be.
This caused me to pause a moment and think — perhaps my solution to the problem requires rethinking. Is there a way by which we can eliminate the need for periodic background token refresh altogether?
This is the approach that I can think of right now:
- Extend the token validity period to one that covers the duration of use of even the most sporadic of your users. So if the most sporadic user’s interval of access is 3 months, make the token validity period so a comfortable range such as 6 months.
- Store the token in offline storage and then upon application startup, look for this token. If it’s present, take the user to the app page that you would direct user to upon successful login within the app.
- Refresh the token whenever the app is in the foreground and when the preset token refresh interval has elapsed. This would require that token acquire/refresh times to be saved in offline store such as localStorage of IndexDB.
- Some token standards such as JWT provide a separate configurable interval for the maximum duration of token refresh. Extend this to a very long period — using the above as an example — 2 years or even longer.
- To mitigate user losing their device, provide a web page listing all the devices using their account and allow them to revoke any device from that list. Once revoked the accessing the service from that device would require user to entire the username and password again.
Come to think of it, this seems to be reason why services like Facebook and Google provide the device list and revoke features for their services.
Notes
- This approach is only recommendable for such services where the server does not hold highly sensitive information such as credit card information, financial account details, etc. If your service keeps track of user’s diet calorie intake that they enter after every meal, I guess then it’s not too big a loss if it gets into the wrong hands (unless you’re a celebrity of course)
- The solution employs a blend of client side and server side code for what is perhaps the best user experience. High usability owing to the seamless experience and zero power impact as there’s no background service is running.
Pros
- High usability provided by the seamless experience
- Zero power impact as there’s no background task constantly running and draining power, however little.
Cons
- Slightly lower security as losing a device can allow a malicious user to access the user data until the user revokes the device.
- Additional development effort as the solution requires server side infrastructure to be built. Server side work involves changes to backend database to store the device-to-token association as well as a front end where the user can list and revoke their devices.
Perhaps there are ready made solutions out there that provide this whole thing as a pluggable component, but if there is one, I’m yet to discover that. Until then I have no choice but to embark on building one myself.