Authentication and Authorization
Disclaimer
These pages attempt to collect strands of thoughts that concern authentication and authorization in CouchDB. These pages do not describe the currently available support for authentication and authorization in CouchDB or any agreed implementation plans.
Discussion threads
The following discussions address authentication and authorization concerns:
2009-09-07 Per-DB Auth Ideas and Proposal
2009-07-10 : Cookie Auth
2009-07-08 : CouchDB shared hosting
2009-06-25 : CouchDB Authentication and Authorization
2009-04-29 : Baking Cookie-Based Authentication into CouchDB
2009-04-20 : Authentication and Authorisation for webmail project
2009-04-12 : auth using Nginx as proxy
2009-04-10 : security and validation API?
2009-03-08 : Proposal for digital signatures of documents (user@couchdb)
2008-11-21 : New Security and Validation Features
2008-07-02 : Security and Validation
2008-04-28 : CouchDB 1.0 work
2009-04-21 : LDAP Authentication handler
2008-01-09 : The planned security model for CouchDB
2008-06-16 : How to contribute - especially authentication
JIRA issues
The following issues address authentication and authorization concerns:
COUCHDB-34 : Enable replicator to use HTTP authentication.
COUCHDB-263 : Require valid user for all database operations.
COUCHDB-420 : OAuth authentication support (2-legged initially) and cookie-based authentication.
COUCHDB-438 : Add per database (OAuth) authentication to couchdb
COUCHDB-329 : Replication from Futon does not copy design docs with admin authentication.
COUCHDB-256 : Replicating from a write-protected server fails
COUCHDB-438 : Add per database (OAuth) authentication to couchdb
Definitions
Authentication:: any process by which you verify that someone is who they claim they are. Authorization:: any process by which someone is allowed to be where they want to go, or to have information that they want to have.
References
Apache 2.2 Authentication, Authorization and Access Control
Apache Tomcat 6 Realms and AAA
Apache Derby derby.authentication.provider
RFC 2617: HTTP Authentication: Basic and Digest Access Authentication
Apache Derby SYSTABLEPERMS Table
Apache Derby SYSCOLPERMS Table
Pluggable Authentication Modules for Linux
RFC 4422: Simple Authentication and Security Layer (SASL)
Announcing Alice and Wonderland
RabbitMQ Management and Monitoring Wiki
RabbitMQ Access Control Design Wiki
OASIS eXtensible Access Control Markup Language (XACML) TC
XML Security: Control information access with XACML
Incubating Shiro (aka Ki, JSecurity) project
Authentication use cases
The following use-cases describe potential usage scenarios for an authentication system. The catalog of use-cases could be helpful to describe the feature set of any proposals and to identify any architectural issues.
NO-IDENTITY: The user is not authenticated. All access is controlled by the rights granted to anonymous users.
FIXED-IDENTITY: The user is specified via configuration.
DECLARED-IDENTITY: The user is specified in the request and not authenticated.
PROXY-AUTH: A reverse proxy authenticates the user and optionally rewrites the request to include the remote user. The authentication handler would extract the remote user from the rewritten request (similar to DECLARED-IDENTITY). The "Via" header could be used to distinguished proxied requests from local or tunnelled requests which could be granted elevated privileges (like local or tunnelled would get <<"_admin">> with current authorization system).
IP-IDENTITY: The originating IP address is used to identify the user. Could be useful for replicating nodes. Local origination could result in elevated privileges.
BASIC-IDENTITY: HTTP Basic Authentication is used to identify the user.
DIGEST-IDENTITY: HTTP Digest Authentication is used to identify the user.
OAUTH-IDENTITY: OAuth is used to identify the user.
LDAP-IDENTITY: LDAP is used to identify the user.
SSL-IDENTITY: An SSL certificate is used to identify the user.
COOKIE-IDENTITY: A cookie is sent that is used for
to provide the identity.
HYBRID-AUTH: An option of different means may be offered to validate the user.
Authentication hooks
CouchDB 0.9.x allows the user to configure an authentication handler in local.ini like:
[httpd] authentication_handler = {modulename, functionname}
SVN HEAD and 0.10.x allow specification of multiple authentication handlers using:
[httpd] authentication_handlers = {modulename, functionname}, (modulename, functionname}
The module must be available on the code path. User provided handlers should be placed in ~couchdb (need to confirm that would be the current working directory) or in a subdirectory under ROOT/lib where root is the Erlang/OTP installation directory.
If not specified in local.ini, the authentication handler specified in default.ini, {couch_httpd, default_authentication_handler}, will be used.
The specified handler is called in couch_httpd::handle_request:
handle_request(MochiReq, DefaultFun, UrlHandlers, DbUrlHandlers, DesignUrlHandlers) -> ... AuthenticationFun = make_arity_1_fun( couch_config:get("httpd", "authentication_handler")), ... {ok, Resp} try HandlerFun(HttpReq#httpd{user_ctx=AuthenticationFun(HttpReq)}) catch
The handler takes an httpd record and returns an user_ctx record. The return value replaces the existing user_ctx member of the httpd record and is passed to a handler for the current request.
user_ctx is defined in src/couch_db.hrl as:
-record(user_ctx, {name=null, roles=[] }).
Authentication handlers
couch_httpd::default_authentication_handler
If the http request contains basic authentication, the user name and password are checked against a configured user list. If the user is recognized as an administrator, the user name and <<"_admin">> (bit stream representation of "_admin") role are added to the user context, otherwise, an exception is thrown. If basic authentication is not present and there are admins defined in the user list, an empty context is returned. If basic authentication is not present and there are no admins defined, then the _admin role is added to the context.
couch_httpd::null_authentication_handler
Any request is granted the <<"_admin">> role.
couch_httpd::special_test_authentication_handler
If the WWW-Authentication header has a value like "X-Couch-Test-Auth username:password", the user name and password are checked against a hard-coded list of username/password combinations. If the request matches, the user name (but not the <<"_admin">> role) is added, otherwise an exception is thrown. If the WWW-Authentication header is not present or does not match the pattern, the <<"_admin role">> is added.
couch_httpd_oauth::oauth_authentication_handler
COUCHDB-420 implemented an OAuth authentication handler now in SVN HEAD and to be included in 0.10.x. The patch also changes couch_httpd to accept a list of authentication handlers instead of a single authentication handler.
Steps to get OAuth authentication working (with the patch installed):
-
in default.d create a file oauth.ini, with contents:
[oauth_consumer_secrets] example.com = sekr1t [oauth_token_secrets] user1 = tokensekr1t [oauth_token_users] user1 = admin_user
-
In Couchdb, create a user document in _users with username = "admin_user", and add the "_admin" role to its "roles" list.
-
In default.ini, change the authentication_handlers line to:
authentication_handlers = {couch_httpd_oauth, oauth_authentication_handler}
-
Install Leah Culver's version of the python oauth library: http://github.com/leah/python-oauth/tree/master 1. Run the following command from the command line (should be one long line):
python -c "URL='http://127.0.0.1:5984/_session';KEY='example.com';TOKEN='user1';SECRET='tokensekr1t';import oauth,httplib;consumer=oauth.OAuthConsumer(KEY,'sekr1t');token=oauth.OAuthToken(TOKEN,SECRET);rq=oauth.OAuthRequest.from_consumer_and_token(consumer,token=token,http_method='GET',http_url=URL,parameters={});rq.sign_request(oauth.OAuthSignatureMethod_HMAC_SHA1(),consumer,token); con=httplib.HTTPConnection('localhost:5984'); con.request('GET',URL,headers=rq.to_header()); print con.getresponse().read()"
If all is well, you should see this response:
{"ok":true,"name":"admin_user","roles":["_admin"]}
Authorization use cases
The following use-cases describe potential usage scenarios for an authorization system. The catalog of use-cases could be helpful to describe the feature set of any proposals and to identify any architectural issues.
ADMIN-PARTY: All requests are authorized.
CONFIGURED-ROOT: All requests are authorized for a configured user or class of users.
DESIGNDOC-AUTHORIZATION: All requests are authorized by evaluating the request against rules stored in design document or documents. This would likely need to involve passing a message to a process that tracks the design documents and which would be able to respond with a go/no-go decision.
VALID-USER: All requests are authorized for authenticated users.
READ-ONLY-ANON: Only read requests are authorized for unauthenticated users.
DENY-ANON: All requests are denied for unauthenticated users.
PER-DB-AUTHORIZATION: Different databases has different authorization schemes.
CUSTOM-AUTHORIZATION: An admin can configure a custom authorization handler.
CONTENT-SENSITIVE: The authorization scheme may evaluate the document (and previous document on updates) before authorizing a GET or PUT.
VIEW-VALUES-ONLY: The authorization scheme may allow a user to retrieve the values from a view, but will reject an attempt to include documents.
PREAPPROVAL: User can request an evaluation if a proposed action would (likely) be approved. This could be used to disable certain parts of a UI that are not appropriate for the user.
Authorization hooks
Authorization is not configurable in CouchDB 0.9.x or the current SVN HEAD. The user_ctx record is examined in couch_db::check_is_admin/1 and couch_db::validate_doc_update/3.
The user_ctx record can be displayed using http://localhost:5984/_whoami on the SVN HEAD.
validate_doc_update functions (see Security_Features_Overview) can examine the user_ctx and reject document modifications.
Proposals
COUCHDB-441 : Insert _user and _timestamp on document writes.
COUCHDB-442 : Add a "view" or "format" function to process source doc on query.