The official documentation has moved to http://docs.couchdb.org — The transition is not 100% complete, but http://docs.couchdb.org should be seen as having the latest info. In some cases, the wiki still has some more or older info on certain topics inside CouchDB.

You need to be added to the ContributorsGroup to edit the wiki. But don't worry! Just email any Mailing List or grab us on IRC and let us know your user name.

Security Features Overview

See also the official documentation for the authentication handler, configuration and database security portions of this topic.

An overview of the security features that CouchDB 0.11 provides out of the box.

Authentication

CouchDB 0.11 ships with several authentication handlers:

For each HTTP request that CouchDB receives, one or more authentication handlers are invoked to authenticate the user. Once an authentication handler succeeds, the remaining ones are not executed. Which authentication handlers are used, as well as the order under which they will be invoked, is defined in the .ini configuration files. The default setting, from the etc/couchdb/default.ini file, is:

[httpd]
authentication_handlers = {couch_httpd_oauth, oauth_authentication_handler}, {couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler}

Note: for testing purposes the authentication handler {couch_httpd_auth, null_authentication_handler} can be used. It authenticates any request as being originated by a server admin user.

Authorization

As of CouchDB 0.11, three types of users can be defined:

Server admins are defined in the admins section of the .ini configuration files. See Setting_up_an_Admin_account for more details.

Database admins and members are defined in the security object of a database. This security object, located under "/db_name/_security" in CouchDB version 0.11 and above, is a JSON document having the following structure:

{
  "admins" : {
     "names" : ["joe", "phil"],
     "roles" : ["boss"]
   },
   "members" : {
     "names" : ["dave"],
     "roles" : ["producer", "consumer"]
   }
}

