<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.nief.org/index.php?action=history&amp;feed=atom&amp;title=Simple_SAML_PHP</id>
	<title>Simple SAML PHP - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.nief.org/index.php?action=history&amp;feed=atom&amp;title=Simple_SAML_PHP"/>
	<link rel="alternate" type="text/html" href="https://wiki.nief.org/index.php?title=Simple_SAML_PHP&amp;action=history"/>
	<updated>2026-04-29T15:12:37Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.38.2</generator>
	<entry>
		<id>https://wiki.nief.org/index.php?title=Simple_SAML_PHP&amp;diff=35&amp;oldid=prev</id>
		<title>Jeff.Krug: Created page with &quot;This page enumerates some configuration methodologies for https://simplesamlphp.org/ Simple SAML PHP when trying to configure for use as a GFIPM/NIEF Identity Provider.  =...&quot;</title>
		<link rel="alternate" type="text/html" href="https://wiki.nief.org/index.php?title=Simple_SAML_PHP&amp;diff=35&amp;oldid=prev"/>
		<updated>2019-01-22T18:15:06Z</updated>

		<summary type="html">&lt;p&gt;Created page with &amp;quot;This page enumerates some configuration methodologies for &lt;a href=&quot;/index.php?title=Https://simplesamlphp.org/_Simple_SAML_PHP&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new&quot; title=&quot;Https://simplesamlphp.org/ Simple SAML PHP (page does not exist)&quot;&gt;https://simplesamlphp.org/ Simple SAML PHP&lt;/a&gt; when trying to configure for use as a GFIPM/NIEF Identity Provider.  =...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;This page enumerates some configuration methodologies for [[https://simplesamlphp.org/ Simple SAML PHP]] when trying to configure for use as a GFIPM/NIEF Identity Provider.&lt;br /&gt;
&lt;br /&gt;
== Attributes ==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Attribute Filters ===&lt;br /&gt;
Simple SAML PHP supports filtering attributes sent to Relying Parties based on the attributes they have requested via Trust Fabric / SAML2 Metadata.  &lt;br /&gt;
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 &lt;br /&gt;
need to change the filter priority.  Do this by editing &amp;#039;&amp;#039;&amp;#039;config/config.php&amp;#039;&amp;#039;&amp;#039; updating this line within the &amp;#039;&amp;#039;&amp;#039;&amp;#039;authproc.idp&amp;#039;&amp;#039;&amp;#039;&amp;#039; array:&lt;br /&gt;
&lt;br /&gt;
        50 =&amp;gt; &amp;#039;core:AttributeLimit&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
to have a much lower priority (higher number):&lt;br /&gt;
&lt;br /&gt;
        999 =&amp;gt; &amp;#039;core:AttributeLimit&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
