Couchbase Mobile has an number of important security features. Sync Gateway acts as the intermediary that allows Couchbase Lite to replicate data to Couchbase Server. Naturally many applications want to authenticate users and control what they can do through Sync Gateway. OpenID Connect offers an option that simultaneously simplifies adding authentication, gives developers a big step up in integration options, and removes the headache of supporting the infrastructure needed.
Let me clarify a little. In a typical scenario, an application uses Couchbase Lite as its primary data store. Information gets read from and written to the local database. The application sets up replication to a backend server through a Sync Gateway instance running in the cloud.
Often, as the application developer, you want to tie data to a unique, verifiable identity. Details of the identity don’t really matter. Managing the infrastructure becomes unnecessary overhead. OpenID Connect provides the way to offload this to other trusted sources.
Let’s spell out all the actors. We have the user, the application, Couchbase Lite (integrated in the application), our Sync Gateway instance, and OpendID Provider (OP).
Sync Gateway controls authorizing any changes during replication. The goal then, is to have the user log in on the application by authenticating themselves to the OP. The OP provides information back the application can then use to provide Sync Gateway proof of the user’s identity. We’ll walk through all the steps for this.
Many services already exist that require users to create an account and so on. The OpenID Foundation formed to build standards to open up the authentication portions of these systems to outside use. This effort produced the OpenID Connect specification. In the words of the OpenID Foundation:
OpenID Connect is an interoperable authentication protocol based on the OAuth 2.0 family of specifications. It uses straightforward REST/JSON message flows with a design goal of “making simple things simple and complicated things possible”. It’s uniquely easy for developers to integrate, compared to any preceding Identity protocol.
To find out more about OpenID Connect, you can take a look at the links above. I also found this write-up valuable.
OpenID Connect follows three possible “flows”. A flow specifies the back and forth stages of the protocol, and all the details of what parameters are necessary and what they mean. We’ll talk about the Authorization Code Flow (auth flow) here. The auth flow sets up refresh capabilities, so if you don’t want to bother a user to sign in too often, it’s the one to use.
Couchbase has implemented classes to abstract out much of the complexity of OpendID Connect. Like other parts of Couchbase Lite, the authentication classes handle a lot behind the scenes, especially the network calls.
Still, a full code sample is too much for one blog post. I’ll provide simplified examples. To see a complete application, take a look at the GrocerySync projects under couchbaselabs on Github. Here are links for Android and iOS. (Note as of this writing you need to switch to the openid branch.)
Let’s walk through the key steps in implementing authentication in an Android app. We’ll use Google as our OpenID Provider (OP).
On Android, you can implement something directly, use the Google Sign-In client library, or use the wrappers built into Couchbase Lite. We’ll use the Couchbase Lite wrappers. To understand the underlying code better, you might want to check out Google’s documentation on implementing OpenID Connect. You can find it here.
In Couchbase, we refer to syncing database changes as replication. No surprise then, that authentication ties deeply to replication. Briefly, to sync, you create replication objects, set some options, then fire them up, either in one-shot or continuous mode.
You typically do authentication by creating an Authenticator object and assigning it to a Replication object. Couchbase Lite has factories for creating different types of authenticators. You can read more about replications, Replication objects, and authenicators here.
In my simple example app, the first Activity on launch presents two buttons, one to sign in, and one to sign out. I’ll refer to this as the main activity. If the user isn’t signed in, clicking the sign in button launches an activity with a web view to handle the sign in process. I’ll call that the login activity. Storing the credentials happens after returning to the main activity.
The code comprises three key sections, spread across these two activities.
Prepare a Replication
Replications have a “direction”. A pull replication transfers data from a Sync Gateway, while a push sends data to one. Here I just set up a pull replication, to highlight the authentication piece. The code is broken out, but gets called during onCreate in the main activity.
The critical part, for our purposes, lies in creating the authenticator. Don’t let the length of the code lines fool you. It’s all very straightforward. It might help to examine the code from the inside out.
Take a look at the body of the callback method. It takes three input parameters. One it saves for later. Two it puts into an Intent. That intent kicks off the login activity and asks to receive a result.
All the formulating of the URLs the way OpenID needs them has been done for you. For example, when I checked the loginURL, it was well over 400 characters long with what looked like more than 15 parameters! Having implemented an OAuth 2 flow myself managing the network calls and all, I can definitely say this is a lot nicer.
We’ll see later how the Sync Gateway configuration feeds into this flow. For the moment, if you do examine the URLs, know Sync Gateway supplies portions in response to the initial unauthenticated kick off of a replication.
The third parameter to the callback method (the OIDCLoginContinuation interface implementation) is supplied by Couchbase Lite. This is the hook that you use to pass back the results of the sign on. We’ll explore it in more detail in a moment.
return(true);// true => application will handle this
return(false);// Webview will load url
(Note Android Studio may give you a warning about shouldOverrideUrlLoading being deprecated. As of this writing, this version is still the most widely supported.)
When you supply a WebViewClient, Android uses it to hook all new page loads. OpenID encodes the result of an authentication attempt in the form of a URL with, once again, a bunch of parameters embedded. Our WebViewClient waits to spot the redirect URL, packages that up, and ends the login activity, returning back to our main activity. You may want to look into handling this with an AsyncTask to add extras like a progress bar.
The login activity passes the response url back to the main activity. To complete the authentication process (including storing credentials), Couchbase Lite supplies its own callback, one that implements the OIDCLoginContinuation interface. The interface takes two arguments, the result url, and an exception. The comments in the code snippet explain the semantics of the arguments, including how combinations of null and non-null values indicate success or other outcomes.
I handle errors simplistically for illustration. You will likely want to do something more sophisticated. The response url can contain error information if something goes wrong. You can use that to give the user more detailed insight into what failed.
App Code Summary
Using the Couchbase Lite classes, we have a very simple flow. We set up an authenticator and attach it to a replication. We start the replication, possibly in response to a user action (i.e. clicking the sign-in button).
The authenticator hands us back control along with three pre-formed elements, two urls and a Couchbase Lite supplied callback. We proceed with the authentication however we choose. And, finally, we need to finish off by calling the callback we received.
Tips and Tricks
We didn’t show it in the code, but often you’ll want to assign some kind of user id based on information in the OpenID response. You can use the id to create a Sync Gateway channel to filter documents, for example.
You can clear the credentials from a replication by calling theclearAuthenticationStores method. If you used a web view, you may also want to get rid of any session cookies. This code snippet shows how to do that with Android API 21 or later.
You can test your code using an emulator and a Sync Gateway instance running on the same machine. Common emulators like the one supplied with Android or the one by Genymotion will allow you to connect to a service on your machine using a special IP address. Google’s OP will often reject these in urls, though. I used a trick where Sync Gateway specifies localhost as its address. Then in the onActivityResult call, I substitute the IP address required by the emulator with this line:
We’re done with the application code. Let’s take a brief look at configuring Sync Gateway to use OIDC. This sample configuration shows how to configure GoogleAuthFlow as a provider. You’ll need to generate your own client_id and validation_key for production. See the Google documentation and links for details. Find out more about Sync Gateway and how to configure it in the Couchbase documentation here.
In part, this blog outlines using a web view as part of the authentication process. This approach has drawbacks, including the possibility that the app can eavesdrop on the authentication process. For increased security, you may wish to consider using the system browser instead. For more details, I recommend reading the latest version of this IETF Internet-Draft. Security tends to be a moving target. If you’re dealing with highly sensitive information, take the time to read up on current best practices.
Posted by Hod Greeley, Developer Advocate, Couchbase
Hod Greeley is a Developer Advocate for Couchbase, living in Silicon Valley. He has over two decades of experience as a software engineer and engineering manager. He has worked in a variety of software fields, including computational physics and chemistry, computer and network security, finance, and mobile. Prior to joining Couchbase in 2016, Hod led developer relations for mobile at Samsung. Hod holds a Ph.D. in chemical physics from Columbia University.