IdP controlling access for Alumni

With the introduction of services such as My eQuals there is now a need to allow your university alumni to use federated authentication. Allowing alumni access bring with it a number of challenges and risks that need to discussed. These issues include but may not be limited to the following;

  • The cost of maintaining Alumni credentials
    • Support services, forgotten usernames, password resets, identity verification
    • Licensing costs
    • Infrastructure costs
  • How long should Alumni credentials remain active, 
    • when to deprovision, or active for ever?
    • Alumni deprovisioed at the termination of their studies
  • Controlling access
    • What services should alumni be entitled to access
    • Alumni who are also current staff or students
    • Impact to the organisation's reputation


The value to the organisation of these "Services for Alumni" may require a changes to policies and the technical architecture to support these changes. 


This guide provides advice and configuration options that can be applied to your federation Identity provider that can limit alumni access to a specific set of federation services. The Identity Provider must be the Shibboleth IdP v3.x and assumes that the AAF IdP installer* was used to deploy the IdP.


* Make changes to files in your installer assets area and use the update-idp.sh script to deploy.


Determining who are your Alumni

File: conf/attribute-resolver.xml


The first step is to determine who are your alumni and flag them with an internal attribute that will be used later in the authentication processing. Each university will have its own way of technically distinguishing alumni from the current staff and student population. The method will change or mark the user's LDAP entry which can be identified unambiguously by the identity provider in the attribute resolution. Possible methods include;

  • Adding them to an Alumni group
  • Moving them to an Alumni OU
  • Moving them to an Alumni directory
  • Setting an attribute such as eduPersonAffiliation to 'alum'

The goal is to create an attribute with an id of say "isAlum" that can have the value of either "true" for "false". For examples if Alumni are added to the group "cn=alumni,ou=groups,dc=uni,dc=example,dc=edu" then the following mapped attribute definition could be used to set isAlum to either true of false based on membership of the group.


<AttributeDefinitionid="isAlum" xsi:type="Mapped" sourceAttributeID="memberOf">
    <Dependency ref="memberOf"/>
    <DefaultValue "false"/>
    <ValueMap>
        <ReturnValue>true</ReturnValue>
        <SourceValue partialMatch="true" ignoreCase="true">cn=alumni</SourceValue>
    </ValueMap>
</AttributeDefinition>


Determining who are your Current users

File: conf/attribute-resolver.xml


To make the next step simpler it is advisable to set a similar flag for a user to indicate if they are a current user or not. These are your users that you want to have open access to the federation services, generally your current staff, students and affiliates. 


Note: An alumni may also be a current user.


An example using eduPersonAffiliation to determine is a user is current or not. The attribute isCurrent will be either true or false.


<AttributeDefinitionid="isCurrent" xsi:type="Mapped" sourceAttributeID="eduPersonAffiliation">
    <Dependency ref="eduPersonAffiliation"/>
    <DefaultValue "false"/>
    <ValueMap>
        <ReturnValue>true</ReturnValue>
        <SourceValue>staff</SourceValue>
        <SourceValue>student</SourceValue>
        <SourceValue>affiliate</SourceValue>
        <SourceValue>member</SourceValue>
    </ValueMap>
</AttributeDefinition>


Service Types

File: conf/intercept/context-check-intercept-config.xml


When restricting alumni access services will fall into one or three classifications.


Classification
Description
Alumni Only
The service is only for anyone identified as an alumni including current staff and student who are also alumni. Current staff and student who are not alumni will not be entitled to access these services.
Open
Anyone can access these services.
Members only
Restricted current staff, students, etc. This is the default group for services and do not need to be specified.


To ensure this configuration does not suffer from scaling and maintenance issues only the Alumni Only and Open services need to be listed. You may decide that there is no use case for Alumni only, i.e. you only want to restrict alumni to a particular set of service with no restriction on current users. 


The following bean are added to the configuration. For each service that you want to add a restriction to add its entityId as a value to the appropriate list. In the following example three versions of the My eQuals service are from alumni only, and the AAF Attribute Validator is open to all. 


    <bean id="alumni-only-sps" parent="shibboleth.Conditions.RelyingPartyId">
        <constructor-arg name="candidates">
            <list>
                <value>https://shib-test.digitary.net/shibboleth</value>
                <value>https://www-dsd-uat.digitary.net/shibboleth</value>
                <value>https://www.myequals.net/shibboleth</value>
            </list>
        </constructor-arg>
    </bean>

    <bean id="open-sps" parent="shibboleth.Conditions.RelyingPartyId">
        <constructor-arg name="candidates">
            <list>
                <value>https://validator.test.aaf.edu.au/shibboleth</value>
                <value>https://validator.aaf.edu.au/shibboleth</value>
            </list>
        </constructor-arg>
    </bean>



Mapping the user's state to service classifications

File: conf/intercept/context-check-intercept-config.xml


The following table provides a mapping between the status or affiliation of the user with respect to the university and the types of services they are entitled to access.

 