=== Defining/Mapping NIEF Attributes ===&lt;br /&gt;
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&lt;br /&gt;
within the &amp;#039;&amp;#039;&amp;#039;metadata/saml20-idp-hosted.php&amp;#039;&amp;#039;&amp;#039; file.  All attributes are generally managed by including them as parts of the authentication processing &lt;br /&gt;
defined within the &amp;#039;&amp;#039;&amp;#039;&amp;#039;authproc&amp;#039;&amp;#039;&amp;#039;&amp;#039; array.  The detailed documentation on available attribute manipulation can be found within the simplesaml documentation: [[https://simplesamlphp.org/docs/stable/simplesamlphp-authproc https://simplesamlphp.org/docs/stable/simplesamlphp-authproc]].  &lt;br /&gt;
&lt;br /&gt;
A few specific examples are included below.&lt;br /&gt;
&lt;br /&gt;
==== Static Attributes ====&lt;br /&gt;
               // Add GFIPM Static Attributes&lt;br /&gt;
                40 =&amp;gt; array(&amp;#039;class&amp;#039; =&amp;gt; &amp;#039;core:AttributeAdd&amp;#039;,&lt;br /&gt;
                            &amp;#039;gfipm:2.0:user:IdentityProviderId&amp;#039; =&amp;gt; array(&amp;#039;NIEF:IDP:your-idp-identifier&amp;#039;),&lt;br /&gt;
                            &amp;#039;gfipm:2.0:user:EmployerName&amp;#039; =&amp;gt; array(&amp;#039;Test Identity Provider&amp;#039;),&lt;br /&gt;
                            &amp;#039;gfipm:2.0:user:ElectronicAuthenticationAssuranceLevelCode&amp;#039; =&amp;gt; array(&amp;#039;NISTLEVEL2&amp;#039;),&lt;br /&gt;
                            &amp;#039;gfipm:2.0:user:IdentityProofingAssuranceLevelCode&amp;#039; =&amp;gt; array(&amp;#039;NISTLEVEL3&amp;#039;),&lt;br /&gt;
                            &amp;#039;gfipm:2.0:user:EmployerStateCode&amp;#039; =&amp;gt; array(&amp;#039;GA&amp;#039;),&lt;br /&gt;
                            &amp;#039;gfipm:2.0:user:EmployerOrganizationGeneralCategoryCode&amp;#039; =&amp;gt; array(&amp;#039;State Government&amp;#039;)),&lt;br /&gt;
&lt;br /&gt;
==== Simple Conversion ====&lt;br /&gt;
                // Convert to GFIPM Attribute Names&lt;br /&gt;
                50 =&amp;gt; array(&amp;#039;class&amp;#039; =&amp;gt; &amp;#039;core:AttributeMap&amp;#039;,&lt;br /&gt;
                            &amp;#039;email&amp;#039; =&amp;gt; array(&amp;#039;gfipm:2.0:user:EmailAddressText&amp;#039;,&amp;#039;NIEF:IDP:your-idp-identifier:USER&amp;#039;),&lt;br /&gt;
                            &amp;#039;gfipm28CFR&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user:28CFRCertificationIndicator&amp;#039;,&lt;br /&gt;
                            &amp;#039;cn&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user:GivenName&amp;#039;,&lt;br /&gt;
                            &amp;#039;sn&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user:SurName&amp;#039;,&lt;br /&gt;
                            &amp;#039;gfipmLEO&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user:SwornLawEnforcementOfficerIndicator&amp;#039;,&lt;br /&gt;
                            &amp;#039;gfipmCriminalHistory&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user::NCICCertificationIndicator&amp;#039;,&lt;br /&gt;
                            &amp;#039;gfipmORICode&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user:EmployerORI&amp;#039;,&lt;br /&gt;
                            &amp;#039;telephoneNumber&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user:TelephoneNumber&amp;#039;&lt;br /&gt;
                            ),&lt;br /&gt;
&lt;br /&gt;
==== Value Conversion ====&lt;br /&gt;
When a converted attributes value does not align with the NIEF definition&amp;#039;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:&lt;br /&gt;
&lt;br /&gt;
                // Convert TRUE -&amp;gt; true, FALSE -&amp;gt; false&lt;br /&gt;
                60 =&amp;gt; array(&amp;#039;class&amp;#039; =&amp;gt; &amp;#039;core:AttributeAlter&amp;#039;,&lt;br /&gt;
                           &amp;#039;subject&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user:28CFRCertificationIndicator&amp;#039;,&lt;br /&gt;
                           &amp;#039;pattern&amp;#039; =&amp;gt; &amp;#039;/FALSE/&amp;#039;,&lt;br /&gt;
                           &amp;#039;replacement&amp;#039; =&amp;gt; &amp;#039;false&amp;#039;),&lt;br /&gt;
                61 =&amp;gt; array(&amp;#039;class&amp;#039; =&amp;gt; &amp;#039;core:AttributeAlter&amp;#039;,&lt;br /&gt;
                           &amp;#039;subject&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user:28CFRCertificationIndicator&amp;#039;,&lt;br /&gt;
                           &amp;#039;pattern&amp;#039; =&amp;gt; &amp;#039;/TRUE/&amp;#039;,&lt;br /&gt;
                           &amp;#039;replacement&amp;#039; =&amp;gt; &amp;#039;true&amp;#039;),&lt;br /&gt;
&lt;br /&gt;
==== Federation Id ====&lt;br /&gt;
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:&lt;br /&gt;
&lt;br /&gt;
                //smart id stuff&lt;br /&gt;
                70 =&amp;gt; array(&lt;br /&gt;
                        &amp;#039;class&amp;#039; =&amp;gt; &amp;#039;smartattributes:SmartID&amp;#039;&lt;br /&gt;
                ),&lt;br /&gt;
&lt;br /&gt;
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):&lt;br /&gt;
&lt;br /&gt;
                //Create Federation Id from SmartId&lt;br /&gt;
                80 =&amp;gt; array(&amp;#039;class&amp;#039; =&amp;gt; &amp;#039;core:AttributeMap&amp;#039;,&lt;br /&gt;
                            &amp;#039;smart_id&amp;#039; =&amp;gt; &amp;#039;gfipm:2.0:user:FederationId&amp;#039;,),&lt;br /&gt;
&lt;br /&gt;
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 &amp;#039;&amp;#039;&amp;#039;modules/smartattributes/lib/Auth/Process/SmartID.php&amp;#039;&amp;#039;&amp;#039; and include an additional line in the array:&lt;br /&gt;
&lt;br /&gt;
                &amp;#039;NIEF:IDP:your-idp-identifier:USER&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Attribute Name Format ===&lt;br /&gt;
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 &amp;#039;&amp;#039;&amp;#039;&amp;#039;attributes.NameFormat&amp;#039;&amp;#039;&amp;#039;&amp;#039; within the &amp;#039;&amp;#039;&amp;#039;metadata/saml20-idp-hosted.php&amp;#039;&amp;#039;&amp;#039; file.  Here is a sample:&lt;br /&gt;
&lt;br /&gt;
        &amp;#039;attributes.NameFormat&amp;#039; =&amp;gt; &amp;#039;urn:oasis:names:tc:SAML:2.0:attrname-format:uri&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== SAML Metadata / Importing New Entities ==&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Local Metadata ===&lt;br /&gt;
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 &amp;#039;&amp;#039;&amp;#039;metadata/saml20-sp-remote.php&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
&lt;br /&gt;
=== Automation via Meta Refresh ===&lt;br /&gt;
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 &amp;#039;&amp;#039;&amp;#039;modules/metarefresh/enable&amp;#039;&amp;#039;&amp;#039;.  You will need to copy the &amp;#039;&amp;#039;&amp;#039;config-metarefresh.php&amp;#039;&amp;#039;&amp;#039; 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:&lt;br /&gt;
&lt;br /&gt;
    &amp;lt;?php&lt;br /&gt;
    $config = array(&lt;br /&gt;
       &amp;#039;sets&amp;#039; =&amp;gt; array(&lt;br /&gt;
                &amp;#039;gfipm-reffed&amp;#039;     =&amp;gt; array(&lt;br /&gt;
                        &amp;#039;cron&amp;#039;     =&amp;gt; array(&amp;#039;hourly&amp;#039;),&lt;br /&gt;
                        &amp;#039;sources&amp;#039;  =&amp;gt; array(&lt;br /&gt;
                                array(&lt;br /&gt;
                                        /*&lt;br /&gt;
                                         * entityIDs that should be excluded from this src.&lt;br /&gt;
                                         */&lt;br /&gt;
                                        #&amp;#039;blacklist&amp;#039; =&amp;gt; array(&lt;br /&gt;
                                        #       &amp;#039;http://some.other.uni/idp&amp;#039;,&lt;br /&gt;
                                        #),&lt;br /&gt;
                                        /*&lt;br /&gt;
                                         * Whitelist: only keep these EntityIDs.&lt;br /&gt;
                                         */&lt;br /&gt;
                                        #&amp;#039;whitelist&amp;#039; =&amp;gt; array(&lt;br /&gt;
                                        #       &amp;#039;http://some.uni/idp&amp;#039;,&lt;br /&gt;
                                        #       &amp;#039;http://some.other.uni/idp&amp;#039;,&lt;br /&gt;
                                        #),&lt;br /&gt;
                                        #&amp;#039;conditionalGET&amp;#039; =&amp;gt; TRUE,&lt;br /&gt;
                                        &amp;#039;src&amp;#039; =&amp;gt; &amp;#039;http://ref.gfipm.net/gfipm-signed-ref-metadata.xml&amp;#039;,&lt;br /&gt;
                                        &amp;#039;certificates&amp;#039; =&amp;gt; array(&lt;br /&gt;
                                                &amp;#039;ref-gfipm-ca.crt&amp;#039;,&lt;br /&gt;
                                        ),&lt;br /&gt;
                                        &amp;#039;template&amp;#039; =&amp;gt; array(&lt;br /&gt;
                                                &amp;#039;tags&amp;#039;  =&amp;gt; array(&amp;#039;gfipm-reffed&amp;#039;),&lt;br /&gt;
                                                &amp;#039;authproc&amp;#039; =&amp;gt; array(&lt;br /&gt;
                                                        99 =&amp;gt; array(&amp;#039;class&amp;#039; =&amp;gt; &amp;#039;core:AttributeMap&amp;#039;, &amp;#039;oid2name&amp;#039;),&lt;br /&gt;
                                                ),&lt;br /&gt;
                                        ),&lt;br /&gt;
                                ),&lt;br /&gt;
                        ),&lt;br /&gt;
                        &amp;#039;expireAfter&amp;#039;           =&amp;gt; 60*60*24*4, // Maximum 4 days cache time.&lt;br /&gt;
                        &amp;#039;outputDir&amp;#039;     =&amp;gt; &amp;#039;metadata/gfipm-reffed/&amp;#039;,&lt;br /&gt;
                        /*&lt;br /&gt;
                         * Which output format the metadata should be saved as.&lt;br /&gt;
                         * Can be &amp;#039;flatfile&amp;#039; or &amp;#039;serialize&amp;#039;. &amp;#039;flatfile&amp;#039; is the default.&lt;br /&gt;
                         */&lt;br /&gt;
                        &amp;#039;outputFormat&amp;#039; =&amp;gt; &amp;#039;flatfile&amp;#039;,&lt;br /&gt;
                ),&lt;br /&gt;
        ),&lt;br /&gt;
    );&lt;br /&gt;
