Using SimpleSAMLphp with Drupal 10
- 10 minute read
-
Co-authored by Brandon Goodwin and Sidhartha Sharma
Installing Simplesamlphp_auth
-
To install the SimpleSAMLphp authentication module, run the following command:
composer require drupal/simplesamlphp_auth
-
Enable the SimpleSAMLphp Authentication module and add the External Authentication module as a dependency.
Creating the Symlink
Create a symbolic link in the docroot to access SimpleSAMLphp from the web:
ln -s ../vendor/simplesamlphp/simplesamlphp/public docroot/simplesaml
Setting up Configuration Directories
-
In your project root, create a directory simplesamlphp_files.
mkdir -p simplesamlphp_files/config simplesamlphp_files/metadata
-
Copy the configuration template files from the vendor/simplesamlphp/simplesamlphp directory:
- In Config:
cp config.php.dist ../../../../simplesamlphp_files/config/config.php cp authsources.php.dist ../../../../simplesamlphp_files/config/authsources.php
- In Metadata:
cp saml20-idp-remote.php.dist ../../../../simplesamlphp_files/metadata/saml20-idp-remote.php
- In Config:
Configuring Environment Variables
Alternatively, you can use an environment variable to dictate where your configuration lives for simplesaml. For Cloud IDE, follow these steps: https://docs.acquia.com/acquia-cloud-platform/add-ons/ide/faq#section-how-can-i-set-a-custom-environment-variable-to-use-with-my-application
- SIMPLESAMLPHP_CONFIG_DIR: /var/www/html/simplesamlphp_files/config
- Acquia Cloud Next Env:
acli api:environments:variable-create <app>.<env> "SIMPLESAMLPHP_CONFIG_DIR" "/var/www/html/simplesamlphp_files/config"
- Acquia Cloud Classic Env:
acli api:environments:variable-create <app>.<env> "SIMPLESAMLPHP_CONFIG_DIR" "/var/www/html/<app>.<env>/simplesamlphp_files/config"
- Acquia Cloud IDE:
echo 'SetEnv SIMPLESAMLPHP_CONFIG_DIR "/home/ide/project/simplesamlphp_files/config"' > ~/configs/apache2/envvars.conf && acli ide:service-restart apache
Modifying Config.php
-
In your config directory create a file named acquia_config.php.This file will be used to override some of the settings in config.php, and provide modifications that are unique to your Acquia environment
- Including acquia_config.php with your config.php
- To append it to your config manually:
cat << EOF >> simplesamlphp_files/config/config.php #Include Acquia specific functions and settings include_once("acquia_config.php"); EOF
- Or add this snippet to the bottom of your config.php:
if (file_exists('/var/www/site-php')) { require_once("/var/www/html/" . $_ENV['AH_SITE_NAME'] . "/simplesamlphp_files/config/acquia_config.php"); }
- To append it to your config manually:
Updating .htaccess
In your .htaccess, add the following snippet to prevent a permission denied error on the simplesaml path:
# Allow access to simplesaml paths
RewriteCond %{REQUEST_URI} !^/simplesaml
- Ensure that you add it after the following line:
RewriteCond %{REQUEST_URI} !/core/modules/statistics/statistics.php$
- Ensure that you add it before the following line:
RewriteRule "^(.+/.*|autoload)\.php($|/)" - [F]
Configuring acquia_config.php
- In your newly created acquia_config.php, insert the following:
<?php /** * @file * SimpleSAMLPhp Acquia Configuration. * * Example Acquia settings for SimpleSAMLphp. Version 20241106.1 * You MUST edit this file! * Edit all sections with "EDIT THIS". * See full instructions at https://dev.acquia.com/blog/using-simplesamlphp-drupal-10 */ use SimpleSAML\Logger; if (!isset($config)) { $config = []; } /** * Perform any global overrides. * EDIT THIS SECTION. */ $config['technicalcontact_name'] = "Your Name"; $config['technicalcontact_email'] = "[email protected]"; $config['secretsalt'] = "EDITME"; $config['auth.adminpassword'] = "EDITME"; $config['certdir'] = "/var/www/html/{$_ENV['AH_SITE_GROUP']}.{$_ENV['AH_SITE_ENVIRONMENT']}/simplesamlphp_files/cert/"; $config['metadatadir'] = "/var/www/html/{$_ENV['AH_SITE_GROUP']}.{$_ENV['AH_SITE_ENVIRONMENT']}/simplesamlphp_files/metadata"; /** * Edits should not be needed below this line. */ /* * Perform any Acquia Cloud overrides. */ if (isset($_ENV['AH_SITE_ENVIRONMENT'])) { // do Acquia specific translations here // Prevent Varnish from interfering with SimpleSAMLphp. // SSL terminated at the ELB / balancer so we correctly set the SERVER_PORT // and HTTPS for SimpleSAMLphp baseurl configuration. $protocol = 'http://'; $port = '80'; if (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') { $_SERVER['SERVER_PORT'] = 443; $_SERVER['HTTPS'] = 'true'; $protocol = 'https://'; $port = $_SERVER['SERVER_PORT']; } $config['baseurlpath'] = $protocol . $_SERVER['HTTP_HOST'] . ':' . $port . '/simplesaml/'; $config['trusted.url.domains'] = [$_SERVER['HTTP_HOST']]; // Setup basic file based logging. $config['logging.handler'] = 'file'; $config['loggingdir'] = dirname(getenv('ACQUIA_HOSTING_DRUPAL_LOG')); $config['logging.logfile'] = 'simplesamlphp-' . date('Ymd') . '.log'; // Retrieve database credentials from creds.json $creds_json = file_get_contents('/var/www/site-php/' . $_ENV['AH_SITE_GROUP'] . '.' . $_ENV['AH_SITE_ENVIRONMENT'] . '/creds.json'); $creds = json_decode($creds_json, true); $database = $creds['databases'][$_ENV['AH_SITE_GROUP']]; // For ODE environments, the host comes from the single item in db_url_ha if (substr($_ENV['AH_SITE_ENVIRONMENT'], 0, 3) === 'ode') { $database['host'] = key($database['db_url_ha']); } // For Cloud Classic environments, the current active database host is determined by a DNS lookup if (isset($database['db_cluster_id'])) { require_once "/usr/share/php/Net/DNS2_wrapper.php"; try { $resolver = new Net_DNS2_Resolver([ 'nameservers' => [ '127.0.0.1', 'dns-master', ], ]); $response = $resolver->query("cluster-{$database['db_cluster_id']}.mysql", 'CNAME'); $database['host'] = $response->answer[0]->cname; } catch (Net_DNS2_Exception $e) { Logger::warning('DNS entry for Acquia database not found'); } } $config['store.type'] = 'sql'; $config['store.sql.dsn'] = sprintf('mysql:host=%s;port=%s;dbname=%s', $database['host'], $database['port'], $database['name']); $config['store.sql.username'] = $database['user']; $config['store.sql.password'] = $database['pass']; $config['store.sql.prefix'] = 'simplesaml'; }
Editing acquia_config.php
Within our acquia_config.php edit the following sections
- Technical Contact Name & Email
$config['technicalcontact_name'] = "Test Name"; $config['technicalcontact_email'] = "[email protected]";
- Secret Salt and auth admin password
$config['secretsalt'] = 'AddYourSaltStringHere'; $config['auth.adminpassword'] = 'ChangeThisPlease';
- Generate Secret Salt
LC_ALL=C tr -c -d '0123456789abcdefghijklmnopqrstuvwxyz' </dev/urandom | dd bs=32 count=1 2>/dev/null;echo z50bvp9ipfy3vhtxsvzqy44jgc09zqqo
- Generate auth admin password
vendor/simplesamlphp/simplesamlphp/bin/pwgen.php
Note: Depending on where you are setting this up (Acquia Cloud or Local), you may need to change the tempdir or loggingdir to an existing path.
Configuring authsources.php
- Next, provide information about your service provider (SP) and identity provider (IdP) to SimpleSAMLphp in an authsources.php file, which configures the service provider.
- The values in the authsources.php file control the following settings:
- Entity ID of your SP, which is a unique identifier for your SP. This value defaults to the URL of the service provider’s metadata. You may want to override this value with a more human-readable name.
- Entity ID of your IdP, which is a unique identifier for your IdP. This value must match the entity ID value in the metadata provided to you by your IdP.
- The NameIDFormat, which your IdP includes in its metadata.
- The location of a self-signed SSL certificate, if your IdP requires your service provider to have a self-signed SSL certificate.
- Previously in this tutorial, we created a copy of the authsources template, but we also provide an example file here: https://docs.acquia.com/downloadable-resources?cid=3e60e#section-authsourcesphp
- Replace the entityID to a unique identifier (Your domain name is fine in this case)
- Replace the idp with the metadata url provided by your idp
<?php
// This file is available at
// https://docs.acquia.com/resource/simplesaml/sources/
$config = array(
// This is a authentication source which handles admin authentication.
'admin' => array(
// The default is to use core:AdminPassword, but it can be replaced with
// any authentication source.
'core:AdminPassword',
),
'default-sp' => array(
'saml:SP',
// The entityID is the entityID of the SP that the IdP is expecting.
// This value must be exactly what the IdP is expecting. If the
// entityID is not set, it defaults to the URL of the SP's metadata.
// Don't declare an entityID for Site Factory.
'entityID' => 'https://' . $_SERVER['HTTP_HOST'] . '/simplesaml' . '/',
// If the IdP requires the SP to hold a certificate, the location
// of the self-signed certificate.
// If you need to generate a SHA256 cert, see
// https://gist.github.com/guitarte/5745b94c6883eaddabfea68887ba6ee6
'certificate' => "../cert/saml.crt",
'privatekey' => "../cert/saml.pem",
'redirect.sign' => TRUE,
'redirect.validate' => TRUE,
// The entityID of the IdP.
// This is included in the metadata from the IdP.
'idp' => 'idp entityID goes here',
// NameIDFormat is included in the metadata from the IdP
'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient',
// If the IdP does not pass any attributes, but provides a NameID in
// the authentication response, we can filter and add the value as an
// attribute.
// See https://simplesamlphp.org/docs/stable/saml:nameidattribute
'authproc' => array(
20 => array(
'class' => 'saml:NameIDAttribute',
'format' => '%V',
),
),
// The RelayState parameter needs to be set if SSL is terminated
// upstream. If you see the SAML response come back with
// https://example.com:80/saml_login, you likely need to set this.
// See https://github.com/simplesamlphp/simplesamlphp/issues/420
'RelayState' => 'https://' . $_SERVER['HTTP_HOST'] . '/saml_login',
// If working with ADFS, Microsoft may soon only allow SHA256 certs.
// You must specify signature.algorithm as SHA256.
// Defaults to SHA1 (http://www.w3.org/2000/09/xmldsig#rsa-sha1)
// See https://docs.microsoft.com/en-us/security/trusted-root/program-requirements
// 'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
),
);
Setting up SSL Certificates (If Required)
If your IdP requires an SSL cert for authentication, create a cert directory under the simplesamlphp_files directory and place both the cert and private key in that location:
-
Create the cert directory:
mkdir simplesamlphp_files/cert
- Create Cert and Private Key:
openssl req -newkey rsa:3072 -new -x509 -days 3652 -nodes -out saml.crt -keyout saml.pem
Configuring saml20-idp-remote.php
-
Given the metadata XML file provided by your IDP, navigate to /simplesaml/module.php/admin/federation/metadata-converter.
-
Press parse. It outputs the proper input for saml20-idp-remote file.
Verifying Installation
- Access SimpleSAMLphp Admin Interface: Visit
https://your-domain.com/simplesaml/admin
to access the SimpleSAMLphp admin interface. You must see the SimpleSAMLphp dashboard if everything is configured correctly. - Run SimpleSAMLphp Diagnostics: Use the diagnostic tools within the admin interface to check the configuration, especially the connection between your Service Provider (SP) and Identity Provider (IdP).
Common Issues and Troubleshooting
- Symlink Issues: Ensure the symlinks are correctly created and point to the correct directories. If SimpleSAMLphp is not accessible, check the symlink paths.
- Permission Errors: If you encounter permission denied errors, verify the file and directory permissions for
simplesamlphp_files
and its contents. All files should be readable by the web server. - Configuration Errors: Double-check the
config.php
andauthsources.php
for syntax errors or incorrect paths.
Useful References and Resources
- SimpleSAMLphp Documentation: SimpleSAMLphp Documentation
- Drupal SimpleSAMLphp Module Documentation: Drupal SimpleSAMLphp Module