isAlum
isCurrent
Access restrictions
Description
true
false
Alumni Only + Open
User is an alumni and has no other current affiliation with the university.
true
true
Alumni Only + Open + Members Only
User is both an alumni and has a current affiliation
false
true
Open + Member Only
Use has an current affiliation but is not an alumni
false
false
Open    


This table is converted into the following configuration that replaces the existing shibboleth.context-check.Condition bean. The configuration is long and a little unwieldy but it's only a nested set of OR, ANDs and NOTs, an IF statement in XML. The result is either true of false.


If the result id "true" the user is granted access to the service. If the result is "false", no access and the user will receive message indicating such.


    <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.OR">
        <constructor-arg>
            <list>
                <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.AND">
                    <constructor-arg>
                        <list>
                            <bean parent="alumni-only-sps" />

                            <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate"
                                    p:useUnfilteredAttributes="true">
                                <property name="attributeValueMap">
                                    <map>
                                        <entry key="isAlum">
                                            <list>
                                                <value>true</value>
                                            </list>
                                        </entry>
                                    </map>
                                </property>
                            </bean>
                        </list>
                    </constructor-arg>
                </bean>
                <bean id="shibboleth.context-check.Condition" parent="shibboleth.Conditions.AND">
                    <constructor-arg>
                        <list>
                            <bean id="MyCondition" parent="shibboleth.Conditions.NOT">
                                <constructor-arg>
                                    <bean parent="alumni-only-sps" />
                                </constructor-arg>
                            </bean>
                            <bean class="net.shibboleth.idp.profile.logic.SimpleAttributePredicate"
                                    p:useUnfilteredAttributes="true">
                                <property name="attributeValueMap">
                                    <map>
                                        <entry key="isCurrent">
                                            <list>
                                                <value>true</value>
                                            </list>
                                        </entry>
                                    </map>
                                </property>
                            </bean>
                        </list>
                    </constructor-arg>
                </bean>
                <bean parent="open-sps" />
            </list>
        </constructor-arg>
    </bean>


This configuration provides a condition that can be used as Intercept Flow. In this case we are using it to stop a flow if a user does not qualify for access to a class of service. The flow is actually enabled by specifying it in various profile configuration beans via relying-party.xml


Applying to Relying Parties

File: conf/relying-party.xml


As we need to apply the test to all services that a user may login to the most appropriate place to apply the Intercept Flow is onto the shibboleth.DefaultRelyingParty bean. By default the AAF IdP Installer configures this bean as follows;


    <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
        <property name="profileConfigurations">
            <list>
                <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="attribute-release" />
                <ref bean="SAML1.AttributeQuery" />
                <ref bean="SAML1.ArtifactResolution" />
                <bean parent="SAML2.SSO" p:postAuthenticationFlows="attribute-release" />
                <ref bean="SAML2.ECP" />
                <ref bean="SAML2.Logout" />
                <ref bean="SAML2.AttributeQuery" />
                <ref bean="SAML2.ArtifactResolution" />
                <ref bean="Liberty.SSOS" />
            </list>
        </property>
    </bean>


The intercept flow needs to be added as a post authentication flow that occurs before the user is asked for attribute release consent. There is value is having the user consent to attribute release to then tell them that they are not authorized to access the service. 


Add the intercept flow as follows;


    <bean id="shibboleth.DefaultRelyingParty" parent="RelyingParty">
        <property name="profileConfigurations">
            <list>
                <bean parent="Shibboleth.SSO" p:postAuthenticationFlows="#{{'context-check', 'attribute-release'}}" />
                <ref bean="SAML1.AttributeQuery" />
                <ref bean="SAML1.ArtifactResolution" />
                <bean parent="SAML2.SSO" p:postAuthenticationFlows="#{{'context-check', 'attribute-release'}}" />
                <ref bean="SAML2.ECP" />
                <ref bean="SAML2.Logout" />
                <ref bean="SAML2.AttributeQuery" />
                <ref bean="SAML2.ArtifactResolution" />
                <ref bean="Liberty.SSOS" />
            </list>
        </property>
    </bean>


Deploying and debugging


The configuration is now ready to deploy. Run the update-idp.sh script to have the AAF IdP Installer deploy the changes to your IdP.


Check the logs to verify there where no typos. These will be highlighted in the idp-warn.log file and details will appear in the idp-process.log file. Note that this will only catch errors in attribute-resolver.xml and relying-party.xml files. The remaining config is only loaded when it is needed. The IdP may start correctly and start responding to authentication requests to only fail after users enter their credentials.


We testing and debugging ensure you have access to user accounts that cover the different status / affiliation and verify that user user is allowed or denied access as expected.


Ensure you first test you changes on your Test IdP before moving to Production!


References

This guide is based on the following sections from the Shibboleth documentation wiki;


Getting Support

The AAF support team can assist you if you have questions or issues with this configuration.