DigiD in Drupal met SimpleSAMLphp

20 juni 2015

DigiD is de identity provider van de Nederlandse overheid. Websites en applicaties kunnen gebruik maken van de DigiD dienst om gebruikers in te laten loggen en hun identiteitsgegevens te ontvangen. Zodra een gebruiker in moet loggen op een website wordt hij naar DigiD doorgestuurd. Hij logt daar in met zijn DigiD account en wordt daarna weer teruggestuurd naar de website.

De website communiceert buiten het zicht van de gebruiker met DigiD en ontvangt de identificatie gegevens van de gebruiker. Over het algemeen is dat het Burger Service Nummer (BSN) van de gebruiker. Hiermee weet de website wie de gebruiker is en kan hij ingelogd worden en voorzien worden van persoonlijke informatie.

Technisch gezien zijn er twee versies van DigiD. De CGI versie communiceert door het opvragen van urls met daarin DigiD specifieke parameters. De SAML versie communiceert via het Security Assertion Markup Language (SAML) protocol. SAML is een op XML gebaseerde standaard voor het uitwisselen van authenticatie- en autorisatiegegevens tussen partijen. Voor Drupal is er een module beschikbaar voor de CGI versie van DigiD. Voor de SAML versie is er ook een module beschikbaar in de Drupal distributie Drupal voor Gemeenten (DVG). Deze module verzorgt de afhandeling van de gebruiker in Drupal en gebruikt de SimpleSAMLphp library voor de communicatie met DigiD. Met alleen deze module en library heb je echter nog geen werkende DigiD SAML implementatie.

Documentatie

Voordat je begint met de implementatie is het handig om het document Koppelvlakspecificatie SAML (PDF | 709 kB) van https://www.logius.nl/ondersteuning/digid/#c8438 grondig door te nemen. Ook de genoemde SAML technical overview is interessant om de voorbeeld berichten te vergelijken met die van DigiD.

Installeer Drupal voor Gemeenten

Download de Drupal voor Gemeenten distributie. De DigiD module staat in \profiles\dvg\modules\features\dvg_digid. De library staat in \profiles\dvg\libraries\simplesamlphp. Plaats de module in je eigen module directory en plaats de library in je eigen libraries directory.

SimpleSAMLphp configureren

Zorg ervoor dat de directory waar simpleSAMLphp in geinstalleerd is in de browser te bereiken is op /simplesaml. Maak hiervoor een simlink in de root van de drupal installatie aan.

ln -s /drupal/sites/all/libraries/simplesamlphp /drupal/simplesaml

Of voeg een alias toe in de httpd.conf van apache.

Alias /simplesaml "/drupal/sites/all/libraries/simplesamlphp"

Pas vervolgens de configuratie van simpleSAMLphp aan in het bestand simplesamlphp\config\config.php. Voeg de volgende code toe aan de config array. Hiermee wordt o.a. de sessie in de database opgeslagen en debugging aangezet.


    // Session.
    'session.duration' => 15 * 60, // 15 minutes
    'session.state.timeout' => 15 * 60, // 15 minutes
    'session.cookie.domain' => 'www.mijndomein.nl', // Must be equal to the Drupal cookie domain.

    // Session storage backend.
    'store.type' => 'sql',
    // See: http://www.php.net/manual/en/ref.pdo-mysql.connection.php
    'store.sql.dsn' => 'mysql:host=dbhost;dbname=databasenaam', 
    'store.sql.username' => '???',
    'store.sql.password' => 'xxx',
    'secretsalt' => 'somethingsecret3089347hsdfjklsdf8u089',
    'store.sql.prefix' => 'simplesaml',

    // Debug and logs.
    'debug' => $debug = TRUE,
    'showerrors' => $debug,
    'logging.level' => ($debug) ? SimpleSAML_Logger::DEBUG : SimpleSAML_Logger::ERR,
    'logging.handler' => 'file',
    'loggingdir' => 'log',

    // SimpleSAML interface.
    'language.available' => array('en', 'nl'),
    'language.default' => 'en',
    'admin.protectindexpage' => TRUE,
    'auth.adminpassword' => 'admin', // This must be changed to be able to log in.
    'technicalcontact_name' => 'Administrator',
    'technicalcontact_email' => 'bogus@example.org',
    'timezone' => 'Europe/Amsterdam',

    // Use a proxy if you have one.    
    'proxy' => 'tcp://outboundproxy.myhoster.com:8080',

