Integrating Drupal with SimpleSAMLphp (SSO) and Microsoft Active Directory - Part 1

I have been researching various ways to allow corporate users (e.g., in MS Active Directory) to access Drupal using the same user credentials, and I have noticed that for the most part, the use of LDAP (lightweight directory access protocol) authentication module in Drupal does the job. There are a lots of information on how to integrate Drupal with various enterprise directories using LDAP. Indeed, it was my first choice for my Drupal installation until my boss delivered a very exciting but yet, challenging news. The central IT department will require subsidiaries to implement the single-sign-on for locally developed applications as well as any local CMS installations. So, I didn't have any choice but to find a way to integrate my Drupal installation with central IT single-sign-on infrastructure.

After reading countless articles, forum posts and blogs, I have decided to use SimpleSAMLphp, which is the first part of this post. There is a well-known Drupal module called simplesamlphp_auth that works pretty well with SimpleSAMLphp as SP (Service Provider). In addition, I can also configure the same installation of SimpleSAMLphp to act as IdP (Identity Provider) to test with LDAP even before talking to the central IT personnel.

Here is the list of things I am going to demonstrate on this post:
  • Install SimpleSAMLphp on Ubuntu
  • Configure SimpleSAMLphp to act as IdP (Identity Provider).
  • Configure LDAP module to retrieve user information from Microsoft Active Directory for IdP 
  • Install simplesamlphp_auth module (Drupal 7).
  • Configure Apache vhost file and configure SimpleSAMLphp to act as SP with Drupal 7
  • Modify simplesamlphp_auth module to use Active Directory security group membership information to automatically map the user to the Drupal role during single-sign-on process. This topic address a specific problem related to how Microsoft Active Directory presents the membership information in LDAP attribute. I will explain it later.

Keep in mind that I am only going to enable saml 2.0 functionality in IdP to show how the SSO works with Drupal 7. If you need to provide different protocols, refer to the SimpleSAMLphp documentation.

Before diving into the installation and configuration of SimpleSAMLphp, let me share my version of "what is IdP (Identity Provider), and what is SP (Service Provider)?"

Assume that you have a web application in DOMAIN A (app.domain_a.com) that generates the authentication session in cookie after a user being logged into the application. And  you have another application in DOMAIN B (app.domain_b.com) that needs to use the same authentication session. Obviously, the issue is that you cannot share the same authentication session because the authentication session (in cookie) is only valid for a specific domain, in this case, DOMAIN A. In order to share the same authentication session with applications in different domains, you need to have a separate entity (Identity Provider) that can validate the user account and then, share the user information with web applications (Service Provider) to allow authenticated users to use the web application functionalities.

In case of Drupal with Active Directory, your Drupal installation with SimpleSAMLphp is the Service Provider, and you can think of the user login page as the front-end of the identity provider. Basically, Drupal's login functionality is now moved to the central location where the authentication page interacts with your company Active Directory (via LDAP) to authenticate corporate users. Simply put, think of this central login page as "Identity Provider". Of course, the Identity Provider (IdP) and Service Provider (SP) must trust each other. You can accomplish this by sharing the configuration data (metadata) between IdP and SP. Although we are going to use SimpleSAMLphp as our test IdP in this example, you can always test with your corporate IdP. Ask your system administrator to provide you with the IdP metadata (usually, in XML format) and at the same time, provide your SP metadata. I will go over these steps later in detail.

Let's install SimpleSAMLphp on Ubuntu. If you need additional information that are not covered by this post, refer to this site: https://simplesamlphp.org/docs/stable/simplesamlphp-install

Installing SimpleSAMLphp on Ubuntu

