1.. Licensed under the Apache License, Version 2.0 (the "License"); you may not
2.. use this file except in compliance with the License. You may obtain a copy of
3.. the License at
4..
5..   http://www.apache.org/licenses/LICENSE-2.0
6..
7.. Unless required by applicable law or agreed to in writing, software
8.. distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
9.. WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
10.. License for the specific language governing permissions and limitations under
11.. the License.
12
13.. _intro/security:
14
15========
16Security
17========
18
19In this document, we'll look at the basic security mechanisms in CouchDB:
20`Basic Authentication` and `Cookie Authentication`. This is how CouchDB
21handles users and protects their credentials.
22
23Authentication
24==============
25
26CouchDB has the idea of an *admin user* (e.g. an administrator, a super user,
27or root) that is allowed to do anything to a CouchDB installation. By default,
28one admin user **must** be created for CouchDB to start up successfully.
29
30CouchDB also defines a set of requests that only admin users are allowed to
31do. If you have defined one or more specific admin users, CouchDB will ask for
32identification for certain requests:
33
34- Creating a database (:put:`PUT /database </{db}>`)
35- Deleting a database (:put:`DELETE /database </{db}>`)
36- Setup a database security (:put:`PUT /database/_security
37  </{db}/_security>`)
38- Creating a design document (:put:`PUT /database/_design/app
39  </{db}/_design/{ddoc}>`)
40- Updating a design document (:put:`PUT /database/_design/app?rev=1-4E2
41  </{db}/_design/{ddoc}>`)
42- Deleting a design document (:delete:`DELETE /database/_design/app?rev=2-6A7
43  </{db}/_design/{ddoc}>`)
44- Triggering compaction (:post:`POST /database/_compact </{db}/_compact>`)
45- Reading the task status list (:get:`GET /_active_tasks </_active_tasks>`)
46- Restarting the server on a given node
47  (:post:`POST /_node/{node-name}/_restart </_restart>`)
48- Reading the active configuration
49  (:get:`GET /_node/{node-name}/_config </_config>`)
50- Updating the active configuration
51  (:put:`PUT /_node/{node-name}/_config/section/key </_config/{section}/{key}>`)
52
53Creating a New Admin User
54-------------------------
55
56If your installation process did not set up an admin user, you will have to add
57one to the configuration file by hand and restart CouchDB first. For the purposes of
58this example, we'll create a default ``admin`` user with the password ``password``.
59
60.. warning::
61    Don't just type in the following without thinking! Pick a good name for your
62    administrator user that isn't easily guessable, and pick a secure password.
63
64To the end of your ``etc/local.ini`` file, after the ``[admins]`` line, add the text
65``admin = password``, so it looks like this:
66
67.. code-block:: ini
68
69    [admins]
70    admin = password
71
72(Don't worry about the password being in plain text; we'll come back to this.)
73
74Now, restart CouchDB using the method appropriate for your operating system.
75You should now be able to access CouchDB using your new administrator account::
76
77    > curl http://admin:password@127.0.0.1:5984/_up
78    {"status":"ok","seeds":{}}
79
80Great!
81
82Let's create an admin user through the HTTP API. We'll call her ``anna``, and
83her password is ``secret``.  Note the double quotes in the following code; they
84are needed to denote a string value for the :ref:`configuration API
85<api/config>`::
86
87    > HOST="http://admin:password@127.0.0.1:5984"
88    > NODENAME="_local"
89    > curl -X PUT $HOST/_node/$NODENAME/_config/admins/anna -d '"secret"'
90    ""
91
92As per the :ref:`_config <api/config>` API's behavior, we're getting the previous value
93for the config item we just wrote. Since our admin user didn't exist, we get an empty
94string.
95
96Please note that ``_local`` serves as an  alias for the local node name, so for all
97configuration URLs, ``NODENAME`` may be set to ``_local``, to interact with the local
98node’s configuration.
99
100.. seealso::
101    :ref:`Node Management <cluster/nodes>`
102
103Hashing Passwords
104^^^^^^^^^^^^^^^^^
105
106Seeing the plain-text password is scary, isn't it? No worries, CouchDB doesn't
107show the plain-text password anywhere. It gets hashed right away. Go ahead and
108look at your ``local.ini`` file now. You'll see that CouchDB has rewritten the
109plain text passwords so they are hashed:
110
111.. code-block:: ini
112
113    [admins]
114    admin = -pbkdf2-71c01cb429088ac1a1e95f3482202622dc1e53fe,226701bece4ae0fc9a373a5e02bf5d07,10
115    anna = -pbkdf2-2d86831c82b440b8887169bd2eebb356821d621b,5e11b9a9228414ab92541beeeacbf125,10
116
117The hash is that big, ugly, long string that starts out with ``-pbkdf2-``.
118
119To compare a plain-text password during authentication with the stored hash,
120the hashing algorithm is run and the resulting hash is compared to the stored
121hash. The probability of two identical hashes for different passwords is too
122insignificant to mention (c.f. `Bruce Schneier`_). Should the stored hash fall
123into the hands of an attacker, it is, by current standards, way too inconvenient
124(i.e., it'd take a lot of money and time) to find the plain-text password from
125the hash.
126
127.. _Bruce Schneier: http://en.wikipedia.org/wiki/Bruce_Schneier
128
129When CouchDB starts up, it reads a set of ``.ini`` files with config settings. It
130loads these settings into an internal data store (not a database). The config
131API lets you read the current configuration as well as change it and create new
132entries. CouchDB writes any changes back to the ``.ini`` files.
133
134The ``.ini`` files can also be edited by hand when CouchDB is not running.
135Instead of creating the admin user as we showed previously, you could have
136stopped CouchDB, opened your ``local.ini``, added ``anna = secret`` to the
137:config:section:`admins`, and restarted CouchDB. Upon reading the new line from
138``local.ini``, CouchDB would run the hashing algorithm and write back the hash
139to ``local.ini``, replacing the plain-text password — just as it did for our
140original ``admin`` user. To make sure CouchDB only hashes plain-text passwords
141and not an existing hash a second time, it prefixes the hash with ``-pbkdf2-``,
142to distinguish between plain-text passwords and `PBKDF2`_ hashed passwords. This
143means your plain-text password can't start with the characters ``-pbkdf2-``,
144but that's pretty unlikely to begin with.
145
146.. _PBKDF2: http://en.wikipedia.org/wiki/PBKDF2
147
148.. _intro/security/basicauth:
149
150Basic Authentication
151--------------------
152
153CouchDB will not allow us to create new databases unless we give the correct admin user
154credentials. Let's verify::
155
156    > HOST="http://127.0.0.1:5984"
157    > curl -X PUT $HOST/somedatabase
158    {"error":"unauthorized","reason":"You are not a server admin."}
159
160That looks about right. Now we try again with the correct credentials::
161
162    > HOST="http://anna:secret@127.0.0.1:5984"
163    > curl -X PUT $HOST/somedatabase
164    {"ok":true}
165
166If you have ever accessed a website or FTP server that was password-protected,
167the ``username:password@`` URL variant should look familiar.
168
169If you are security conscious, the missing ``s`` in ``http://`` will make you
170nervous. We're sending our password to CouchDB in plain text. This is a bad
171thing, right? Yes, but consider our scenario: CouchDB listens on ``127.0.0.1``
172on a development box that we're the sole user of. Who could possibly sniff our
173password?
174
175If you are in a production environment, however, you need to reconsider. Will
176your CouchDB instance communicate over a public network? Even a LAN shared
177with other collocation customers is public. There are multiple ways to secure
178communication between you or your application and CouchDB that exceed the
179scope of this documentation. CouchDB as of version :ref:`1.1.0 <release/1.1.0>`
180comes with :ref:`SSL built in <config/ssl>`.
181
182.. seealso::
183    :ref:`Basic Authentication API Reference <api/auth/basic>`
184
185.. _intro/security/cookie:
186
187Cookie Authentication
188---------------------
189
190Basic authentication that uses plain-text passwords is nice and convenient,
191but not very secure if no extra measures are taken. It is also a very poor
192user experience. If you use basic authentication to identify admins,
193your application's users need to deal with an ugly, unstylable browser modal
194dialog that says non-professional at work more than anything else.
195
196To remedy some of these concerns, CouchDB supports cookie authentication.
197With cookie authentication your application doesn't have to include the ugly
198login dialog that the users' browsers come with. You can use a regular HTML
199form to submit logins to CouchDB. Upon receipt, CouchDB will generate a
200one-time token that the client can use in its next request to CouchDB. When
201CouchDB sees the token in a subsequent request, it will authenticate the user
202based on the token without the need to see the password again. By default,
203a token is valid for 10 minutes.
204
205To obtain the first token and thus authenticate a user for the first time,
206the username and password must be sent to the :ref:`_session <api/auth/session>`
207API. The API is smart enough to decode HTML form submissions, so you don't have
208to resort to any smarts in your application.
209
210If you are not using HTML forms to log in, you need to send an HTTP request
211that looks as if an HTML form generated it. Luckily, this is super simple::
212
213    > HOST="http://127.0.0.1:5984"
214    > curl -vX POST $HOST/_session \
215           -H 'Content-Type:application/x-www-form-urlencoded' \
216           -d 'name=anna&password=secret'
217
218CouchDB replies, and we'll give you some more detail::
219
220    < HTTP/1.1 200 OK
221    < Set-Cookie: AuthSession=YW5uYTo0QUIzOTdFQjrC4ipN-D-53hw1sJepVzcVxnriEw;
222    < Version=1; Path=/; HttpOnly
223    > ...
224    <
225    {"ok":true}
226
227A :statuscode:`200` response code tells us all is well, a :header:`Set-Cookie`
228header includes the token we can use for the next request, and the standard JSON
229response tells us again that the request was successful.
230
231Now we can use this token to make another request as the same user without
232sending the username and password again::
233
234    > curl -vX PUT $HOST/mydatabase \
235           --cookie AuthSession=YW5uYTo0QUIzOTdFQjrC4ipN-D-53hw1sJepVzcVxnriEw \
236           -H "X-CouchDB-WWW-Authenticate: Cookie" \
237           -H "Content-Type:application/x-www-form-urlencoded"
238    {"ok":true}
239
240You can keep using this token for 10 minutes by default. After 10 minutes you
241need to authenticate your user again. The token lifetime can be configured
242with the timeout (in seconds) setting in the :ref:`chttpd_auth
243<config/chttpd_auth>` configuration section.
244
245.. seealso::
246    :ref:`Cookie Authentication API Reference <api/auth/cookie>`
247
248Authentication Database
249=======================
250
251You may already note that CouchDB administrators are defined within the config
252file and are wondering if regular users are also stored there. No, they are not.
253CouchDB has a special `authentication database`, named ``_users`` by default,
254that stores all registered users as JSON documents.
255
256This special database is a `system database`. This means that while it shares
257the common :ref:`database API <api/database>`, there are some
258special security-related constraints applied. Below is a list of how the
259`authentication database` is different from the other databases.
260
261- Only administrators may browse list of all documents
262  (:get:`GET /_users/_all_docs </{db}/_all_docs>`)
263- Only administrators may listen to :ref:`changes feed
264  <changes>` (:get:`GET /_users/_changes </{db}/_changes>`)
265- Only administrators may execute design functions like :ref:`views <viewfun>`.
266- There is a special design document ``_auth`` that cannot be modified
267- Every document except the `design documents` represent registered
268  CouchDB users and belong to them
269- By default, the ``_security`` settings of the ``_users`` database disallow
270  users from accessing or modifying documents
271
272.. note::
273
274    Settings can be changed so that users do have access to the ``_users`` database,
275    but even then they may only access (:get:`GET /_users/org.couchdb.user:Jan
276    </{db}/{docid}>`) or modify (:put:`PUT /_users/org.couchdb.user:Jan
277    </{db}/{docid}>`) documents that they own. This will not be possible in CouchDB 4.0.
278
279These draconian rules are necessary since CouchDB cares about its users'
280personal information and will not disclose it to just anyone. Often, user
281documents contain system information like `login`, `password hash` and `roles`,
282apart from sensitive personal information like real name, email, phone, special
283internal identifications and more. This is not information that you
284want to share with the World.
285
286Users Documents
287---------------
288
289Each CouchDB user is stored in document format. These documents contain
290several *mandatory* fields, that CouchDB needs for authentication:
291
292- **_id** (*string*): Document ID. Contains user's login with special prefix
293  :ref:`org.couchdb.user`
294- **derived_key** (*string*): `PBKDF2`_ key derived from salt/iterations.
295- **name** (*string*): User's name aka login. **Immutable** e.g. you cannot
296  rename an existing user - you have to create new one
297- **roles** (*array* of *string*): List of user roles. CouchDB doesn't provide
298  any built-in roles, so you're free to define your own depending on your needs.
299  However, you cannot set system roles like ``_admin`` there. Also, only
300  administrators may assign roles to users - by default all users have no roles
301- **password** (*string*): A plaintext password can be provided, but will be replaced
302  by hashed fields before the document is actually stored.
303- **password_sha** (*string*): Hashed password with salt. Used for ``simple``
304  `password_scheme`
305- **password_scheme** (*string*): Password hashing scheme. May be ``simple`` or
306  ``pbkdf2``
307- **salt** (*string*): Hash salt. Used for both ``simple`` and ``pbkdf2``
308  ``password_scheme`` options.
309- **iterations** (*integer*): Number of iterations to derive key, used for ``pbkdf2``
310  ``password_scheme``
311- **type** (*string*): Document type. Constantly has the value ``user``
312
313Additionally, you may specify any custom fields that relate to the target
314user.
315
316.. _org.couchdb.user:
317
318Why the ``org.couchdb.user:`` prefix?
319^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
320
321The reason there is a special prefix before a user's login name is to have
322namespaces that users belong to. This prefix is designed to prevent
323replication conflicts when you try merging two or more `_user` databases.
324
325For current CouchDB releases, all users belong to the same
326``org.couchdb.user`` namespace and this cannot be changed. This may be changed
327in future releases.
328
329Creating a New User
330-------------------
331
332Creating a new user is a very trivial operation. You just need to do a
333:method:`PUT` request with the user's data to CouchDB. Let's create a user with
334login `jan` and password `apple`::
335
336    curl -X PUT http://localhost:5984/_users/org.couchdb.user:jan \
337         -H "Accept: application/json" \
338         -H "Content-Type: application/json" \
339         -d '{"name": "jan", "password": "apple", "roles": [], "type": "user"}'
340
341This `curl` command will produce the following HTTP request:
342
343.. code-block:: http
344
345    PUT /_users/org.couchdb.user:jan HTTP/1.1
346    Accept: application/json
347    Content-Length: 62
348    Content-Type: application/json
349    Host: localhost:5984
350    User-Agent: curl/7.31.0
351
352And CouchDB responds with:
353
354.. code-block:: http
355
356    HTTP/1.1 201 Created
357    Cache-Control: must-revalidate
358    Content-Length: 83
359    Content-Type: application/json
360    Date: Fri, 27 Sep 2013 07:33:28 GMT
361    ETag: "1-e0ebfb84005b920488fc7a8cc5470cc0"
362    Location: http://localhost:5984/_users/org.couchdb.user:jan
363    Server: CouchDB (Erlang OTP)
364
365    {"ok":true,"id":"org.couchdb.user:jan","rev":"1-e0ebfb84005b920488fc7a8cc5470cc0"}
366
367The document was successfully created! The user `jan` should now exist in our
368database. Let's check if this is true::
369
370    curl -X POST http://localhost:5984/_session -d 'name=jan&password=apple'
371
372CouchDB should respond with:
373
374.. code-block:: javascript
375
376    {"ok":true,"name":"jan","roles":[]}
377
378This means that the username was recognized and the password's hash matches
379with the stored one. If we specify an incorrect login and/or password, CouchDB
380will notify us with the following error message:
381
382.. code-block:: javascript
383
384    {"error":"unauthorized","reason":"Name or password is incorrect."}
385
386Password Changing
387-----------------
388
389Let's define what is password changing from the point of view of CouchDB and
390the authentication database. Since "users" are "documents", this operation is
391just updating the document with a special field ``password`` which contains
392the *plain text password*. Scared? No need to be. The authentication database
393has a special internal hook on document update which looks for this field and
394replaces it with the *secured hash* depending on the chosen ``password_scheme``.
395
396Summarizing the above process - we need to get the document's content, add
397the ``password`` field with the new password in plain text and then store the
398JSON result to the authentication database. ::
399
400    curl -X GET http://localhost:5984/_users/org.couchdb.user:jan
401
402.. code-block:: javascript
403
404    {
405        "_id": "org.couchdb.user:jan",
406        "_rev": "1-e0ebfb84005b920488fc7a8cc5470cc0",
407        "derived_key": "e579375db0e0c6a6fc79cd9e36a36859f71575c3",
408        "iterations": 10,
409        "name": "jan",
410        "password_scheme": "pbkdf2",
411        "roles": [],
412        "salt": "1112283cf988a34f124200a050d308a1",
413        "type": "user"
414    }
415
416Here is our user's document. We may strip hashes from the stored document to
417reduce the amount of posted data::
418
419    curl -X PUT http://localhost:5984/_users/org.couchdb.user:jan \
420         -H "Accept: application/json" \
421         -H "Content-Type: application/json" \
422         -H "If-Match: 1-e0ebfb84005b920488fc7a8cc5470cc0" \
423         -d '{"name":"jan", "roles":[], "type":"user", "password":"orange"}'
424
425.. code-block:: javascript
426
427    {"ok":true,"id":"org.couchdb.user:jan","rev":"2-ed293d3a0ae09f0c624f10538ef33c6f"}
428
429Updated! Now let's check that the password was really changed::
430
431    curl -X POST http://localhost:5984/_session -d 'name=jan&password=apple'
432
433CouchDB should respond with:
434
435.. code-block:: javascript
436
437    {"error":"unauthorized","reason":"Name or password is incorrect."}
438
439Looks like the password ``apple`` is wrong, what about ``orange``? ::
440
441    curl -X POST http://localhost:5984/_session -d 'name=jan&password=orange'
442
443CouchDB should respond with:
444
445.. code-block:: javascript
446
447    {"ok":true,"name":"jan","roles":[]}
448
449Hooray! You may wonder why this was so complex - we need to retrieve user's
450document, add a special field to it, and post it back.
451
452.. note::
453    There is no password confirmation for API request: you should implement it
454    in your application layer.
455
456Authorization
457=============
458
459Now that you have a few users who can log in, you probably want to set up some
460restrictions on what actions they can perform based on their identity and their
461roles.  Each database on a CouchDB server can contain its own set of
462authorization rules that specify which users are allowed to read and write
463documents, create design documents, and change certain database configuration
464parameters.  The authorization rules are set up by a server admin and can be
465modified at any time.
466
467Database authorization rules assign a user into one of two classes:
468
469- `members`, who are allowed to read all documents and create and modify any
470  document except for design documents.
471- `admins`, who can read and write all types of documents, modify which users
472  are members or admins, and set certain per-database configuration options.
473
474Note that a database admin is not the same as a server admin -- the actions
475of a database admin are restricted to a specific database.
476
477When a database is first created, there are no members or admins.  HTTP
478requests that have no authentication credentials or have credentials for a
479normal user are treated as members, and those with server admin credentials
480are treated as database admins.  To change the default permissions, you must
481create a :ref:`_security <api/db/security>` document in the database::
482
483    > curl -X PUT http://localhost:5984/mydatabase/_security \
484         -u anna:secret \
485         -H "Content-Type: application/json" \
486         -d '{"admins": { "names": [], "roles": [] }, "members": { "names": ["jan"], "roles": [] } }'
487
488The HTTP request to create the `_security` document must contain the
489credentials of a server admin.  CouchDB will respond with:
490
491.. code-block:: javascript
492
493    {"ok":true}
494
495The database is now secured against anonymous reads and writes::
496
497    > curl http://localhost:5984/mydatabase/
498
499.. code-block:: javascript
500
501    {"error":"unauthorized","reason":"You are not authorized to access this db."}
502
503You declared user "jan" as a member in this database, so he is able to read and
504write normal documents::
505
506    > curl -u jan:apple http://localhost:5984/mydatabase/
507
508.. code-block:: javascript
509
510    {"db_name":"mydatabase","doc_count":1,"doc_del_count":0,"update_seq":3,"purge_seq":0,
511    "compact_running":false,"sizes":{"active":272,"disk":12376,"external":350},
512    "instance_start_time":"0","disk_format_version":6,"committed_update_seq":3}
513
514If Jan attempted to create a design doc, however, CouchDB would return a
515401 Unauthorized error because the username "jan" is not in the list of
516admin names and the `/_users/org.couchdb.user:jan` document doesn't contain
517a role that matches any of the declared admin roles.  If you want to promote
518Jan to an admin, you can update the security document to add `"jan"` to
519the `names` array under `admin`.  Keeping track of individual database
520admin usernames is tedious, though, so you would likely prefer to create a
521database admin role and assign that role to the `org.couchdb.user:jan` user
522document::
523
524    > curl -X PUT http://localhost:5984/mydatabase/_security \
525         -u anna:secret \
526         -H "Content-Type: application/json" \
527         -d '{"admins": { "names": [], "roles": ["mydatabase_admin"] }, "members": { "names": [], "roles": [] } }'
528
529See the :ref:`_security document reference page <api/db/security>` for
530additional details about specifying database members and admins.
531