neighbourhoodie-nnh-logo

Using Two-Factor Authentication (2FA) in CouchDB posted Wednesday, June 25, 2025 by The Neighbourhoodie Team tipCouchDB

With growing digital security risks it’s becoming increasingly important to implement a secured method of authentication, especially for critical services like database access. The good news is CouchDB supports two factor authentication out-of-the box without any need for extensive configuration.

When enabled, a second factor is required to acquire a session cookie and reject basic authentication attempts (as a second factor cannot be presented).

To enable this, you add a totp object to your user doc with a secret key value. Let’s look at the details on how to do this. See below for an example.

What is TOTP

TOTP or time-based one-time password is a form of two factor authentication which generates a 6-8 digit code that is valid for a specified amount of time only for one login session or transaction. Tools like Aegis, 2FAS, Ente, Google Authenticator etc. can be used to generate these codes when a secret key or QR code is added.

Using TOTP in CouchDB

CouchDB uses the _users database to manage its user account information including information on authentication and authorization. CouchDB stores the TOTP settings per user in this _users database. When this is set the user must provide a valid time-based token along with their username and password to access the database.

Creating a user with TOTP

To get started you’ll be required to create a randomly generated base32 string. This will be used as the token for setting the TOTP for your user. Here’s an example of how a random key can be generated. /dev/urandom ensures the string is random.

# Generate random token key
LC_ALL=C tr -dc 'A-Z2-7' </dev/urandom | head -c 32; echo

Use this token to create a user, passing it under totp and key properties. This will enable two factor authentication for the user. Note that an admin account will be required to create a user. Here is further documentation on creating users in CouchDB.

curl -X PUT http://admin:password@localhost:5984/_users/org.couchdb.user:USERNAME \
     -H "Accept: application/json" \
     -H "Content-Type: application/json" \
     -d '{"name": "USERNAME", "password": "PASSWORD", "roles": [], "type": "user", "totp": {"key": "YOURTOKEN"}}

Logging in with password and TOTP

A TOTP app as mentioned above can be used to create tokens for login. To do so, add the key created in the previous step to your authenticator. This will generate a time bound token which needs to be used for logging in.

To log in, send a post request to _session making sure to pass the token from the authenticator.

curl -X POST http://localhost:5984/_session \
  -H "Content-Type: application/json" \
  -d '{
    "name": "username",
    "password": "password",
    "token": "123456"
  }'

If password and token are both valid CouchDB returns a session cookie that can be used in subsequent requests.

{"ok":true,"name":"ninette2fa","roles":[]}

Tokens generated using the authenticator apps are time bound and generally expire after 30 seconds. When an expired token or wrong password is used, an error message will be displayed.

{"error":"unauthorized","reason":"Name or password is incorrect."}

Saving and using Auth session

The Auth token generated can be saved in a separate .txt file or echoed to be used later.

curl -c cookie.txt -X POST http://localhost:5984/_session \
  -H "Content-Type: application/json" \
  -d '{
    "name": "username",
    "password": "password",
    "token": "123456"
  }'

The auth session can then be passed with each request. For example to view a document the following curl command can be run passing the AuthSession.

# Example passing AuthSession directly
curl -H "Cookie: AuthSession=AUTH_SESSION_COOKIE" http://localhost:5984/DB_NAME/DOC_NAME

# Example using the cookie.txt
curl -b cookie.txt http://localhost:5984/DB_NAME/DOC_NAME

Here are some examples of doing the same requests using fetch() to save and reuse the cookies session.

fetch() in browser using credentials: include

// Log in and store the session cookie in the browser
await fetch('http://localhost:5984/_session', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  credentials: 'include', // Store cookies
  body: JSON.stringify({
    name: username,
    password: 'password',
    token: '123456'
  })
});

// Use the session cookie to access a protected database document
const res = await fetch('http://localhost:5984/DB_NAME/DOC_NAME, {
  credentials: 'include'
});

fetch() with manual cookie handling

const sessionResponse = await fetch('http://localhost:5984/_session', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      name: 'username',
      password: 'password',
      token: '123456'
    })
  });

  const cookie = sessionResponse.headers.get('set-cookie')

  // Use the session cookie to access a protected database document
  const dataResponse = await fetch('http://localhost:5984/DB_NAME/DOC_NAME', {
    headers: {
      Cookie: cookie
    }
  })

Alternatively, secured session handlers like fetch-cookie or axios can be set up to reuse session cookies.

// fetch-cookie
import nodeFetch from 'node-fetch'
import fetchCookie from 'fetch-cookie'

const fetch = fetchCookie(nodeFetch)

// Use `fetchCookie` as you would use `fetch`

And that’s it! Setting up 2FA in CouchDB is a straightforward way to add a layer of security, but more importantly, peace of mind.

« Back to the blog post overview
og-image-preview