Couchbase Sync Gateway supports OpenID Connect or OIDC-based client authentication.

In this context, clients may be Couchbase Lite clients that synchronize data with Sync Gateway over the Internet using the websockets-based replication protocol or they could be web frontend or mobile apps accessing Sync Gateway through the public REST endpoint.

In the first blog post in this series, we discussed the fundamentals of OIDC and OAuth2 authentication and authorization flows and in last week’s blog post, we learned more in-depth about OIDC implicit flow-based Sync Gateway client authentication.

In this post, I’ll introduce you to OIDC authorization code flow-based client authentication within the context of Couchbase Sync Gateway replication.

This post assumes familiarity with OIDC and OAuth2 flows for authentication and authorization. If you’re unfamiliar with the flows or need a refresher, please check out the earlier blog posts linked above.

Couchbase Sync Gateway OIDC Configuration

The Couchbase Sync Gateway must be configured for OIDC authentication on a per database basis.

Below is a basic OIDC config for Authorization Code. Refer to the official Couchbase documentation for a complete listing of all OIDC config options.

    • issuer is the authentication URL corresponding to the OIDC identity provider
    • client_id is generated as part of the app registration process with the OIDC provider. The client here refers to the Couchbase Lite app or web app. Note that the client_id does not correspond to the end user of the app who is technically the resource owner.
    • validation_key corresponds to the client_secret and should be generated as part of the app registration process with the OIDC provider.
    • callback_url is the URL to be redirected to on Sync Gateway after the client obtains the identity token (ID token).
    • register flag, if set to true, will result in the user being automatically created on Sync Gateway following successful ID token validation.
    • username_claim corresponds to the JWT claim to be used as the Sync Gateway username. By default, the Sync Gateway username would take the form issuer+subject where issuer refers to the username prefix. The prefix value defaults to the issuer claim and can be configured to use a different claim value via the user_prefix config option.
    • disable_session, if set to true, can be used to override the automatic session creation by the Sync Gateway following successful authentication.

Couchbase Sync Gateway OIDC Discovery

On startup, the Sync Gateway connects to the discovery endpoint associated with the configured OIDC provider/issuer to fetch relevant provider metadata. The metadata includes relevant information required for token validation such as issuer public keys, supported encryption algorithms used for encoding the claims in the ID token, etc.

The discovery endpoint corresponds to a well-known discovery URL associated with the issuer. If needed, you can override the URL via Sync Gateway discovery_url config option.

OIDC Authorization Code Flow for Client Authentication

This flow is based on the standard OIDC authorization code flow discussed in the OIDC basics blog (part one of the series).

Authentication

An example of user authentication using OIDC and Couchbase Sync Gateway

  1. When a user logs into the Couchbase Lite client app, the client invokes the _oidc REST endpoint on Sync Gateway to initiate the OIDC Auth Code flow.
  2. Sync Gateway redirects the client app to the OIDC provider URL.
  3. The client initiates the authorization code flow with the OIDC provider to retrieve the authorization code. This is per standard OIDC flow procedures outlined in the OIDC basics blog.
  4. The client is redirected to the Sync Gateway with the authorization code. The redirect URL corresponds to the OIDC callback REST endpoint.
  5. The client app invokes the OIDC callback REST endpoint with the authorization code.
  6. The Sync Gateway exchanges the code for the ID token, the refresh token, and the access token by sending a suitable request to the OIDC provider. The request includes the client_id and client_secret which were configured on Sync Gateway. This allows the OIDC provider to validate that only trusted clients are able to retrieve the tokens.
  7. Sync Gateway validates the ID token locally. Following successful token validation, a corresponding UserCtx object is created.
    • The metadata retrieved from the OIDC Provider Discovery URL during startup is used to validate the token in “offline mode.”
    • If this is the first time that the user is authenticating with the Sync Gateway and if a corresponding user does not exist on the server, the Sync Gateway automatically creates a user if the register config option is set to true.
      • Note: The user that is created is not associated with any access grants such as channels or roles, so this auto registration would work for public users with no user-specific access grants. We will discuss a flow later in this post that describes how to create users with user-specific access grants.
    • A session is created for the user with an idle session timeout of 24 hours. The session is created ONLY IF the disable_session is set to false.
  8. The session ID and refresh tokens are sent back to the client app.
  9. Client app initiates a replication by setting the session ID as the session cookie using the SessionAuthenticator.
  10. Sync Gateway checks the validity of the session to determine if the session has been deleted or has expired.
    • If the session is active, the session gets auto-extended to 24 hours if 10% of idle session timeout has elapsed.
  11. Following successful initialization, replication proceeds as usual and document changes on the client app and Sync Gateway side are synchronized.
    • If the user is deleted during an active replication, the replication is terminated.
    • If the access grants associated with the user have changed, then documents that get impacted by the updated access grants won’t be replicated. So for instance, if a user loses access to a channel, then the documents in that channel won’t be pulled.

