Table of Contents

SSL

Authentication Users Password

Presentation

LL::NG uses Apache SSL module, like any other Apache authentication module, with extra features:

Configuration

By default, SSL is required before the portal is displayed (handled by webserver). If you want to display a button to connect to LLNG (compatible with Combination), you can activate “SSL by Ajax request” in the manager. See SSL by Ajax below.

With Apache

Enable SSL in Apache

You have to install mod_ssl for Apache.

For CentOS/RHEL:

yum install mod_ssl
In Debian/Ubuntu mod_ssl is already shipped in apache*-common package.
For CentOS/RHEL, We advice to disable the default SSL virtual host configured in /etc/httpd/conf.d/ssl.conf.

Apache SSL global configuration

You can then use this default SSL configuration, for example in the head of /etc/lemonldap-ng/portal-apache2.conf:

SSLProtocol all -SSLv2
SSLCipherSuite HIGH:MEDIUM
SSLCertificateFile /etc/httpd/certs/ow2.cert
SSLCertificateKeyFile /etc/httpd/certs/ow2.key
SSLCACertificateFile /etc/httpd/certs/ow2-ca.cert
Put your own files instead of ow2.cert, ow2.key, ow2-ca.cert:
  • SSLCertificateFile: Server certificate
  • SSLCertificateKeyFile: Server private key
  • SSLCACertificateFile: CA certificate to validate client certificates

If you specify port in virtual host, then declare SSL port:

NameVirtualHost *:80
NameVirtualHost *:443

Apache portal SSL configuration

Edit the portal virtual host to enable SSL double authentication:

SSLEngine On
SSLVerifyClient optional
SSLVerifyDepth 10
SSLOptions +StdEnvVars
SSLUserName SSL_CLIENT_S_DN_CN

All SSL options are documented in Apache mod_ssl page.

Here are the main options used by LL::NG:

With Nginx

Enable SSL:

ssl on;
ssl_verify_client optional;
ssl_certificate /etc/letsencrypt/live/my/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/my/privkey.pem;
ssl_verify_depth 3;
ssl_client_certificate /etc/nginx/ssl/ca.pem;
ssl_crl /etc/nginx/ssl/crl/my.crl;

You must also export SSL_CLIENT_S_DN_CN in FastCGI params:

# map directive must be in http context
map $ssl_client_s_dn  $ssl_client_s_dn_cn {
           default           "";
           ~/CN=(?<CN>[^/]+) $CN;
      }
fastcgi_param  SSL_CLIENT_S_DN_CN $ssl_client_s_dn_cn;

Nginx SSL Virtual Host example with uWSGI

server {
  listen 443;
  server_name authssl.example.com;
  root /usr/share/lemonldap-ng/portal/htdocs/;
  # Use "lm_app" format to get username in nginx.log (see nginx-lmlog.conf)
  access_log /var/log/nginx/access.log lm_app;
 
  ssl_verify_client on;
  ssl_verify_depth 3;
 
  # Full chain CRL is required
  # All CRLs must be concatenated in a single .pem format file
  ssl_crl /etc/nginx/ssl/crl/crls.pem;
  if ($uri !~ ^/((static|javascript|favicon).*|.*\.psgi)) {
    rewrite ^/(.*)$ /index.psgi/$1 break;
  }
 
  location ~ ^(?<sc>/.*\.psgi)(?:$|/) {
    # uWSGI Configuration
    include /etc/nginx/uwsgi_params;
    uwsgi_pass 127.0.0.1:5000;
    uwsgi_param LLTYPE psgi;
    uwsgi_param SCRIPT_FILENAME $document_root$sc;
    uwsgi_param SCRIPT_NAME $sc;
    uwsgi_param  SSL_CLIENT_S_DN_CN $ssl_client_s_dn_cn;
  }
 
  #index index.psgi;
  location / {
    try_files $uri $uri/ =404;
    add_header Strict-Transport-Security max-age=15768000;
  }
}

Configuration of LemonLDAP::NG

In Manager, go in General Parameters > Authentication modules and choose SSL for authentication.

You can then choose any other module for users and password.

Then, go in SSL parameters:

Auto reloading SSL Certificates

A known problematic is that many browser (Firefox, Chrome) remembers the fact that the certificate is not available at a certain time. It is particularly important for smart cards: when the card is not inserted before the browser starts, the user must restart his browser, or at least refresh (F5) the page.

It is possible with AJAX code and 3 Apache locations to bypass this limitation.

1. Modify the portal virtual host to match this example:

    SSLEngine On
    SSLCACertificateFile /etc/apache2/ssl/ca.crt
    SSLCertificateKeyFile /etc/apache2/ssl/lemonldap.key
    SSLCertificateFile /etc/apache2/ssl/lemonldap.crt
 
    SSLVerifyDepth 10
    SSLOptions +StdEnvVars
    SSLUserName SSL_CLIENT_S_DN_CN
 
    # DocumentRoot
    DocumentRoot /var/lib/lemonldap-ng/portal/
    <Directory /var/lib/lemonldap-ng/portal/>
        Order Deny,Allow
        Allow from all
        Options +ExecCGI +FollowSymLinks
        SSLVerifyClient none
    </Directory>
 
    <Location /index>
        Order Deny,Allow
        Allow from all
        SSLVerifyClient none
    </Location>
 
    <Location /testssl>
        Order Deny,Allow
        Allow from all
        SSLVerifyClient require
    </Location>
 
    Alias /sslok /var/lib/lemonldap-ng/portal
    <Location /sslok>
        Order Deny,Allow
        Allow from all
        SSLVerifyClient require
    </Location>

2. Then you need to construct the Ajax page, for example in /index/bouton.html. It looks like this:

<body>
<script src="./jquery-2.1.4.min.js"             type="text/javascript"> </script>
<!--<script src="./jquery-ui-1.8-rass.js"   type="text/javascript">  </script>-->
 
 
<a href="http://www.google.fr" class="enteteBouton" id="continuerButton"><img src=authent.png></a>
<script>
$('.enteteBouton').click( function (e) {
  var b=navigator.userAgent.toLowerCase();
  if(b.indexOf("msie")!==-1){
    document.execCommand("ClearAuthenticationCache")
  }
  e.preventDefault();
  $.ajax({
        url:"https://auth.example.com/testssl",
        beforeSend:function(){},
        type:"GET",
        dataType:"html",
        success:function(c,a){ 
          if (c !== "") {
                alert("Carte OK");
                window.location.href = "https://auth.example.com/sslok/";
          }
          else {
              alert('Carte KO');
          }
        },
        error:function (xhr, ajaxOptions, thrownError){
          if(xhr.status==404) {
                alert("Carte OK");
                window.location.href = "https://auth.example.com/sslok/";
          }
          else {
              alert('Carte KO');
          }
        },
        complete:function(c,a){}
  });
});
</script>
</body>
It is incompatible with authentication combination because of Apache parameter “SSLVerifyClient”, which must have the value “require”. To enable SSL with Combination, use SSL by Ajax

SSL by Ajax

If you enable this feature, you must configure 2 portal virtual hosts:

then declare the second URL in SSL options in the Manager. That's all ! Then you can chain it in a combination.

With choice, the second URL should be also declared in module URL parameter to redirect user to Portal menu.
Content Security Policy may prevent to submit Ajax Request. To avoid security warning,

Go to : General Parameters > Advanced Parameters > Security > Content security policy

and set :

Default value => 'self' “Ajax request URL

Form destinations => 'self' “Ajax request URL

Ajax destinations => 'self' “Ajax request URL