Simple SAML PHP

From GFIPM Implementation Wiki
Jump to: navigation, search

This page enumerates some configuration methodologies for [Simple SAML PHP] when trying to configure for use as a GFIPM/NIEF Identity Provider.

Attributes

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.

Attribute Filters

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.

Static Attributes

              // 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')),

Simple Conversion

               // 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'
                           ),

Value Conversion

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'),

Federation Id

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:

               'NIEF:IDP:your-idp-identifier:USER',

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.

Local Metadata

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]

SAML Features

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',

SHA-256

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',

Encrypting Assertions

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].

Troubleshooting

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.