Introduction to CouchDB with .NET part 24: cookie based authentication for the CouchDB HTTP API
July 7, 2017 1 Comment
Introduction
In the previous post we looked at role-based authorisation in CouchDB. With roles it’s easier to assign users as database admins, database members and read-only users than working with names only. It’s enough to assign each CouchDB user to a role and the existing authorisation rules will be applied automatically.
In this post we’ll look at how authentication works for the HTTP API using cookies.
Logging in
Using the CouchDB HTTP API with a cookie follows the same model as many popular public APIs out there. We first have to authenticate ourselves using an endpoint. This is analogous to logging in using a form on a UI. The HTTP API responds with an authentication cookie which must be attached to each subsequent HTTP request. The cookie is by default valid for 600 seconds, i.e. 10 minutes. This value can be adjusted in the configuration file, i.e. either default.ini or local.ini. The setting is called “timeout” in [couch_httpd_auth] section:
timeout = 600 ; number of seconds before automatic logout
Cookies can also be made persistent using the following setting in the same section:
allow_persistent_cookies = false ; set to true to allow persistent cookies
We log in using the POST /_session endpoint and send the username and password in the JSON body. We also need to set the Content-Type header to applications/json:
POST http://localhost:5984/_session
Here’s the payload:
{ "name": "olivia", "password": "secret" }
You can probably guess what the properties in the JSON object stand for.
Since we’re sending our credentials in plain text it’s a good idea to set up HTTPS for our CouchDB server. This guide shows you how to do it.
If the login was successful then the API will respond with some user authentication details:
{ "ok": true, "name": "olivia", "roles": [ "database-read-write" ] }
There will also be a header called Set-Cookie with a value similar to the following:
Set-Cookie: AuthSession=b2xpdmlhOjU5NTI4OUNBOomEzugg8rzgACqaIWWIY4qLjEyB; Version=1; Path=/; HttpOnly
The long string assigned to AuthSession, i.e. b2xpdmlhOjU5NTI4OUNBOomEzugg8rzgACqaIWWIY4qLjEyB in this example, is the cookie itself which must be attached to all subsequent requests. We assigned Olivia to the role “database-read-write” in the previous post and added that role to the database members of the restaurants database. This value must be added as the Cookie header in the request:
Cookie: AuthSession=b2xpdmlhOjU5NTI4OUNBOomEzugg8rzgACqaIWWIY4qLjEyB
Olivia can now execute the following GET request:
http://localhost:5984/restaurants/
The API should respond with summary JSON about the restaurants database.
If, on the other hand, she tries to access the bands database where we set up name-based authorisation she’ll get the following exception in the API response:
{ "error": "forbidden", "reason": "You are not allowed to access this db." }
Getting the current session data
The _session endpoint can be used to get information about our current session:
GET http://localhost:5984/_session
We’ll get some basic user related information in the current session:
{ "ok": true, "userCtx": { "name": "olivia", "roles": [ "database-read-write" ] }, "info": { "authentication_db": "_users", "authentication_handlers": [ "cookie", "default" ], "authenticated": "cookie" } }
If there’s no valid authenticated session then the user context is null:
{ "ok": true, "userCtx": { "name": null, "roles": [] }, "info": { "authentication_db": "_users", "authentication_handlers": [ "cookie", "default" ] } }
Logging out
We can also log out from the session. It is the same endpoint and Cookie header as above but the HTTP verb is delete:
DELETE http://localhost:5984/_session
CouchDB will simply respond with an ok true or false:
{ "ok": true }
Other types of authentication
The simplest authentication type in any application is basic auth. The username and password are concatenated with a colon in between and transformed into a base 64 string. E.g. the username “olivia” and password “secret” are combined into olivia:secret and then converted: b2xpdmlhOnNlY3JldA== . This authentication type for APIs is nowadays considered highly unsafe and outdated since the base64 string can be easily converted back. This online resource lets you convert the string to base 64 and back.
Nonetheless, CouchDB supports basic authentication. We need to attach the base64 authentication information in the Authorization header of every request we send to the API:
Authorization: Basic b2xpdmlhOnNlY3JldA==
OAuth is on the other hand a much safer way to open a session with an API. It allows the caller to communicate with an API without sharing the username and password in any form. However, it’s also more difficult to demo in a simple HTTP client since the process involves signing the request. You can find an example here on how to set up OAuth with CouchDB.
The require_valid_user key
Finally we can mention that there’s a setting in the CouchDB configuration file which helps close off access for unanimous users. It is under the [couch_httpd_auth] section and is called require_valid_user and is by default set to false. Set it to true to restrict access to the database.
Read the next post here where we see how to connect to CouchDB from C#.
You can view all posts related to data storage on this blog here.
Pingback: CouchDB Weekly News, July 13, 2017 – CouchDB Blog