&lt;br /&gt;
Additionally you will need to make sure the directory specified in &amp;#039;&amp;#039;&amp;#039;outputDir&amp;#039;&amp;#039;&amp;#039; 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 https://simplesamlphp.org/docs/stable/simplesamlphp-automated_metadata]]&lt;br /&gt;
&lt;br /&gt;
== SAML Features ==&lt;br /&gt;
&lt;br /&gt;
=== Persistent Name Identifiers ===&lt;br /&gt;
&lt;br /&gt;
Simple SAML PHP requires a &amp;#039;&amp;#039;&amp;#039;&amp;#039;userid.attribute&amp;#039;&amp;#039;&amp;#039;&amp;#039; to be defined in order to properly generate a persistent name identifier.  The best place to define this value is within the &amp;#039;&amp;#039;&amp;#039;metadata/saml20-idp-hosted.php&amp;#039;&amp;#039;&amp;#039; file.  You must specify an appropriate local attribute to use.  In this example that local attribute is the ldap attribute &amp;#039;&amp;#039;&amp;#039;email&amp;#039;&amp;#039;&amp;#039;, but that may be a different value for your deploy:&lt;br /&gt;
&lt;br /&gt;
        // userid.attribute&lt;br /&gt;
        &amp;#039;userid.attribute&amp;#039; =&amp;gt; &amp;#039;email&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
