Using SAML-based Single Sign On

In addition to the other authentication mechanisms provided within ZendTo, you can now also use SAML-based authenticators such as

  • Shibboleth
  • Microsoft Azure AD
  • Yubikeys
  • Windows Live
  • Even Twitter or Facebook
The support for these within ZendTo is implemented with the widely-used SimpleSAMLphp library.

Azure AD: If you are using Microsoft's Azure Active Directory, jump straight to the illustrated step-by-step guide.

Important note: SimpleSAMLphp provides its own mini-website to do things like test your SAML authenticator configuration, get the SP metadata your IdP may require, try authenticating, list what attributes you can read from the authenticator and so on. This site is at https://your-zendto-site.example.com/saml, where you should replace "your-zendto-site.example.com" with the root URL of your ZendTo installation. Refer to the SimpleSAMLphp documentation.

The layout of SimpleSAMLphp within ZendTo is as per their documentation, except:

  • The root dir is /opt/zendto/simplesamlphp
  • The base URL is /saml (by default it is /simplesaml)
  • The automatically-refreshed metadata from the identity provider is stored under /var/zendto/saml-metadata (by default it is in .../simplesamlphp/metadata)
  • The "metarefresh" and "cron" modules have been enabled by placing an empty file named "enable" in each of those 2 module's directories, as per the documentation
Its main configuration directory "config" is still in /opt/zendto/simplesamlphp/config and any SSL certificates still need to go into /opt/zendto/simplesamlphp/cert.

The overall steps you need to go through are:

  1. Install packages.
  2. Configure the Apache web server.
  3. Configure ZendTo's preferences.php file to use SAML authentication.
  4. Configure SimpleSAMLphp's 4 main configuration files for your environment.
    This step also includes generating a certificate for signing your SAML requests, and checking that the IdP is prepared to talk to you.
  5. Use SimpleSAMLphp's own mini website to test your configuration, and find what attributes (name, email, etc.) the IdP will pass back to ZendTo, and exactly what they are called.
  6. Fix your users' ZendTo "address books" to account for the fact they are now logging in as an email address and not just a username.
  7. If you are using ZendTo's "automation" feature to create and pick up drop-offs directly from a script or other code of your own, you need to check 1 last setting.

Note: please read and follow this carefully. Do not skip steps or skim-read sections because you already know how to do it. There are extra commands needed that you might miss!

Glossary for SAML novices:

  • "SP" = "Service Provider". In this case, the SP is your ZendTo installation.
  • "IdP" = "Identity Provider". The authentication provider you are using. Microsft's Azure AD or a Shibboleth server, for example.

Package Installation

Fetch and install the "zendto-saml" package, preferably with apt or yum, depending on your system. Doing it this way should automatically install the dependencies, which are the "memcached" package and the PHP module for it which is called either "php-memcached" or "php-pecl-memcached" depending on your version of Linux. Note that the PHP module "memcache" is different, you need the "memcached" module. Ensure the "memcached" service is enabled (so it will start at boot time) and has started.

On Ubuntu or Debian-based Linux systems:

sudo su -
apt update
apt install php-memcached memcached
apt install zendto-saml

On RedHat or CentOS-based Linux systems:

su -
# If this yum command complains about dependency problems,
# use this one instead:
# yum --enablerepo=ius-testing install zendto-saml
yum install zendto-saml
setsebool -P httpd_can_network_memcache 1
systemctl enable memcached
systemctl restart memcached
systemctl restart httpd

Apache Configuration

You need to add 1 "Alias" to the Apache web server configuration. The file you need to edit is

  • Debian-based — /etc/apache2/sites-available/001-zendto-ssl.conf
  • CentOS-based — /etc/httpd/conf.d/zendto-ssl.conf
Just after the "<VirtualHost..." line, add these 4 lines:
  Alias /saml /opt/zendto/simplesamlphp/www
  <Directory /opt/zendto/simplesamlphp/www/>
    Require all granted
  </Directory>
Save the file and restart Apache:
  • Debian-based — systemctl restart apache2
  • CentOS-based — systemctl restart httpd

ZendTo Configuration Files for SAML Authentication

In ZendTo, you will need to edit preferences.php; search for "SAML" in there and you will find the SAML-related settings. You will need to set
'authenticator' => 'SAML',
The only other change you will need to make is to set the 'samlAttributesMap' correctly. More about that later.

You will also need a directory /var/zendto/saml-metadata. This needs to be globally readable, and writeable by the web server. If you are using the rpm or deb (or yum or apt) packages, this directory should have been created automatically.

SimpleSAMLphp Configuration for SAML Authentication

Azure AD users: From here on follow these step-by-step illustrated instructions.