Zet de waarde van de instelling enable.saml20-idp op true.

    'enable.saml20-idp' => true,

Vervolgens moeten de public en private keys van de server beschikbaar gemaakt worden voor simpleSAMLphp. Deze keys zijn nodig om de communicatie met DigiD te kunnen verifieren. Het genereren van deze key bestanden is vaak een taak van de hosting provider. Plaats de key bestanden in ieder geval buiten de webroot, zodat ze nooit gedownload kunnen worden. Pas in de configuratie de waarde van de instelling 'certdir' aan.

    //The directory with the public and private key files.
    'certdir' => '/example/home/myuser/keys',

Identity providers opgeven

Nu moet er opgegeven worden welke identity providers er gebruikt moeten gaan worden. We gaan er twee opgeven, de pre-productie en de productie versies van DigiD. Dit moet gebeuren in het bestand simplesamlphp\config\authsources.php. Plaatst de volgende code.


	$config = array(
	  /**
	   * DigiD4 IdP (PROD).
	   */
	  'digid4' => array(
	    'saml:SP',
	    // Personal configuration.
	    'entityID'             => www.mijndomein.nl, // Set this to your own entity ID.
	    // General configuration.
	    'privatekey'           => 'digid.key',
	    'certificate'          => 'digid.crt',
	    'AuthnContextClassRef' => 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport',
	    'idp'                  => 'https://was.digid.nl/saml/idp/metadata',
	    'sign.logout'          => TRUE,
	    'sign.authnrequest'    => TRUE,
	    'authproc' => array(
	      20 => array(
	        'class' => 'saml:NameIDAttribute',
	        'format' => '%V',
	      ),
	    ),
	  ),
	
	  /**
	   * DigiD4 IdP (PREPROD).
	   */
	  'digid4_preprod' => array(
	    'saml:SP',
	    // Personal configuration.
	    'entityID'             => 'test.mijndomein.nl', // Set this to your own entity ID.
	    // General configuration.
	    'privatekey'           => 'digid_preprod.key',
	    'certificate'          => 'digid_preprod.crt',
	    'AuthnContextClassRef' => 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport',
	    'idp'                  => 'https://was-preprod1.digid.nl/saml/idp/metadata',
	    'sign.logout'          => TRUE,
	    'sign.authnrequest'    => TRUE,
	    'authproc' => array(
	      20 => array(
	        'class' => 'saml:NameIDAttribute',
	        'format' => '%V',
	      ),
	    ),
	  ),	
	);

De waarde voor 'entityID' mag zelf bepaald worden. Het handigste is om hier het (sub)domein van de website te gebruiken. De waarde 'privatekey' bevat de naam van het private key bestand van de server. 'certificate' bevat de naam van het public key bestand. In de configuratie van simpleSAMLphp is opgegeven in welke directory deze bestanden moeten staan. 'idp' is de url van DigiD.

Endpoints opgeven

Elke identity provider heeft een aantal urls (endpoints) waarmee gecommuniceerd moet worden. Deze urls moeten in het bestand simplesamlphp\metadata\saml20-idp-remote.php opgegeven worden.


/**
 * DigiD4 IdP (PROD).
 */