Token Refresh

One of the advantages of the authorization code flow is that in addition to the ID token, a refresh token is also returned to the client app. The client app can use the refresh token to automatically request a new auth code without requiring the end user to reauthenticate with their login credentials.

An example of user token refresh using OpenID Connect authorization and Couchbase

  1. When the client app wants to refresh the token, it makes a request to the OIDC refresh REST endpoint with the refresh token.
  2. The Sync Gateway exchanges the refresh token for the updated ID token and access token by sending a suitable request to the OIDC provider. The request includes the client_id and client_secret which were configured on Sync Gateway. This allows the OIDC Provider to validate that only trusted clients are able to retrieve the tokens.
  3. Sync Gateway validates the ID token locally. Following successful token validation, a corresponding UserCtx object is created.
    • The metadata retrieved from the OIDC provider discovery URL during startup is used to validate the token in “offline mode.”
    • A new session is created for the user with an idle session timeout of 24 hours. The session is created ONLY IF the disable_session is set to false.
  4. The session ID and ID tokens are sent back to the client app.
  5. The client app initiates a replication using session ID as the session cookie following the same steps as in the previous flow.

Associating Access Grants to Authenticated Users

Sync Gateway channels and roles are two key elements of Sync Gateway’s access control mechanism. They define the access grants associated with a user, dictating the set of documents that the user has read and write access to.

There are a couple of options to assign access grants to a user:

    • Dynamic assignment of users to channels or roles by the sync function with the access() or role() APIs using an access grant document which specifies the channels or roles that a user must be assigned to.
    • Static assignment of grants to users via the admin _user REST API.

As you’ve seen from the previous flows, the Couchbase Sync Gateway can be configured to automatically create the authenticated user on the Sync Gateway following successful authentication. However, the created user is not associated with any access grants. This works for a public user with public channel access.

But what if you wanted to assign user-specific access grants? This task is typically handled via a backend application server that would be responsible for creating or updating the user. The Sync Gateway is only responsible for OIDC authentication.

Here is a typical flow:

User-specific access grants using OIDC authorization and Couchbase Sync Gateway

  1. A backend process or app server is responsible for registering users with the OIDC provider.
  2. Subsequent to the registration, the app server creates a corresponding user on Sync Gateway via the _user REST API or by adding a suitable access grant document.
  3. Next time the user logs into the app, OIDC authentication proceeds using the authorization code flow procedures described earlier.
  4. Regardless of the type of OIDC flow, once the ID token is validated by the Sync Gateway, the Sync Gateway does not create a user because it already exists.
  5. Replication proceeds as usual using the authenticated user.
  6. If a user is updated on the OIDC Provider, the app server updates the corresponding user on the Sync Gateway via the _user REST API or by updating the access grant document.
    • If a user is deleted during an active replication, the replication is terminated.
    • If the access grants associated with the user have changed, then documents that get impacted by the updated access grants won’t be replicated. For instance, if a user loses access to a channel then the documents in that channel won’t be pulled.

Frequently Asked Question (FAQ)

Which is better: implicit flow or authorization code flow?

There isn’t a preferred flow from my perspective. The implicit flow is simple and is generally preferred by most of our users. Since mobile apps have a secure store, the ID and access tokens can be securely stored in the local keystore on the device. You can learn more in this blog post about how to leverage OIDC implicit flow for Sync Gateway authentication.

The advantage of the authorization code flow is that it provides slightly better security. This is because the tokens are granted to the Sync Gateway in exchange for the authorization code only when the OIDC Provider is presented with a valid client_id and client_secret. This ensures that only authenticated clients get the tokens. Also the refresh tokens allow refreshing of the auth sessions without requiring the end user to enter their credentials every time.

More Resources

In this post, we described OIDC authentication support in Sync Gateway. Here are some additional resources you might want to check out:

If you have questions or feedback, please leave a comment below or email me at priya.rajagopal@couchbase.com. The Couchbase Forums are another good place to reach out with questions.

Acknowledgements

I would like to thank Sync Gateway architect Adam Fraser for his input on this blog post.
 

Catch up with the rest of the posts in this series on authentication and authorization:


 
 
 

Author

Posted by Priya Rajagopal, Senior Director, Product Management

Priya Rajagopal is a Senior Director of Product Management at Couchbase responsible for developer platforms for the cloud and the edge. She has been professionally developing software for over 20 years in several technical and product leadership positions, with 10+ years focused on mobile technologies. As a TISPAN IPTV standards delegate, she was a key contributor to the IPTV standards specifications. She has 22 patents in the areas of networking and platform security.

Leave a reply