Simple SAML PHP
This page enumerates some configuration methodologies for [Simple SAML PHP] when trying to configure for use as a GFIPM/NIEF Identity Provider.
It is necessary to configure Simple SAML to both filter attributes correctly and to map and define GFIPM/NIEF attributes correctly. Each section below should be reviewed below and your configuration should be updated according to your requirements.
Simple SAML PHP supports filtering attributes sent to Relying Parties based on the attributes they have requested via Trust Fabric / SAML2 Metadata. This is a great feature, but by default this filtering can happen before the attributes have been derived from local attributes. To alter this behavior you need to change the filter priority. Do this by editing config/config.php updating this line within the 'authproc.idp' array:
50 => 'core:AttributeLimit',
to have a much lower priority (higher number):
999 => 'core:AttributeLimit',
Defining/Mapping NIEF Attributes
It is necessary to map existing attributes into NIEF/GFIPM attributes. While this can be done within the main config, it most naturally should be done within the metadata/saml20-idp-hosted.php file. All attributes are generally managed by including them as parts of the authentication processing defined within the 'authproc' array. The detailed documentation on available attribute manipulation can be found within the simplesaml documentation: [https://simplesamlphp.org/docs/stable/simplesamlphp-authproc].
A few specific examples are included below.
// Add GFIPM Static Attributes 40 => array('class' => 'core:AttributeAdd', 'gfipm:2.0:user:IdentityProviderId' => array('NIEF:IDP:your-idp-identifier'), 'gfipm:2.0:user:EmployerName' => array('Test Identity Provider'), 'gfipm:2.0:user:ElectronicAuthenticationAssuranceLevelCode' => array('NISTLEVEL2'), 'gfipm:2.0:user:IdentityProofingAssuranceLevelCode' => array('NISTLEVEL3'), 'gfipm:2.0:user:EmployerStateCode' => array('GA'), 'gfipm:2.0:user:EmployerOrganizationGeneralCategoryCode' => array('State Government')),
// Convert to GFIPM Attribute Names 50 => array('class' => 'core:AttributeMap', 'email' => array('gfipm:2.0:user:EmailAddressText','NIEF:IDP:your-idp-identifier:USER'), 'gfipm28CFR' => 'gfipm:2.0:user:28CFRCertificationIndicator', 'cn' => 'gfipm:2.0:user:GivenName', 'sn' => 'gfipm:2.0:user:SurName', 'gfipmLEO' => 'gfipm:2.0:user:SwornLawEnforcementOfficerIndicator', 'gfipmCriminalHistory' => 'gfipm:2.0:user::NCICCertificationIndicator', 'gfipmORICode' => 'gfipm:2.0:user:EmployerORI', 'telephoneNumber' => 'gfipm:2.0:user:TelephoneNumber' ),
When a converted attributes value does not align with the NIEF definition's acceptable attribute values, you will need to perform a value conversion. This is all handled via regular expressions, but here are a few simple examples:
// Convert TRUE -> true, FALSE -> false 60 => array('class' => 'core:AttributeAlter', 'subject' => 'gfipm:2.0:user:28CFRCertificationIndicator', 'pattern' => '/FALSE/', 'replacement' => 'false'), 61 => array('class' => 'core:AttributeAlter', 'subject' => 'gfipm:2.0:user:28CFRCertificationIndicator', 'pattern' => '/TRUE/', 'replacement' => 'true'),
The NIEF Federation Id is always constructed from the Identity Provider Id and some sort of local user identifier. Simple SAML comes with a module called SmartId that is convenient for constructing a Federation Id. To this you need to include a call to SmartID within the authproc:
//smart id stuff 70 => array( 'class' => 'smartattributes:SmartID' ),
Then the output of SmartID needs to be mapped to the Federation Id with another authproc (note the number on this step must be higher then the Smart ID number):
//Create Federation Id from SmartId 80 => array('class' => 'core:AttributeMap', 'smart_id' => 'gfipm:2.0:user:FederationId',),
Additionally, to do this you will need to enable the SmartId module, and add the FederationId syntax as valid for use. To enable the module create an empty file in the module directory named enable. To add FederationId syntax support to the module edit the file modules/smartattributes/lib/Auth/Process/SmartID.php and include an additional line in the array:
Finally, if you look in the example above you will see there is a step where e-mail address is mapped to an attribute with the same name as seen in the previous step. You will need to mimic that for whatever locally unique identifier you choose to use with your FederationId.
Attribute Name Format
Likely you will need to update the attribute NameFormat from unspecified or text to uri when using NIEF attributes. To do so you specify a value for 'attributes.NameFormat' within the metadata/saml20-idp-hosted.php file. Here is a sample:
'attributes.NameFormat' => 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri',
SAML Metadata / Importing New Entities
There are generally two ways to handle trusted updates. One is to enable automation via remotely hosted trusted SAML2 Metadata. The second is to manually update the configuration. Frequently a single deploy will need to do both, as some trusted partners may not have their metadata available remotely in a trusted fashion.
Typically in this case you will take the SAML2 Metadata provided by a trusted partner and run it through the Metadata to PHP conversion. This tool is available within the admin interface for Simple SAML PHP. Then you will take the output of this program and add it to the metadata/saml20-sp-remote.php.
Automation via Meta Refresh
Simple SAML comes with a meta refresh module that will greatly simplify managing your trusted partners. To enable this module you will need to create an empty file names enable at this location modules/metarefresh/enable. You will need to copy the config-metarefresh.php file from the modules template folder to the main config directory. Below you will find the configuration for how to trust the NIEF Test Federation, only a few minor tweaks are necessary to trust other federations:
<?php $config = array( 'sets' => array( 'gfipm-reffed' => array( 'cron' => array('hourly'), 'sources' => array( array( /* * entityIDs that should be excluded from this src. */ #'blacklist' => array( # 'http://some.other.uni/idp', #), /* * Whitelist: only keep these EntityIDs. */ #'whitelist' => array( # 'http://some.uni/idp', # 'http://some.other.uni/idp', #), #'conditionalGET' => TRUE, 'src' => 'http://ref.gfipm.net/gfipm-signed-ref-metadata.xml', 'certificates' => array( 'ref-gfipm-ca.crt', ), 'template' => array( 'tags' => array('gfipm-reffed'), 'authproc' => array( 99 => array('class' => 'core:AttributeMap', 'oid2name'), ), ), ), ), 'expireAfter' => 60*60*24*4, // Maximum 4 days cache time. 'outputDir' => 'metadata/gfipm-reffed/', /* * Which output format the metadata should be saved as. * Can be 'flatfile' or 'serialize'. 'flatfile' is the default. */ 'outputFormat' => 'flatfile', ), ), );
Additionally you will need to make sure the directory specified in outputDir is writeable by the process running php/web server. This varies by operating system and web server. You will likely also wish to setup an external program to invoke the meta refresh periodically. Review the simple saml php documentation for more information about this: [https://simplesamlphp.org/docs/stable/simplesamlphp-automated_metadata]
Persistent Name Identifiers
Simple SAML PHP requires a 'userid.attribute' to be defined in order to properly generate a persistent name identifier. The best place to define this value is within the metadata/saml20-idp-hosted.php file. You must specify an appropriate local attribute to use. In this example that local attribute is the ldap attribute email, but that may be a different value for your deploy:
// userid.attribute 'userid.attribute' => 'email',
Most likely your Simple SAML PHP install is already defaulting to using SHA-256, but if you need to specifically configure this, you would do so within the metadata/saml20-idp-hosted.php file, by specifying the signature algorithm to be SHA-256 like this:
'signature.algorithm' => 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
If you wish to encrypt assertions to relying parties you do so by turning on the option assertion.encryption within the metadata/saml20-idp-hosted.php file. For example:
// Turn on encryption of assertions... 'assertion.encryption' => TRUE,
Authentication Context Classes
Currently Simple SAML's handling of Authentication Context Classes seems relatively basic. It defaults to sending
urn:oasis:names:tc:SAML:2.0:ac:classes:Password where as within NIEF and most federated use cases the actual Authentication Context Class should be something else. Most commonly it is still username/password but over a secured channel (TLS/SSL) in which case the correct Authentication Context Class Reference is
urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport. To update your configuration to default to Password Protected Transport add the following to 'authproc' array within metadata/saml20-idp-hosted.php:
85 => array ('class' => 'saml:AuthnContextClassRef', 'AuthnContextClassRef' => 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport', ),
Unsolicited SSO (aka IDP Initiated SSO)
You can read about this in section 11 of the Simple SAML PHP basic setup page: [https://simplesamlphp.org/docs/stable/simplesamlphp-idp#section_11].
1. If you are getting strange redirects related to no sessions being established, it could be related to the temporary folder getting so full the system is unable to engage in proper session management.