Home / Blog / SimpleSAMLphp SAML 2.0 SSO Single Sign On: Setting up a local SP & IdP
Angel's picture
Angel Alvarado R.
Soft. and Data engineer.
23 Jan 2017
SimpleSAMLphp
SAML 2.0 SSO Single Sign On: Setting up a local SP & IdP

SAML 2.0 with simplesaml setting up a service provider and an identity provider.

Body: 

What are SAML, SSO and SimpleSAMLphp?

Single Sign On is authentication in one point for N providers. A user will log into a SAML2.0 Identity Provider. In our case the IdP is a SAML module, but it can be a LDAP, RADIUS, Facebook, or Twitter entity. Once the user is authenticated in the IdP, the credentials/session will be valid for any Service Provider (basically any website) that has a valid conection with the IdP. The entire authentication process is done via the exchanging of XML metadata between an IdP and an SP. Also, the IdP and SP exchange cerficates will sign SAML tokens. In this way, the SSO process is supposed to be secure and reliable. As a quick note, the SAML tokens can be encrypted as well. However, we won't cover that in this article.

SAML (Security Assertion Markup Language): SSO protocol that supports XML to exchange data between SPs and IdPs. 

Simplesamlphp: The UNINETT and many contributers have implemented the SAML protocol in PHP. Thanks to them, using this library makes implementing SAML/SSO just a mere setup of 'configurations'. I'll refer to this library as 'SAML' in this article.

Benefits

  • Users only have to remember one username and password instead of N credentials for N websites.
  • Users don't have to relogin everytime they are trying to visit a website (a SP).
  • Users' data is stored only in a unique database (this depends on the implementation).

Installation:

The SAML installation tends to be tedius if you lack knowledge of Apache, Nginx, Linux, etc. This article is only about the configuration of an SP and an IdP, although you can use this release of a Vagrant machine configuration which provides a Drupal 7 and SAML installation. Download it and run it to start following this article right away.  This is the article with the steps to create the Vagrant Machine and here's the github.  

Here are some basic steps to install SAML (jump to the next section if you have already installed it). 

Based on SAML's website, these are the minimum requirements:

  • PHP >= 5.3
  • Memcache to store sessions. You could use sqli, or phpsessions. However, we will use a memcache.
  • A PHP library to connect to Memcache. Although you really only need memcache, I recommend that you install both PHP libraries, memcache and memcached, to avoid confusion.  Normally you install these libraries with pecl /usr/local/bin/pecl install memcache which generates a .so bin that has to be loaded with the php.ini.
  • PHP extensions: date, dom, hash, libxml, openssl, pcre, SPL, zlib, mcrypt

 

Download the library SAML: https://simplesamlphp.org/download. This article assumes you are using the version 1.13.

Once downloaded, place it into /var/simplesaml. Point the URL http://localhost/simplesaml to /var/simplesaml/www

You can do this with Apache using the following: 

  1. <virtualhost>
  2. ServerName service.example.com
  3. DocumentRoot /var/www/service.example.com
  4.  
  5. SetEnv SIMPLESAMLPHP_CONFIG_DIR /var/simplesamlphp/config
  6.  
  7. Alias /simplesaml /var/simplesamlphp/www
  8. </virtualhost>

Or using Nginx:

  1. location /simplesaml {
  2. alias /var/simplesaml/www;
  3. try_files $uri $uri/ /index.php?$query_string;
  4. location ~ \.php(/|$) {
  5. fastcgi_split_path_info ^(.+?\.php)(/.+)$;
  6. fastcgi_param PATH_INFO $fastcgi_path_info;
  7. fastcgi_pass unix:/var/run/php5-fpm.sock;
  8. fastcgi_index index.php;
  9. include fastcgi_params;
  10. }
  11. }

Service Provider: 

As of 2015, the IdP Feide OpenIdP no longer lets users test SAML's Service Providers against it. We will create a local SP and IdP to overcome this.  