I am going to assume that you have already installed Drupal 7 with php 5.6. The PHP extensions listed below are required, but by installing and configuring Drupal 7, you have probably already installed these extensions in your system. You can check the status by creating phpinfo.php file (http://php.net/manual/en/function.phpinfo.php).

Required extension: date, dom, hash, libxml, openssl, pcre, SPL, zlib, json

Since the SimpleSAMLphp Service Provider (SP) needs to use something other than PHP session (I will explain this later), I am going to use sqlite3 for session management. The following extensions must be installed to allow sql session management, ldap communication, encryption etc.

Install modules & sqlite3 and then, download the SimpleSAMLphp package from https://simplesamlphp.org/download  and extract it in /var. Rename the folder to simplesamlphp and create a symbolic link called "idp.company.me" (that points to /var/simplesamlphp/www) in /var/www folder

 root@localhost:~# apt-get install php5-ldap php5-mcrypt php5-curl libnss3-tools sqlite3  
 root@localhost:/var# tar xzf simplesamlphp-1.14.17.tar.gz  
 root@localhost:/var# mv simplesamlphp-1.14.17 simplesamlphp
 root@localhost:/var# ln -s /var/simplesamlphp/www /var/www/idp.company.me
 
You should be able to see simplesamlphp site under /var folder. Now, let's configure the apache config file to set up SimpleSAMLphp as an IdP.

Configure SimpleSAMLphp to act as IdP (Identity Provider)

Since we are going to configure the IdP and SP on the same machine, I need to create a separate vhost for IdP with a different named host. For the purpose of the demo, I am going to create two entries in hosts file, one (www.company.me) for Drupal 7 + SP and another for IdP (idp.company.me). Both host entries point to the same IP address (same machine). Note that if you have a DNS server running in your network environment, you can ask your system administrator to create another CNAME entry for your server ip address instead of modifying clients' hosts file.
  1. Edit hosts file on the client machine.
    10.10.10.1     www.company.me
    10.10.10.1     idp.company.me
  2. Go to /etc/apache2/sites-available folder and create a file called "simplesamlphp-idp" and enter the content below:
     <VirtualHost *:80>  
         ServerAdmin admin@company.me  
         ServerName idp.company.me  
         DocumentRoot /var/www/idp.company.me  
         SetEnv SIMPLESAMLPHP_CONFIG_DIR /var/simplesamlphp/config  
         Alias /simplesaml /var/simplesamlphp/www  
         <Directory /var/simplesamlphp/www>  
             <IfModule !mod_authz_core.c>  
                 Order allow,deny  
                 Allow from all  
             </IfModule>  
             <IfModule mod_authz_core.c>  
                 Require all granted  
             </IfModule>  
         </Directory>  
         ErrorLog ${APACHE_LOG_DIR}/error.log  
         # Possible values include: debug, info, notice, warn, error, crit,  
         # alert, emerg.  
         LogLevel warn  
         CustomLog ${APACHE_LOG_DIR}/access.log combined  
     </VirtualHost>  
    
  3. Enable the site and reload or restart apache2 service.
     root@localhost:~# a2ensite simplesamlphp-idp  
     root@localhost:/var# service apache2 restart  
    
  4. Go to /var/simplesamlphp/config and edit config.php file as shown below.
     $config = array(  
       'baseurlpath' => 'simplesaml/',  
       'certdir' => 'cert/',  
       'loggingdir' => 'log/',  
       'datadir' => 'data/',
      
       'auth.adminpassword' => 'myComplexPasswordHere',  
       'admin.protectindexpage' => false,  
       'admin.protectmetadata' => false,  
    
       'secretsalt' => 'mycompanyid',  
    
       'technicalcontact_name' => 'Administrator',  
       'technicalcontact_email' => 'admin@company.me',  
       'timezone' => 'America/Los_Angeles',  
    
       'enable.saml20-idp' => true,  
       'enable.shib13-idp' => false,  
       'enable.adfs-idp' => false,  
       'enable.wsfed-sp' => false,  
       'enable.authmemcookie' => false,  
    
       'store.type'          => 'sql',  
       'store.sql.dsn'         => 'sqlite:/var/sessiondb/session.sq3',  
    

    a.   The baseurlpath indicates the entry point for IdP. For example, you need to access the site via http://idp.company.me/simplesaml.

    b.   You need to modify adminpassword, secretesalt, technical contact and time zone information. Since this example only deals with SAML 2.0, enable saml20-idp by setting its value to true.

    c.   Drupal and SimpleSAMLphp SP (I will discuss this later) will share the same host, and because of this, I need to change store.type from phpsession to sql. Configure sql.dsn to your custom sqlite3 database. In my case, I have created a session.sq3 file in /var/sessiondb folder. Just type sqlite3 session.sq3 and exit the application by issuing .exit command. All necessary schema will be generated by SimpleSAMLphp. Don't forget to grant www-data full access to this file.

  5. Open your browser and go to http://idp.company.me/simplesaml



Configure LDAP module to retrieve user information from Microsoft Active Directory for IdP 

To configure the LDAP to talk to your corporate Active Directory, you need to create an account in Active Directory. This account will be served as a search agent to get attributes of the user account the system is trying to validate. For example, if you use sAMAccountName (or mail) as userid, the system cannot retrieve these attributes before binding to the directory. The system uses this search account to connect to Active Directory and find the user object with a user-provided id, in this case, sAMAccoutName (or mail) and then, retrieve the user' DN to be used (along with provided password) to verify whether the user can bind to the directory or not (LDAP binding authentication).

First, open authsources.php  in /var/simplesamlphp/config folder. Then, create the LDAP entry (array format) as shown below. I believe the configuration settings are self-explanatory. Just don't forget to replace hostname, search.base, search.username and search.password with your values. 
   'AD-viaLDAP' => array(  
     'ldap:LDAP',  
     // The hostname of the LDAP server.  
     'hostname' => 'ad.company.me',  
     // Whether SSL/TLS should be used when contacting the LDAP server.  
     'enable_tls' => FALSE,  
     // Whether debug output from the LDAP library should be enabled.  
     'debug' => FALSE,  
     // The timeout for accessing the LDAP server, in seconds.  
     // The default is 0, which means no timeout.  
     'timeout' => 0,  
     // The port used when accessing the LDAP server.  
     // The default is 389.  
     'port' => 389,  
     // Set whether to follow referrals. AD Controllers may require FALSE to function.  
     'referrals' => TRUE,  
     // Only attributes below are fetched.  
     'attributes' => array('cn','distinguishedName','name','sAMAccountName','mail'),  
     'search.enable' => TRUE,  
     'search.base' => 'ou=users,dc=company,dc=me',  
     'search.attributes' => array('sAMAccountName', 'mail'),  
     'search.username' => 'cn=SearchAccount,ou=users,dc=company,dc=me',  
     'search.password' => 'search-account-password',  
     'priv.read' => FALSE,  
     'priv.username' => NULL,  
     'priv.password' => NULL,  
   ),  

Second, you need to generate a SSL certificate to sign SAML message. Create the key and certificate in /var/simplesamlphp/cert folder.
 # openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out idp.company.me.crt 
-keyout idp.company.me.pem  

After generating the SSL certificate and private key, you need to modify IdP configuration to point to these files. Go to /var/simplesamlphp/metadata folder and edit saml20-idp-hosted.php file as shown below:
 $metadata['__DYNAMIC:1__'] = array(  
     'host' => '__DEFAULT__',  
     // X.509 key and certificate. Relative to the cert directory.  
     'privatekey' => 'idp.company.me.pem',  
     'certificate' => 'idp.company.me.crt',  
     /*  
      * Must be one that is configured in  
      * 'config/authsources.php'.  
      */  
     'auth' => 'AD-viaLDAP',  
 }  

Just be sure that the value for auth key is the one you have previously configured in /var/simpleSAMLphp/config/authsources.php file.

Finally, you are ready to test the LDAP connection. Go to http://idp.company.me/simplesaml site and click on Authentication tab.


You will see the link called "Test configured authentication sources". Click this link. Now, you will see the LDAP configuration you just configured. Click AD-viaLDAP link.

You will be redirected to the authentication page. Enter your Active Directory credentials and click Login. If the configuration is correct, you will be redirected to the page with attributes specified in authsources.php file (cn, distinguishedName, name,sAMAccountName, mail).

I hope you enjoy reading this post. Shortly, I will continue with the last part of "Integrating Drupal with SimpleSAMLphp (SSO) and Microsoft Active Directory", which will cover how to configure Drupal to talk to the Identity Provider you just configured with this part. See you next time.


Comments

Post a Comment

Popular Posts