Short description

Currently the SSL Client Certificate authentication only seems to work with Apache, and other web servers that provide the parts of the subject distinguished name separately. Nginx for instance only supports sending the whole subject or issuer name as a string. Here is a little patch (diff to 1.9.7) that enables using SSLClientCertAuth also with nginx. Handles authentication with email or commonname in the subject name, but can be easily improvided to handle the organization in the issuer name as well.

diff -r 77533e162654 MoinMoin/auth/sslclientcert.py
--- a/MoinMoin/auth/sslclientcert.py    Tue Aug 13 12:17:47 2013 +0200
+++ b/MoinMoin/auth/sslclientcert.py    Fri Sep 06 15:16:42 2013 +0300
@@ -42,13 +42,31 @@
             if self.authorities and env.get('SSL_CLIENT_I_DN_OU') in self.authorities:
                 return user_obj, True
 
+            # some web servers parse the distinguished name for us
+            email = ''
+            commonname = ''
+            if self.email_key:
+                email = env.get('SSL_CLIENT_S_DN_Email', '').decode(config.charset)
+            if self.name_key:
+                commonname = env.get('SSL_CLIENT_S_DN_CN', '').decode(config.charset)
+
+            # others just send the unparsed name
+            if not email and not commonname:
+                dn = env.get('SSL_CLIENT_S_DN', '').decode(config.charset)
+                for p in dn.split('/'):
+                    tmp = p.split('=')
+                    if 2 == len(tmp):  
+                        (name, value) = (tmp[0], tmp[1])
+                        if 'CN' == name:
+                            commonname = value
+                        elif 'emailAddress' == name:
+                            email = value
+
             email_lower = None
             if self.email_key:
-                email = env.get('SSL_CLIENT_S_DN_Email', '').decode(config.charset)
                 email_lower = email.lower()
             commonname_lower = None
             if self.name_key:
-                commonname = env.get('SSL_CLIENT_S_DN_CN', '').decode(config.charset)
                 commonname_lower = commonname.lower()
             if email_lower or commonname_lower:
                 for uid in user.getUserList(request):

The needed configuration in /etc/nginx/nginx.conf running moin over uwsgi is like this:

server {
  listen 443;
  ssl on;
  ssl_client_certificate /path/to/ca.crt;
  ssl_verify_client on;

  location / {
     uwsgi_param SSL_CLIENT_VERIFY  $ssl_client_verify;
     uwsgi_param SSL_CLIENT_S_DN    $ssl_client_s_dn;


CategoryFeatureRequest

MoinMoin: FeatureRequests/SslClientAuthenticationForNginx (last edited 2013-09-06 12:17:37 by JuhaniMäkelä)