Configuring Microsoft Azure AD and ZendTo

This aims to be a step-by-step walkthrough showing you how to configure Azure Active Directory and ZendTo, so that Azure AD is used as a Single Sign-On (SSO) Identity Provider (IdP) for ZendTo (the SP).

I assume you are familiar with the Azure Portal and ZendTo.

You must have followed the first 3 overall steps in the main SAML instructions:

  1. Install packages
  2. Configure the Apache web server
  3. Configure ZendTo's preferences.php file to use SAML authentication

Note: throughout this, replace "" with the name of your ZendTo site.

SimpleSAMLphp provides its own mini-website at to let you:

  • find your application entity ID — your IdP will need this
  • find the SP metadata — your IdP will need this
  • test your SAML authentication
  • list what user attributes you can read from the IdP

SimpleSAMLphp Configuration Files

The SimpleSAMLphp configuration files are all 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 ''.
  • '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/urandom | dd bs=32 count=1 2>/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 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. There is only 1 occurrence of 'metadata.sources' that is not in a comment. Find this setting, and set its 'directory' to '/var/zendto/saml-metadata/azure'. This is the directory where the Azure IdP metadata file(s) will be stored.

2. module_cron.php

The only setting used here is the 'key' which should be set to a long random string just the same way as the 'secretsalt' in config.php above.

3. authsources.php

  • 'entityID' — set this to NULL (no quotes!)
  • Around line 50, uncomment the 'NameIDFormat' and 'simplesaml.nameidattribute' settings.
  • 'idp' — we will come back to this setting.

4. Generate Certificate for Signing SAML Requests

It is a very good idea to sign all SAML requests sent by ZendTo (the SP), and to check the signature of all responses from Azure (the IdP). Azure will send us their signing key in a few steps time, but we need to generate the signing key for ZendTo. Run this command:
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

5. Azure Portal & SimpleSAMLphp mini-site

Once you have logged into and selected "Azure Active Directory", you need to add a new Enterprise application:



The "Name" you enter here can be anything, it is purely a displayed name with Azure. The users never see it.

You must first assign some users (or a group of all your users) so that these users will be able to login to ZendTo when these steps are complete. Always add at least yourself!


Back in the application's "Overview" page, we now configure SAML single sign on:



To find the Application Entity ID we need to use the SimpleSAMLphp mini-site at Go there and log in with the password that you have set in config.php as the 'auth.adminpassword':

Go to the "Federation" tab and copy the "Entity ID" which looks like a URL:

Back in the Azure Portal, there are 3 settings that are needed:

Identifier (Entity ID)
This is the Entity ID you just copied from the SimpleSAML mini-site.
Reply URL (Assertion Consumer Service URL)
This must be the following, customised to your site name
Logout Url
This must be the following, customised to your site name

Do not test your setup yet, we haven't finished so it won't work.

If, at any time, you see the following warning box, then click the "Click here" link to fix the problem. This looks to be caused by a minor bug in the Azure Portal, which it flags up itself:

Further down the Azure Portal page, there is the "SAML Signing Certificate" section. The only thing you need here is the "App Federation Metadata Url", from which SimpleSAMLphp will read everything else it needs (including the certificate). Copy it.

6. config-metarefresh.php

Back on your ZendTo server edit config-metarefresh.php.

  • '__ZENDTO:_IDP_SHORT_NAME__' — Set this to 'azure'
  • 'src' — Set this to the App Federation Metadata Url you just copied from Azure
  • 'outputDir' — Set this to '/var/zendto/saml-metadata/azure/'

7. Fetch the IdP metadata

The next job is to test that your ZendTo server can fetch the IdP metadata, and then that it puts it in the right place.

Replacing 'IDP-METADATA-URL' with the App Federation Metadata Url you just copied from Azure, run this command:
/opt/zendto/simplesamlphp/modules/metarefresh/bin/metarefresh.php -s 'IDP-METADATA-URL'
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.

Now to fetch it for real for the first time and check the output is in the right place. Run the command:
If that worked, you should now have at least 1 file in /var/zendto/saml-metadata/azure.

In future, the cron feature in SimpleSAMLphp will automatically re-fetch the IdP metadata every day to ensure it is kept up to date. There is no need to do this manually.

8. authsources.php

We can now get the value for the 'idp' setting.

  1. Look at the metadata file we just fetched, which should be in
    Do not change the file at all!
  2. At the very top of the file, ignoring the comment, there is a line that starts "$metadata".
  3. From this line, copy the entire URL, including any '/' at the end. This is the ID of the IdP.
  4. Edit authsources.php and set the value of 'idp' to this URL.

9. Test Authentication and Find User Attributes

We should now be ready to test your authentication configuration, and if that works we will be shown all the User Attributes needed for the 'samlAttributesMap' in ZendTo's preferences.php.

  1. Open a new "Incognito" or "Private" web browser window — avoiding previous cookies is essential when testing!
  2. Go to the SimpleSAMLphp mini-site at
  3. Login as before with the 'auth.adminpassword' password from config.php
  4. Select the "Authentication" tab
  5. Select "Test configured authentication sources"
  6. Select "default-sp"
  7. You should now be asked (by Microsoft) to login with your email address, so login as you usually would into an SSO application
  8. SimpleSAMLphp's mini-site will then show your all the User Attributes that it has been configured to send you.

  9. The first interesting part is the list of "Your attributes". You use this to construct the 'samlAttributesMap' setting in ZendTo's preferences.php file.
  10. 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.
  11. 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.
  12. 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:
  13. 'mail' — the user's primary email address. It is very often of the form '' but not always. It is okay if the user or IT staff can change this string, such as if the user changes their surname.
  14. 'uid' — the user's address in the form ''. 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.
  15. 'displayName' — the user's real name, displayed in the way that they prefer.
  16. 'organization' — the organization of which the user is a member. If the attributes list on the SimpleSAMLphp page does 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).
  17. 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!
  18. 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 "".

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 "" 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`, "") WHERE `username` NOT LIKE "";
where you should change both occurrences of 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.