=== SHA-256 ===&lt;br /&gt;
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 &amp;#039;&amp;#039;&amp;#039;metadata/saml20-idp-hosted.php&amp;#039;&amp;#039;&amp;#039; file, by specifying the signature algorithm to be SHA-256 like this:&lt;br /&gt;
&lt;br /&gt;
        &amp;#039;signature.algorithm&amp;#039; =&amp;gt; &amp;#039;http://www.w3.org/2001/04/xmldsig-more#rsa-sha256&amp;#039;,&lt;br /&gt;
&lt;br /&gt;
=== Encrypting Assertions ===&lt;br /&gt;
If you wish to encrypt assertions to relying parties you do so by turning on the option &amp;#039;&amp;#039;&amp;#039;assertion.encryption&amp;#039;&amp;#039;&amp;#039; within the &amp;#039;&amp;#039;&amp;#039;metadata/saml20-idp-hosted.php&amp;#039;&amp;#039;&amp;#039; file.  For example:&lt;br /&gt;
&lt;br /&gt;
        // Turn on encryption of assertions...&lt;br /&gt;
        &amp;#039;assertion.encryption&amp;#039; =&amp;gt; TRUE,&lt;br /&gt;
&lt;br /&gt;
=== Authentication Context Classes ===&lt;br /&gt;
Currently Simple SAML&amp;#039;s handling of Authentication Context Classes seems relatively basic.  It defaults to sending &amp;lt;code&amp;gt;urn:oasis:names:tc:SAML:2.0:ac:classes:Password&amp;lt;/code&amp;gt; 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 &amp;lt;code&amp;gt;urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport&amp;lt;/code&amp;gt;.  To update your configuration to default to Password Protected Transport add the following to &amp;#039;&amp;#039;&amp;#039;&amp;#039;authproc&amp;#039;&amp;#039;&amp;#039;&amp;#039; array within &amp;#039;&amp;#039;&amp;#039;metadata/saml20-idp-hosted.php&amp;#039;&amp;#039;&amp;#039;:&lt;br /&gt;
&lt;br /&gt;
                85 =&amp;gt; array (&amp;#039;class&amp;#039; =&amp;gt; &amp;#039;saml:AuthnContextClassRef&amp;#039;,&lt;br /&gt;
                             &amp;#039;AuthnContextClassRef&amp;#039; =&amp;gt; &amp;#039;urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport&amp;#039;,&lt;br /&gt;
                ),&lt;br /&gt;
&lt;br /&gt;
== Unsolicited SSO (aka IDP Initiated SSO) ==&lt;br /&gt;
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 https://simplesamlphp.org/docs/stable/simplesamlphp-idp#section_11]].&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
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.&lt;/div&gt;</summary>
		<author><name>Jeff.Krug</name></author>
	</entry>
</feed>