Usability - Productivity - Business - The web - Singapore & Twins

Running a CouchDB with the authenticated Apache HTTP user

Apache CouchDB shares the same Stallgeruch with Domino thanks to sharing a warden at some time. So during the festive season I gave it a spin.
There is ample literature around to get you started with CouchDB including Apache's own wiki.
So I was looking for something more sporty.
Since Domino 9.0 ships with IBM's version of the Apache HTTP server I was wondering if I could setup couchDB behind an Apache reverse Proxy and make couchDB recognize the authenticated user accessing the couchDB as kind of a poor man's single sign on.
I used Apache's basic authentication (only via HTTPs please), but it, in theory, would work with any authentication scheme that provides a username as outcome.
The whole solution required a bit of chicken string and duct tape combination of Apache modules, but works surprisingly well.
The participants:
  • proxy_authentification_handler (note the unconventional spelling): a couchDB module that accepts authentication information in the request header. You have to add that to the httpd section for the key authentication handlers. My entry looks like this: {couch_httpd_oauth, oauth_authentication_handler}, {couch_httpd_auth, proxy_authentification_handler}, {couch_httpd_auth, cookie_authentication_handler}, {couch_httpd_auth, default_authentication_handler}
  • mod_headers: Create, remove, alter headers. Anything coming in gets stripped of eventually fake headers and then the couchDB headers reapplied.
  • mod_proxy: The core proxy capability
  • mod_rewrite: The dark magic of Apache. Used here mainly to lookup roles
  • mod_auth_basic: Used for authentication here, any other mechanis should work too
The whole magic lies in the Apache configuration (typically to find in /etc/apache2/sites-enabled. Here is what worked for me:
  • In line 5-7 I remove any header that might be in the original request to prevent identity spoofing
  • Line 10 allows slashes to be transmitted encoded. I found it wouldn't work without that
  • Line 13-19 are standard Apache static files
  • Line 22-25 establish the regular reverse proxy pattern with the forward proxying switched off, nothing special there
  • Line 28 defines a simple lookup map which in a production system probably would be a LDAP or database query
  • Line 31-36 establish the authentication mechanism. For a production system you would use something more sophisticated to run
  • Line 39 is essential: it simply states: only authenticated users here please
  • The dark magic happens in lines 42-48
  • Line 43 and 45 extract the identified user for use in a RewriteRule. It seems you can use the extracted variable only once, hence the duplicate lines (I might also simply not be skilled enough )
  • Line 44 assigns the current user to the variable CUSER
  • Line 46 looks up the roles the user has into CROLE. Make sure your admin user has the role _admin. Multiple entries separated by comma and no spaces. If a user has no roles, (s)he is assigned the guest role
  • Lines 47/48 finally add them to the header
  • I didn't use the Token in this example
As usual YMMV - enjoy
  1. < VirtualHost *: 80>
  2.     ServerAdmin webmaster@localhost
  4.     # Removal of eventually spoofed request headers
  5.     RequestHeader unset X -Auth -CouchDB -UserName
  6.     RequestHeader unset X -Auth -CouchDB -Roles
  7.     RequestHeader unset X -Auth -CouchDB -Token
  9.     # Needed for CouchDB
  10.     AllowEncodedSlashes On
  12.     # Location of static HTML files
  13.     DocumentRoot /var/www/default
  14.     < Directory />
  15.         Options Indexes FollowSymLinks MultiViews
  16.         AllowOverride None
  17.         Order allow, deny
  18.         allow from all
  19.     </ Directory>
  21.     # We don't want to be an open relay
  22.     ProxyRequests Off
  23.     ProxyPreserveHost On    
  24.     ProxyPass /couchdb http://localhost: 5984 nocanon
  25.     ProxyPassReverse /couchdb http://localhost: 5984
  27.     # Role mapping for couch
  28.     RewriteMap role -map dbm:/var/secrets/passwd/rolemapping.map
  30.     < Location /couchdb>
  31.         AuthType Basic
  32.         AuthName couchdb
  33.         AuthUserFile /var/secrets/passwd/users
  34.         AuthGroupFile /var/secrets/passwd/groups
  35.         Order allow, deny
  36.         Allow from all
  39.         Require valid - user
  41.         # Request headers for CouchDB from authenticated user
  42.         RewriteEngine On
  43.         RewriteCond % {LA -U:REMOTE_USER } (. + )
  44.         RewriteRule . - [E=CUSER:%1 ]
  45.         RewriteCond % {LA -U:REMOTE_USER } (. + )
  46.         RewriteRule . - [E=CROLE:$ {role -map:%1|guest } ]
  47.         RequestHeader set X -Auth -CouchDB -UserName "%{CUSER}e" env=CUSER
  48.         RequestHeader set X -Auth -CouchDB -Roles "%{CROLE}e" env=CROLE
  49.     </ Location>
  50. </ VirtualHost>

Posted by on 23 January 2013 | Comments (2) | categories: CouchDB


  1. posted by Stephan H. Wissel on Friday 25 July 2014 AD:
    The link in the bullet list points to the instructions how to make a mapping file. It is a space separated file with roles

    johndoe admin,family,dev
    janedoe dev

    then you use httx2dbm tool to create the map file. Which part didn't work?
  2. posted by Steven Wagger on Friday 25 July 2014 AD:
    I've been looking for this! Thank you!

    But it would be kind from you to include the instructions to create the rolemapping.map file. I've been trying to make it work without success... :'(