Note that security objects are not regular versioned documents (that is, they are not under MVCC rules). This is a design choice to speedup authorization checks (avoids traversing a database's documents B-Tree).

If both the names and roles fields of either the admins or members properties are empty arrays, it means the database has no admins or members. Having no admins, only server admins (with the reserved _admin role) are able to update design document and make other admin level changes. Having no members, any user can write regular documents (any non-design document) and read documents from the database.

Note: If there are any member names or roles defined for a database, then only authenticated users having a matching name or role are allowed to read documents from the database (or do a GET /db_name/ call).

Each user name mentioned in a database security object refers to a user that is defined in the authentication database. The default name of this database is _users but it is configurable in the .ini configuration files:

[couch_httpd_auth]
authentication_db = _users
require_valid_user = false

The require_valid_user configuration parameter shown above causes CouchDB to have the following behaviour:

  1. No server admins are configured:
    1. require_valid_user is set to false: the request will be validated (by the handler {couch_httpd_auth, default_authentication_handler}) as if it originated from a server admin, but only if the handler did not found any authentication credentials in the user's HTTP request message

    2. require_valid_user is set to true: if none of the configured authentication handlers succeeds, an HTTP message with error code 401 (unauthorized) will be sent back to the requester

  2. There are one or more server admins configured:
    1. require_valid_user is set to false: the request will be validated as "anonymous" (unnamed user, no roles)

    2. require_valid_user is set to true: if none of the configured authentication handlers succeeds, an HTTP message with error code 401 (unauthorized) will be sent back to the requester

Authentication database

The authentication database is a system database called _users.

Currently the documents in the authentication database can only have the type attribute set to "user". Prior to version 1.3.0, such documents have the following structure (see below for 1.3.0 and newer):

{
  "_id"          : "org.couchdb.user:joe",
  "type"         : "user",
  "name"         : "joe",
  "roles"        : ["erlanger"],
  "password_sha" : "fe95df1ca59a9b567bdca5cbaf8412abd6e06121",
  "salt"         : "4e170ffeb6f34daecfd814dfb4001a73"
}

The "_id" attribute value must be prefixed with the string "org.couchdb.user:" and the rest must match the value of the attribute "name". The roles attribute must be an array of roles (and each role is a string). The "password_sha" attribute is an hexadecimal representation of the SHA-1 hash computed over a string that matches the user password concatenated with a salt (ideally a random string). The salt attribute is the hexadecimal representation of the salt used to generate the user's password hash.

Note: If you are using CouchDB versions 1.1.x or earlier, please see "Generating password_sha" below for more about the SHA-1 hash.

Since CouchDB 1.2.0, the password_sha and salt fields are automatically created when a password field is present in the user document. When the user document is written, CouchDB checks for the existence of the password field and if it exists, it will generate a salt, hash the value of the password field and hash the concatenation of the password hash and the salt. It then writes the resulting password into the password_sha field and the salt into the salt field. The password field is removed.

This has the following implications: Clients no longer have to calculate the password salt and hash manually. Yay.

In addition, the _users database is now treated different from other databases:

Some rules regarding user documents:

Finally, server admins can create user documents that represent themselves. This is useful if server admins (which always have the role "_admin") want to have other roles (application specific roles). User documents that represent server admins do not need to have the "password_sha" and "salt" attributes defined - their authentication credentials are stored in the .ini configuration files.

All these rules regarding authentication database documents are enforced by the validate document update function stored in the design document with ID "_design/_auth" found in the authentication database (it is automatically created by CouchDB) and by special system database hooks inside CouchDB.

Generating password_sha (only applicable for 1.1.x and earlier)

password_sha can be generated a number of different ways. Below are some methods that work:

OpenSSL command line tool

$ echo -n "foobar" | openssl sha1
8843d7f92416211de9ebb963ff4ce28125932878

NOTE: Newer versions of openssl include "(stdin)=" in their output. Do NOT include that prefix in your document.

Erlang

Erlang R14B01 (erts-5.8.2) [source] [smp:2:2] [rq:2] [async-threads:4] [hipe] [kernel-poll:true]

Eshell V5.8.2  (abort with ^G)
1> Apache CouchDB 1.2.0ab0c6e32-git (LogLevel=info) is starting.
Apache CouchDB has started. Time to relax.
[info] [<0.37.0>] Apache CouchDB has started on http://127.0.0.1:5984/

1> couch_util:to_hex(crypto:sha("foobar")).
"8843d7f92416211de9ebb963ff4ce28125932878"

Ruby

irb(main):001:0> require 'digest/sha1'
=> true
irb(main):002:0> Digest::SHA1.hexdigest 'foobar'
=> "8843d7f92416211de9ebb963ff4ce28125932878"

Python

>>> import hashlib
>>> h=hashlib.sha1()
>>> h.update('mypassword')
>>> h.update('mysalt')
>>> h.digest()
'O,\x19\xf8\x85\xea\xe0\x88kRo\xda\x96\x824\x87OQ\xbe4'
>>> h.hexdigest()
'4f2c19f885eae0886b526fda968234874f51be34'
>>> # create secure salts using os.urandom
...
>>> salt = os.urandom(16).encode('hex') # 16 byte random salt encoded as hexadecimal string

sha1.js implementation (from CouchDB)

hex_sha1(foobar);

Java (using Jasypt library)

import org.jasypt.digest.StandardStringDigester;

StandardStringDigester digester = new StandardStringDigester();
digester.setAlgorithm("SHA-1");
digester.setIterations(1);
digester.setStringOutputType("hexadecimal");
digester.setSaltSizeBytes(0);
String digested = digester.digest("foobar").toLowerCase();  // 8843d7f92416211de9ebb963ff4ce28125932878

Perl command line utility

This Perl script expects a password on STDIN or as its first parameter, and an optional salt as its second parameter. If no salt is provided, a random one will be selected.

The salt and password_sha are printed on STDOUT.

#!/usr/bin/env perl
# Usage: couchdb_password [password [salt]]  or provide password on STDIN.

use Digest::SHA1 qw(sha1);

my $password;

if(@ARGV) {
  $password = shift;
} else {
  $password = <>;
  chomp $password;
}

my $salt;

if(@ARGV) {
  my $unsalted = shift;
  $salt = pack("H*",$unsalted);
} else {
  # Get some bytes from random
  open(my $urandom, '<', '/dev/urandom') or die $!;
  binmode($urandom);
  my $random_bytes;
  read($urandom,$random_bytes,16) == 16 or die $!;
  close($urandom) or die $!;

  $salt = unpack('H*',sha1($random_bytes));
}

print "salt = $salt\n";

my $password_sha = sha1($password,$salt);
print "password_sha = ".unpack('H*',$password_sha)."\n";

OpenSSL command line version:

$ SALT=`openssl rand 16 | openssl md5`
$ echo salt=$SALT
salt=b7774c617642099bbe6233e9ee08a8eb
$ echo -n "foobar$SALT" | openssl sha1
b79393894929362b5ba006ce210467fec5bae9ef

NOTE: If you have openssl 1.0.0e or newer, the $SALT value includes a '(stdin)=' prefix. You should remove it and calculate password_sha with just the hex part.

Node JS

var crypto = require('crypto');
var password = 'coolbeans';
var salt = crypto.randomBytes(16).toString('hex');
var hash = crypto.createHash('sha1');
hash.update(password + salt);
var password_sha = hash.digest('hex');

pbkdf2 (v1.3.0 or newer)

The default password hashing scheme in version 1.3.0 and newer is now pbkdf2 (replacing SHA1). By using a "slower" hash function along with an iterations parameter, dictionary attacks are now much more difficult to attempt (see issue COUCHDB-1060: CouchDB should use a secure password hash method instead of the current one). This adds a few new keys to user documents. Here's a sample user document with username "username" and password "password":

{
   "_id": "org.couchdb.user:username",
   "_rev": "1-227bbe6ddc1db6826fb6f8a250ef6264",
   "password_scheme": "pbkdf2",
   "iterations": 10,
   "name": "username",
   "roles": [
   ],
   "type": "user",
   "derived_key": "aa7dc3719f9c48f1ac72754b28b3f2b6974c2062",
   "salt": "77bac623e30d91809eecbc974aecf807"
}

The new keys are "password_scheme", "iterations", and "derived_key".

Document Update Validation

See Document_Update_Validation.

Security_Features_Overview (last edited 2013-12-10 22:20:50 by lancecarlson)