The other configuration changes needed are all to files in /opt/zendto/simplesamlphp/config. These files are:

  1. config.php — Config for the whole of SimpleSAMLphp
  2. config-metrefresh.php — Says how to automatically fetch the IdP's metadata
  3. module_cron.php — Says how to call the "metarefresh" module to automatically update your copy of the IdP's metadata
  4. authsources.php — Describes the IdP you are using
In each of these files,
  • All changes from the SimpleSAMLphp default values are commented with "ZendTo:".
  • All settings you must change are clearly labelled. The labels all start with "__ZENDTO".

1. config.php

  • 'technicalcontact_email' — set this to your organization's technical support email address, such as 'support@your-company.com'.
  • 'secretsalt' — this must be set to a random string. A good command to generate that string is this next line:
    LC_CTYPE=C tr -c -d '[:alnum:]' /dev/null;echo
    Copy and paste that into a bash command-line and it should print 32 random alpha-numeric characters. Set 'secretsalt' to that 32-character string (don't forget to put quotes around it!).
  • 'auth.adminpassword' — this is the SimpleSAML admin password you will need to enter when testing your SAML configuration at https://your-zendto-site.example.com/saml. Again, this needs to be a strong password, so run the command I provided for 'secretsalt' again to generate another random password.
  • 'metadata.sources' — this is a PHP data structure that says how and where to find the metadata from the IdP. It just supplies the directory name, not the complete filename. Use a directory name that is related to the IdP you are using. For example, if using your company's Shibboleth server you could put '/var/zendto/saml-metadata/your-company-shib', or if using Microsoft Azure put '/var/zendto/saml-metadata/azure'.
    Note: Remember the last element of this directory name, you will need it again in a few minutes.

2. config-metarefresh.php

  • The name of the structure within 'sets' — Set this to something short (with no spaces or "awkward" characters) that is relevant to the name of the IdP you are using. For example 'your-company-shib' or 'azure' or similar.
  • 'src' — this is the URL from where SimpleSAMLphp can automatically fetch the federation metadata from the IdP.
  • 'outputDir' — this is the directory where the automatically-updated metadata from the IdP will be stored. The only part you should change is the last element of the path. Use the same name you set in 'metadata.sources' in config.php above. Ensure that here you include a trailing slash '/' on the end of it.
  1. Test the URL for 'src' to check it supplies reasonable data.
    You can ask SimpleSAMLphp to convert it into a PHP data structure. Replacing 'YOUR-URL-HERE' with the "Federation metadata document" you just found, run this command:
    /opt/zendto/simplesamlphp/modules/metarefresh/bin/metarefresh.php -s 'YOUR-URL-HERE'
    It should print out a big PHP data structure with lots of keys, arrows and values. If it prints a load of errors, you have got the wrong URL.
  2. Fetch and store the metadata for the first time.
    Run the command
    /opt/zendto/sbin/refresh_saml_metadata.sh
    If that worked, you should now have at least 1 file in a sub-directory within /var/zendto/saml-metadata.
    If there is no file there, check your SimpleSAMLphp settings again, and be sure that the web server can write to the /var/zendto/saml-metadata directory.

3. module_cron.php

  • 'key' — another long secret string that is used to protect the cron job that automatically fetches updates to the IdP's metadata, so nothing other than SimpleSAMLphp can call it. Again, the same command as desribed above for 'secretsalt' will generate a good one for you.

4. authsources.php

  • 'entityID' — the entity ID of ZendTo that the IdP is expecting, or else NULL so that it creates one automatically.
  • 'idp' — the Entity ID of the IdP that ZendTo should contact. This looks like a URL, but is actually only used as a name. So don't worry if you cannot reach that URL from your ZendTo server, the URL doesn't have to actually work at all. It is just a name that looks like a URL.
    Provided you successfully fetched the IdP's metadata following the instructions above for configuring config-metarefresh.php, you should now have at least 1 file in the IdP's directory under /var/zendto/saml-metadata. You normally want to look in the file saml20-idp-remote.php but if you are using Shibboleth, then it is in the file shib13-idp-remote.php.
    Ignoring comments and blank lines at the very top of the file, the first line should contain a URL. The URL in that line is what you need.
  • 'certificate' and 'privatekey' — most Identity Providers (IdPs) require that all SAML requests are signed. These 2 settings give the filenames for the certificate and its private key, within the directory /opt/zendto/simplesamlphp/cert.
    You can use a self-signed certificate for this. Run this as root, and it will generate the certificate and private key files for you:
    openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out /opt/zendto/simplesamlphp/cert/saml.crt -keyout /opt/zendto/simplesamlphp/cert/saml.pem
    It does not matter much what answers you give to the questions. then set its permissions correctly:
    • Debian-based —
      chgrp -R www-data /opt/zendto/simplesamlphp/cert
      chmod g=r,o-rwx /opt/zendto/simplesamlphp/cert/saml.pem
    • CentOS-based —
      chgrp -R apache /opt/zendto/simplesamlphp/cert
      chmod g=r,o-rwx /opt/zendto/simplesamlphp/cert/saml.pem

Test Your SimpleSAMLphp Configuration

SimpleSAMLphp includes a small website that allows you to test your configuration, find attribute names and a few other things. This website will be at https://your-zendto-site.example.com/saml

  1. Browse there now. You should see a welcome page from SimpleSAMLphp
  2. Click on the "Authenticaion" tab
  3. Click on "Test configured authentication sources"
  4. Click on "default-sp"
  5. If everything is working, you should now be redirected to your organization's "Single Sign-On" page.
    If not, then it's time to start reading particularly the Installation and Configuration sections of the SimpleSAMLphp documentation on their website
  6. Assuming it is working, log in as a member of your organization normally would
  7. After logging in, you should see another page from SimpleSAMLphp called "SAML 2.0 SP Demo Example"
  8. The first interesting part is the list of "Your attributes". You use this to construct the 'samlAttributesMap' setting in ZendTo's preferences.php file.
  9. Each line has the name of an attribute, and its value for the user who just logged in. The attribute names may look a bit like URLs, they may be strings of letters/numbers separated by ':' or '.'. You need to use the entire attribute name, whatever line noise it looks like.
  10. In ZendTo's preferences.php, search for 'samlAttributesMap' and you will see an example. It is an array of 4 settings. Each one tells ZendTo how to convert each of its 4 "nice" ZendTo names ('mail', 'uid', displayName', 'organization') into the name of the appropriate attribute returned by the IdP.
  11. You may have more attributes than you need, and some (hopefully only the 'organization') may not be listed at all. Don't worry, here are some tips:
  12. 'mail' — the user's primary email address. It is very often of the form 'username@your-company.com' but not always. It is okay if the user or IT staff can change this string, such as if the user changes their surname.
  13. 'uid' — the user's address in the form 'username@your-company.com'. This is the address they will use to login to ZendTo. If this string changes for a user, they will lose access to their previous drop-offs in their ZendTo Inbox and Outbox, and they will lose access to all their existing ZendTo address book entries.
  14. 'displayName' — the user's real name, displayed in the way that they prefer.
  15. 'organization' — the organization of which the user is a member. If the attributes list on the "SAML 2.0 SP Demo Example" page do not include the name of the organization, you can just set the value to be the name of the organization (i.e. not the name of a real SAML attribute at all).
  16. Note for later debugging: If in ZendTo you see an attribute name where ZendTo should show the user's value for that attribute, you have got the attribute name wrong as it does not exist for that user. Check for typos!
  17. Test the 'Logout' link in the bottom left corner. Clicking that should show a "you have logged out" page from your IdP. If you then quit your web browser completely, open it again and walk through the login steps above, it should ask for your username and password again.

