Whereas in the last post I showed the theory / basics on custom authentication, in this article we’ll see those concepts applied in a practical example. When it comes to ‘real life’, an integration of couchbase mobile will most probably need to run in parallel with regular REST api supporting calls. That said, to unify/integrate their authentication/authorization processes into one scheme can be the next natural step. In other words, we attempt and make an authentication scheme that is sufficient for both standard REST calls as well as for Sync Gateway’s replication. Along with the tutorial, at the bottom, you will find the source code that contains the implementation number 3 described here.
- oAuth and JSON Web Tokens review
- Federated Authentication & Sync Gateway
- Demo ‘bootstrap’ Project
1- oAuth and JSON Web Tokens review
Whether you’re building a server-side web application, client-side application, the end goal of using oAuth is the same: obtain an oAuth access token that your application can use to perform API requests on behalf of a user or the application itself. The token can then be sent along with your requests on behalf of the user or the application itself in several ways, where one of the preferred is at the HTTP authorisation header:
GET /app/v1/lists/tasks HTTP/1.1
Authorization: Bearer XXX.XXXXX –> token info
Nowadays the token format is commonly based on the JWT (JSON Web Tokens) standard. Such tokens are also what we get (temporary access tokens) when sending requests to popular services such as Facebook, Twitter, Google, etc on user’s behalf. I will not go into deep details on these topics (oauth, JWT) since there is a lot of information about them already – please do some research before continuing if you’re not familiar with the terms. But just to review:
JSON Web Token (JWT) is a standard for creating tokens that assert some number of claims. For example, a server could generate a token that has the claim “logged in as admin” and provide that to a client. The client could then use that token to prove that they are logged in as admin. The tokens are signed by the server’s key, so the server is able to verify that the token is legitimate. It is composed of a header, a payload, and a signature.
If you’re still not confident about it, watch the video below, otherwise just skip to the next section.
Now after that video, everyone should know why the heck there are so many websites offering e.g. login with Facebook. Sometimes the only option, ouch.
Attention with the terms!
Authentication vs. Authorisation – as already explained, these are different things and you probably already know – but it’s still easy to ‘misread’ and confuse the words by accident due their similarity in english – so please pay double attention on which one is it while reading.
2- Federated Authentication & Sync Gateway
oAuth brings the concept of Federated Authentication. Which basically means, delegating the task of authenticating an user through another app.
Couchbase Lite and Sync gateway already have built-in support for some of such services. Using the provided client SDK’s one may fetch a token from these providers, and provide that token to Sync Gateway, which in turn will use it to verify if the user is who he/she claim is. But not all of them are there yet, example: Google and Yahoo aren’t supported out of the box. Still, it’s possible to integrate them with SDK’s and a bit of planning.
If all you are looking for is one of the already supported Auth providers, and / or don’t need your own account system, the sample code provided by Couchbase should suffice and is pretty straight-forward.
However as mentioned, in many other situations we don’t want or can be dependent to a certain Federated provider. One can actually design a system to support multiple Authentication providers under one account (For instance, Stackoverflow allows ‘adding’ more than one Federated Authentication to your account, and in this case if you loose access to one of them you still can access with another).
On top of that, nothing stops one to use a mix of both approaches (federated + ‘in-house/own’ auth), it all depends on your needs. In this article, we’ll be generating/consuming our own JW Tokens – so we are our own authentication provider, like a boss :). Even if you don’t need it, a quick read might give a good insight on Couchbase Mobile handles these integrations today.
3.1 Client Side
The client example is a simple Objective-C class based on AFNetworking for the registration / login requests.
From a security perspective, it is not ‘nice’ to be sending user credentials over and over via HTTP Basic for sync gateway or REST calls even when under SSL (remember, that’s why tokens exists), therefore, in couchbase we’ll opt for session-based authentication. This session token from sync gateway has approximatelly the same effect as the JWT token, but for couchbase-related communication of the respective user.
The most important methods at the client are:
+(void)authenticate:(NSString *)username and:(NSString *)password
onSuccess:(void (^) (void)) successBlock
onError:(void (^) (NSError * )) errorBlock;
+(void)registerUser:(NSString *)username and:(NSString *)password
onSuccess:(void (^) (void)) successBlock
onError:(void (^) (NSError * )) errorBlock;
They call, respectively, the API endpoints at:
http://yourserver.com/api/v1.0/register > for registering a new user
http://yourserver.com/api/v1.0/auth > for obtaining valid API-JWT token along with sync gateway’s session;
And that’s basically all there is for the client side.
3.2- Implementation – Server Side
Let’s now see a few possibilities suggested by Couchbase on how to it setup, then I finalise with a conclusion and respective implementation.
3 CUSTOM AUTH Architecture Examples
Number 1: Sync gateway as “proxy”
At first we’ll take a look at a more recent but not so well documented hook which was added to sync gateway. Honestly it makes integrating custom auth quite straight-forward (I was surprised to find it only here while writing this article: link ). “WebSphere” is a sample app name:
The idea described above is to have simply: the sync gateway in ‘front’ as a proxy, neutral to all requests *except* those to /custom_auth. Custom_auth is a sync gateway special handler which will redirect such requests to a certain end-point in the app server, which in turn helps verifying the credentials, finalising one way of the the cycle. The ‘password’ defined in sync gateway doesn’t really do anything as the final piece that validates the credentials is the app server, and session is what is used for replication auth checks.
Now this solution is *almost* perfect, because there’s way less round-trips (less ping-pong effect) of the requests to get a response. But, do you notice something missing? Yep, where does our needed Jason Web Tokens fit in the picture? It looks great from a Couchbase mobile side, but let’s not forget about the standard requests which also need authentication/authorisation. Of course we could add it separately, but remember that the goal of this article is to better integrate both schemes.
Number 2: Sync gateway as the main Authentication Server
In this case, the sync gateway is itself acting as the ‘Federated Authenticator’, meaning, it’s own database of users (which ultimately will be in a bucket) is what actually defines if the credentials of an user are correct or not, as well as be serving as the central point for user management:
The middle block represents the app server, responsible for forwarding the registration/login requests/verification to the sync gateway. This scheme is well detailed and explained in this: link. However.. yep, still thinking about JWT.
Number 3: Own Authentication Server + JWT
Before proceeding, take a moment to read the “Quick start” of this page (link), to get an overview how the JWT library is implemented, as we will highly rely on it in the following steps.
This is basically the approach described in the previous article, but with some small “tweaks”. Let’s see what they are.
For registration, nothing changes:
- POST /register
- Server checks if information is valid, if yes, create the user in couchbase server’s users bucket and return success.
Once the user is registered, let’s see the authentication steps:
1- First, the client sends a request to /auth end point with user / password, triggering the jwt_flask authentication handler.
This call-back function, is responsible for validating the user and upon success instructs the JWT library to proceed on generating the JTW token. Breaking it down, this function does the following (steps 2 to 3):
2- Check if the credentials are correct against Couchbase’s users bucket.
3- Involving both the sync gateway and the app server, now we take the chance to make sure a valid session is created in the sync gateway (creating the user if necessary) as well (_session request), again, creating a user in the sync gateway if needed.
4- If everything worked, get the sync gateway session and store it in the user object (for later use during the token creation). Now that the JWT authentication handler finished, it will call the payload_handler delegate method, where we have an opportunity to customise the contents of the token, adding the session id from the sync gateway, and finally sending it back to the client:
'exp': (datetime.utcnow() + app.config['JWT_EXPIRATION_DELTA']).isoformat()
5- The client will in turn receive something like (but with the actual token):
HTTP/1.1 200 OK
The JWT validty time is in the demo is in purpose set to expire at the same time as the session from the gateway.
Note that one may modify the token’s data, but since the key used to sign is hidden, doing so will automatically invalidate the token, which can only be properly signed with posession of the private key. (That is, at least until quantum computers don’t reach around 3000 qubits we should be safe 😉 ).
The password in the sync gateway is set to a random bcrypted value, since in this scheme it is not acting as the main Authentication server.
So from now on, the usual REST requests can be made using the token, which will be automatically validated by the JWT library. The client decodes the token and uses the gateway session id to setup Couchbase mobile’s replication. The first time the authentication function runs (where it need to generate the token), there will be an additional delay caused by the ‘extra’ round-trip needed to consult/update the sync gateway. But after that, requests will be quicker until the token expires and the cycle repeats.
The hardest part is breaking it down (understanding). The actual implementation is actually small and involves few lines of code, considering there are already several JWT library available doing part of the work.
Here I leave my idea for Couchbase Mobile, in order to create a better experience for developers when it comes to oAuth.
Expand on the idea/architecture number 1, but include support for JWT already in this step, inside sync gateway, and proxy all other request (which passes JWT validation) to the app server.
Since the developer can modify the token’s payload, we can even think of associating channel data to correlate to token’s permissions (authorisation). And since nobody else can modify the payload without invalidating the token, on a later step there could be handy sync functions which checks for specific fields in the tokens, e.g.: ‘requiresJWT(‘string’)’.
This would totally relieve the developers of worries with authentication, all one needs to do would be respond to whether a user/pass combination is valid or not (checking in whatever datasource they want). . Plus, since there are actually JWT libraries for go, I suspect the changes in code might be minimal and it would be a double win since the developer gets REST API authentication ‘for free’.
Feedback – your opinion
What do you think of the proposed methods? How have your experiences on this topic been? Do you use JWT in your application, or have a different scheme as those proposed here? If so, let us know about it.
I’ve created a message on Couchbase mobile’s google groups to hear what others think about it:
5- Sample demo project
Here is an actual working demo project either to serve as a ‘bootstrap’ to get your next app’s basics up and running so you can more quickly get to your core business (or learn by trying/debugging). As a pre-requisite it is expected that you already have a Couchbase Server instance running and connected with a sync gateway. Nevertheless, it will always be important that you understand all security aspects of your project.
The sample project is available in github:
Disclaimer: Be aware that this initial version provided is very verbose and has not been deeply tested in production; It is there mainly for teaching purposes. In other words: I’m not responsible for what you’ll do with it!
However, If you do find any improvements please fork and send a pull request, so that everyone can benefit. The current implementation is a flask/python app template using flask_jwt module. But even if you’re not familiar with python/flask, it is pretty easy to read and understand what is going on. Again, if you’d like to contribute by providing the code in another language, that would be very welcome as well.