Update 4/22/2014: Version 1 JWTs have been deprecated. Make sure you check out this post to see how the script for JWT creation needs to be changed.
Update 2/20/2014: Due to a few issues, the app formally known as PikShare has been renamed LensRocket. Everything except some names remains the exact same as the originally released source code and application.
With the app I recently released, LensRocket, I wanted to implement custom authentication. I had already setup custom authentication with Mobile Services last year, however, Mobile Services has launched a few different new features which makes doing custom auth a bit easier / make more sense. The previous method was based off an early demonstration of doing custom auth which was created by Josh Twist and made use of a table based script to handle both user account registration as well as authenticating and logging users in. This works fine but now that Mobile Services has Custom APIs which allow you to define functionality for different HTTP methods for a custom endpoint, it seems like this would be a good place to put this functionality. That’s easy enough, but there is a lot of code for generating a JSON Web Token, creating a HASH, and making a SALT. Since this code is used in both the login and register functionality, we need to have this code accessible in both places. Another feature of Mobile Services, shared scripts, helps solve this problem. Let’s look at that in a bit more detail how we can make authentication a bit easier using these newer capabilities.
Creating a shared script
Turning on script source control is a very easy process once you have a Mobile Service. Go to the Dashboard tab for your Mobile Service and after a few seconds, you’ll see a link to Set up source control on the right side under quick glance:
Once you’ve done that, you’ll be taken to the Configure tab where you can see the URL for your Mobile Service’s GIT repository as well as a URL you can use to trigger a deployment (just go to the URL in the browser). Once you’ve cloned the GIT repository locally, you can then edit all of your scripts (table, custom api, and scheduler scripts) as well as create and modify shared scripts. These shared scripts allow you to define functionality which you can then pull into any of your other scripts. In this case, we’re going to take the createSalt, hash, zumoJwt, and slowEquals methods and put them all into a shared script file (called jwthelper.js for LensRocket). Not all of these methods are used in both the login and register methods but it’s a good place to put all this similar code:
Note that we’re going to pass the master key into this script when it’s needed. If we wanted to we could also pull the master key value directly into this script by requiring the mobileservice-config module and using that to access the masterKey property. One difference I had to make in the midst of working on LensRocket was the addition of an expiration in the JWT creation method. Expiration is now required. I didn’t want the users to be kicked out unless they actively logged out so I’m setting the expiration to be sometime in the future (like ten years in the future). If you wanted users to be more regularly forced to log in, you would just need to alter the expiration to be a (much) smaller value. Now that I’ve added that file, I can make use of all of those methods from any of my other scripts.
Simplifying our Login and Register
Now that we’ve moved that code to our shared script, our login and register custom APIs become all about the logic and not about the cruft of creating the underlying JWT stuff. First up is our register API:
The first thing we have is our require line which pulls in our shared script. From there, we get to our actual Register method. We first check that the length of the password is at least 7 characters and then that the email address used doesn’t already exist. You could do any other sort of password validation (i.e. at least X different types of characters) here. Once we know everything is good we can generate a JWT, save our account data, and send it back to the calling application. For logging in, pull out the record that matches the username / email address sent in and then compare the password hash against the one saved. Finally we create a JWT and hand it back:
Today we saw how shared scripts help simplify the functionality in our Mobile Service scripts. We also saw how we can use Custom APIs to simplify the design of our backend and avoid using table scripts as virtual endpoints. As more features are added to Mobile Services you’ll see even more elegant solutions to problems like Custom Auth. You can check out both the Android client code and the server side scripts for LensRocket here.