Updating Users' Address Books

The "address book" feature in ZendTo uses their login username as the key for looking up their list of stored names and addresses, which is presented when they enter a recipient in the "new drop-off" or "request a drop-off" forms. Up until now, your users will have logged in as a simple username (no @ in it). Now using SAML, they will be logged in as an email address in the form "username@your-domain.com".

The effect of this change will be that all your users will suddenly appear to have empty address books; no auto-complete suggestions will be shown.

The solution to this is a single SQL command that will append "@your-domain.com" onto the end of every username in the address book table within ZendTo's database. This SQL command is
UPDATE `addressbook` SET `username` = CONCAT(`username`, "@your-domain.com") WHERE `username` NOT LIKE "%@your-domain.com";
where you should change both occurrences of your-domain.com to be the correct domain name that your users enter when they login via SAML.

Using ZendTo's "automation" Feature?

Check in your preferences.php file for the setting 'automationUsers'. If this has clearly been set for your local environment, then you are probably using this feature so that you can drive ZendTo in an entirely automated way, from scripts and other applications of your own.

If so, then check the preferences.php file for the setting 'samlAutomationAuthenticator'. SAML authentication is not very suitable for scripting or logging in to an application in an automated way. To fix this shortcoming, ZendTo's other authentication mechanisms are still available for any users listed in the 'automationUsers' setting. This 'samlAutomationAuthenticator' setting simply tells ZendTo which authenticator to use in this case. It would most likely be 'Local' or 'AD'.

If you are not using the "automation" feature, there is no reason to change this setting at all.

Tell Me What You Think

If you set up ZendTo using any other interesting SAML-based authentication systems such as, in particular, Yubikeys or other hardware tokens, please do write a few notes on how you did it and what configuration changes you had to make. Then share what you have learned by emailing me, so that I can help make it easier for the next person that wants to use the same system as you.

Please also report all bugs, issues, suggestions and so on.

The mailing list would be the best place, so we can all discuss them, but otherwise you can of course email me too.