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