Configuring a SP in config/authsources.php

  1. <!--?php
  2.  
  3. $config = array(
  4.  
  5. // This is a authentication source which handles admin authentication.
  6. 'admin' =--> $config = array(
  7.   'admin' => array(
  8. // SAML will use this authentication source to do its own authentication.
  9.   // The module used for this is core:AdminPassword, but it can be replaced with
  10. // any authentication source.
  11. 'core:AdminPassword',
  12. ),
  13.  
  14. 'openidp' => array( //we will named our SP 'openidp'
  15. 'saml:SP', //we want to use SAML for this SP
  16. 'entityID' => 'http://192.168.33.99/simplesaml/idp', //this is the ID for this SP, later on it will be used in the IdP
  17. 'privatekey' => 'saml.pem', //stored in simplesaml/cert
  18. 'certificate' => 'saml.crt', //stored in simplesaml/cert
  19. ),
  20.  
  21. );

Generating a certificate: 

We need a certificate to sign assertions (on SLI and SLO).

In your SAML installation create a folder.

  1. $ cd simplesamlphp & mkdir cert & cd cert

And create a certificate.

  1. openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out saml.crt -keyout saml.pem -subj "/C=US/ST=Denial/L=Oakland/O=Dis/CN=192.168.33.99" //using -subj to automatizate this process later on

Telling our SP about the IdP

Add the IdP's metadata  into the file metadata/saml20-idp-remote.php. If you are using the Vagrant box simplesamlphp, it can be found in 

  1. http://192.168.33.99/simplesaml/saml2/idp/metadata.php.

This part is a little tricky because you have to first configure the IdP and get its metadata. The instructions to configure a local IdP are below.

Note: If you are setting up an external IdP and have the XML data, then convert it into an array using the SAML's converter in

  1. http://192.168.33.99/simplesaml/admin/metadata-converter.php

Add the array to metadata/saml20-idp-remote.php 

  1. $metadata['http://192.168.33.99/simplesaml/saml2/idp/metadata.php'] = array (
  2. 'metadata-set' => 'saml20-idp-remote',
  3. 'entityid' => 'http://192.168.33.99/simplesaml/saml2/idp/metadata.php',
  4. 'SingleSignOnService' =>
  5. 0 =>
  6. 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
  7. 'Location' => 'http://192.168.33.99/simplesaml/saml2/idp/SSOService.php',
  8. ),
  9. ),
  10. 'SingleLogoutService' =>
  11. 0 =>
  12. 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
  13. 'Location' => 'http://192.168.33.99/simplesaml/saml2/idp/SingleLogoutService.php',
  14. ),
  15. ),
  16. 'certData' => 'MIIDhTCCAm2gAwIBAgIJAJWSkrMdkaKeMA0GCSqGSIb3DQEBC...',
  17. 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
  18. );

Identity Provider: 

Enabling SAML as IdP

SAML2.0 has to be enabled in config/config.php

  1. 'enable.saml20-idp' => true,

Enabling and configuring an authentication source

You will retrieve  'identities' from the IdP - therefore the IdP has to request users's data (i.e. username, password, firstname, lastname) from somewhere. Here's where LDAP, RADIUS, a SQL database, Facebook, Twitter etc. comes into play to provide these entities/identities. In our case, we will use a built-in authentication method that the library provides. As a quick note: users' data in SAML are called attributes and claims in Windows Server. 

Enabling example UserPass module

$ cd simplesamlphp & touch modules/exampleauth/enable
 

Configuring authentication source

This has to be configured in config/authsources.php

  1. <!--? php
  2.  
  3. $config = array(
  4. 'molanco-idp' =--> array(
  5. 'exampleauth:UserPass',
  6. 'student:studentpass' => array(
  7. 'uid' => array('student'),
  8. 'eduPersonAffiliation' => array('member', 'student'),
  9. ),
  10. 'employee:employeepass' => array(
  11. 'uid' => array('employee'),
  12. 'eduPersonAffiliation' => array('member', 'employee'),
  13. ),
  14. ),
  15. );

At this point the file config/authsources.php should look like this:

  1. $config = array(
  2.  
  3. 'admin' =--> array(
  4. // SAML will use this authentication source to do its own authentication.
  5. // The module used for this is core:AdminPassword, but it can be replaced with
  6. // any authentication source.
  7. 'core:AdminPassword',
  8. ),
  9.  
  10. 'openidp' => array( //we will named our SP 'openidp'
  11. 'saml:SP', //we want to use SAML for this SP
  12. 'entityID' => 'http://192.168.33.99/simplesaml/idp', //this is the ID for this SP, later on it will be used in the IdP
  13. 'privatekey' => 'saml.pem', //stored in simplesaml/cert
  14. 'certificate' => 'saml.crt', //stored in simplesaml/cert
  15. ),
  16.  
  17. 'molanco-authentication' => array(
  18. 'exampleauth:UserPass',
  19. 'admin1:admin1' => array(
  20. 'email' => array('admin1@molanco.com'),
  21. 'roles' => array('2', '3'),
  22. ),
  23. 'admin2:admin2' => array(
  24. 'email' => array('admin2@molanco.com'),
  25. 'roles' => array('2', '4'),
  26. ),
  27. ),
  28.  
  29. );

Creating a certificate for the IdP

  1. $ cd simplesamlphp & cd cert
  2. $ openssl req -newkey rsa:2048 -new -x509 -days 3652 -nodes -out idp.crt -keyout idp.pem -subj "/C=US/ST=Denial/L=OaklandIdP/O=Dis/CN=192.168.33.99"

Configuring the local IdP