$metadata['https://was.digid.nl/saml/idp/metadata'] = array(
  'certificate'               => 'digid.crt',
  'name'                      => 'DigiD4',
  'description'               => 'Authenticate against the DigiD 4.x SAML login service.',
  'SingleSignOnService'       => 'https://digid.nl/saml/idp/request_authentication',
'SingleLogOutService' => 'https://digid.nl/saml/idp/request_logout', 'ArtifactResolutionService' => array( array( 'Location' => 'https://was.digid.nl/saml/idp/resolve_artifact', 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP', 'index' => 0, ), ), ); /** * DigiD4 IdP (PREPROD). */ $metadata['https://was-preprod1.digid.nl/saml/idp/metadata'] = array( 'certificate' => 'digid_preprod.crt', 'name' => 'DigiD4 PREPROD', 'description' => 'Authenticate against the DigiD 4.x SAML PREPROD login service.', 'SingleSignOnService' => 'https://preprod1.digid.nl/saml/idp/request_authentication', 'SingleLogoutService' => 'https://preprod1.digid.nl/saml/idp/request_logout', 'ArtifactResolutionService' => array( array( 'Location' => 'https://was-preprod1.digid.nl/saml/idp/resolve_artifact', 'Binding' => 'urn:oasis:names:tc:SAML:2.0:bindings:SOAP', 'index' => 0, ), ), );

 Je ziet dus dat er drie endpoints opgegeven zijn. Een endpoint waar de gebruiker inlogd (request_authentication), een endpoint waar de gegevens van de ingelogde gebruiker opgevraagd worden (resolve_artifact) en een endpoint waarmee de gebruiker uit kan loggen (request_logout).

Metadata XML genereren

De identity provider heeft een aantal technische gegevens nodig. Deze gegevens moeten aangeleverd worden in een SAML metadata xml bestand. SimpleSAMLphp kan deze genereren. Ga naar /simplesaml op het domein van de website. Log in met het wachtwoord wat in de configuratie is opgegeven. Klik op het tabblad 'Federatie'. Klik op 'Toon metadata' voor de betreffende identity provider. SimpleSAMLphp zal de XML met daarin alle metadata genereren. Stuur deze XML mee met de aanvraag voor Digid bij Logius.

SimpleSAMLPHP patchen

Voor de correcte werking van DigiD moet er een kleine aanpassing doorgevoerd worden. Er moet een extra waarde in de communicatie met DigiD meegegeven worden. Het gaat over het Comparison="minimum" attribuut zoals dat op pagina 30 van het koppelvlak specificaties document staat. Dit is het patch bestand wat doorgevoerd moet worden.


diff --git a/sites/all/libraries/simplesamlphp/modules/saml/lib/Message.php b/sites/all/libraries/simplesamlphp/modules/saml/lib/Message.php
index 83bbd6c..5fbb38e 100644
--- a/sites/all/libraries/simplesamlphp/modules/saml/lib/Message.php
+++ b/sites/all/libraries/simplesamlphp/modules/saml/lib/Message.php
@@ -429,7 +429,7 @@ class sspmod_saml_Message {
 
 		if ($spMetadata->hasValue('AuthnContextClassRef')) {
 			$accr = $spMetadata->getArrayizeString('AuthnContextClassRef');
-			$ar->setRequestedAuthnContext(array('AuthnContextClassRef' => $accr));
+			$ar->setRequestedAuthnContext(array('AuthnContextClassRef' => $accr, 'Comparison' => 'minimum'));
 		}
 
 		self::addRedirectSign($spMetadata, $idpMetadata, $ar);

Testen met simpleSAMLphp

Op het tabblad 'Authentication' van simpleSAMLphp kan nu de digid verbinding getest worden. SimpleSAMLphp houdt logging bij. De logging directory is in de configuratie opgeven en is standaard de log directory. Hier kun je alle acties terug vinden.

Testen met Drupal

De url om DigiD in Drupal aan te roepen is /user/digid. Je kunt Drupal's destination parameter gebruiken om na het inloggen bij DigiD op een specifieke Drupal pagina terug te komen. De inlogurl wordt dan bijvoorbeeld /user/digid?destination=inschrijven. De gebruiker zal dan eerst naar DigiD gaan en daar inloggen. Bij terugkomst op de Drupal site wordt de gebruiker dan naar de inschrijven pagina gestuurd.

Logius checklist

Logius heeft een checklist die ze doorlopen nadat de DigiD koppeling is gerealiseerd. Een van de testitems is dat een gebruiker automatisch na een bepaalde periode geen activiteit uitgelogd wordt. Het automatisch uitloggen wordt geregeld met de autologout module die in de dvg_digid module is geconfigureerd.

Een ander testitem is de foutmelding die getoond wordt op het moment dat er een fout is opgetreden in de DigiD communicatie. Standaard wordt er alleen een Engelse tekst getoond omdat de Nederlandse vertaling niet in de module is opgenomen. Er moet dus nog een Nederlandse vertaling toegevoegd worden om niet op dit testitem afgekeurd te worden. Dit zijn de Engelse en Nederlandse meldingen:


"Error communicating with DigiD. Please try again later. If this error persists, please check the DigiD website for more information."

"Er is een fout opgetreden in de communicatie met DigiD. Probeert u het later nogmaals. Indien deze fout blijft aanhouden, kijk dan op de website van DigiD voor de laatste informatie."