The IdP is configured in metadata/saml20-idp-hosted.php

  1. $metadata['__DYNAMIC:1__'] = array(
  2. /*
  3.   * '__DEFAULT__' to use the IP (192.168.33.99) of the host by default
  4.   */
  5. 'host' => '__DEFAULT__',
  6.  
  7. /* Stored into the folder cer */
  8. 'privatekey' => 'idp.pem',
  9. 'certificate' => 'idp.crt',
  10.  
  11. /*
  12.   * In authsources.php we created this authenticated source
  13.   */
  14. 'auth' => 'molanco-authentication',
  15. );

Adding the SP to our local IdP 

You have to tell the IdP what SPs will be comunicating with it. Again, this step is a little bit tricky because in order to get the SP's metadata, first you need to tell the SP about our IdP (adding the IdP's metadata to the SP). At this point you can get the IdP's metadata from simplesaml/module.php/core/frontpage_federation.php. If you haven't done so already,  go back to "Telling our IdP about the SP".  If you have the SP's metadata then add it to metadata/saml20-sp-remote.php.

  1. $metadata['http://192.168.33.99/simplesaml/idp'] = array (
  2. 'SingleLogoutService' =>
  3. 0 =>
  4. 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect',
  5. 'Location' => 'http://192.168.33.99/simplesaml/module.php/saml/sp/saml2-logout.php/openidp',
  6. ),
  7. ),
  8. 'AssertionConsumerService' =>
  9. 0 =>
  10. 'index' => 0,
  11. 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST',
  12. 'Location' => 'http://192.168.33.99/simplesaml/module.php/saml/sp/saml2-acs.php/openidp',
  13. ),
  14. 1 =>
  15. 'index' => 1,
  16. 'Binding' => 'urn:oasis:names:tc:SAML:1.0:profiles:browser-post',
  17. 'Location' => 'http://192.168.33.99/simplesaml/module.php/saml/sp/saml1-acs.php/openidp',
  18. ),
  19. 2 =>
  20. 'index' => 2,
  21. 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact',
  22. 'Location' => 'http://192.168.33.99/simplesaml/module.php/saml/sp/saml2-acs.php/openidp',
  23. ),
  24. 3 =>
  25. 'index' => 3,
  26. 'Binding' => 'urn:oasis:names:tc:SAML:1.0:profiles:artifact-01',
  27. 'Location' => 'http://192.168.33.99/simplesaml/module.php/saml/sp/saml1-acs.php/openidp/artifact',
  28. ),
  29. ),
  30. 'certData' => 'MIIDfzCCAmegAwIBAgIJAKGGusSHcFnHMA0GCS...',
  31. );

That's it!

If you have followed all the instructions visit 

  1. http://192.168.33.99/simplesaml/module.php/core/authenticate.php.

You'll see our authentication source (molanco-authentication) and our SP(openidp) which will be authenticated against the molanco-authentication source (IdP). Note: You could use another Server/SAML installation to have the SPs and IdPs in their own environment. For testing purposes, having the SP and IdP is enough.

Click on the SP openidp and select one of the IdPs added to this SAML installation. In our case it will appear as the only one we have added into metadata/saml20-idp-remote.php.  For each IdP you add you will be adding one more option into the selectlist below. 

Note: When working with enterprise clients, sometimes you don't really want to let them know that you are working with each other (each one of them will appear in the above list). The idea behind the Drupal module multiple_idp_simplesamlphp is that you want to:

  • Provide customers a seamless deeplinking integration.
  • Provide SLO.
  • Use OOP practices.
  • Use a different uniqueid per customer. Customers may want to use an employeeId, a random number, an SSN, etc.
  • Use different attributes from different customers.
  • Not use a proxy to prevent the above selectlist from appearing to redirect users to their IdP. OpenContext is an example of a third party proxy. Here's a use case
  • Improve the UX for customers. If a customer wants to authenticate with your website they don't have to select their own company from a selectlist which is not Adhoc.
  • Use Drupal 7.

Use admin1:admin1 or admin2:admin2 as Username:Password. Here is when the module UserPass kicks in.

You'll see two amazing attributes

Really, that's it! You are ready to test and play with SSO.

Updating Vagrant box configuration

Based on the above configurations, you can enjoy a new git release (in case you were following the Vagrant box article). Download it and run it!

  1. $ vagrant up

Simplesamlphp_auth & multiple_idp_simplesamlphp

Based on the Drupal module instructions, at this point we have done the following steps:

Installation Overview

  1. Install SimpleSAMLphp
  2. Configure SimpleSAMLphp as a Service Provider
  3. Install Drupal (if you haven't already)
  4. Install simplesamlphp_auth module
  5. Configure simplesamlphp_auth module
  6. Activate the simplesamlphp_auth module

Missing: Configure SimpleSAMLphp as an Identity Provider

 

TO DOs

  • Add configuration to the Vagrant box and create a new release
  • Generate certificates in the Vagrant configuration and generate metadata dynamically
  • Connect SAML (simpleSAMLphp) with Drupal 7, simplesaml_php and multiple_idp_simplesamlphp
  • Connect SAML (simpleSAMLphp) with Drupal 8 and simplesaml_php