Shibboleth IdP 2.x is becoming End-Of-Life on July 31st, 2016. This page now exists only as a historical archive - any new IdP deployments should follow the IdP 3.x documentation.
For upgrading, please see the instructions on Upgrading a 2.x IdP to 3.x.
Please note that if your 2.x IdP was configured with ComputeId connector for eduPersonTargetedID (not storing the values in a database), you will need to follow these instructions on configuring the StoredId connector on the 2.x IdP before upgrading to the 3.x IdP.
This page is a guide to installing a Shibboleth 2.x IdP. This page assumes the IdP would be installed on a blank Linux system (typically a virtual machine) and follows from that point on. The same process can be used to bootstrap a generic VM. The IdP will be installed both with the Shibboleth IdP software and the uApprove attribute release approval web application.
This guide is periodically updated as new versions of the software installed become available. This guide is current for IdP 2.3.6 and uApprove 2.4.1, the latest versions available as of May 2012. The guide was initially written with the assumption that CentOS/RHEL 5 would be the OS and Tomcat5 would be the web application server, but has been updated for RHEL6 (no change really needed) and Tomcat6 (minor variations, documented inline).
If you are interested in upgrading an existing IdP to the latest 2.x release, please see Upgrading a Shibboleth 2.x IdP.
But, more importantly, see the instructions on Upgrading a 2.x IdP to 3.x.
If you are interested in linking an existing IdP into Tuakiri, please see Configuring a Shibboleth Identity Provider to join the Tuakiri Federation.
Prerequisites
- A Linux system (VM) preinstalled with base OS distribution, with current updates installed.
- Minimum hardware recommendation: 1GB RAM, 16GB diskspace minimum
- Linux distribution: recommended RHEL 6 or CentOS 6
- Network requirements:
- Allocating a hostname (typically
idp.institution.domain.ac.nz
) and a static IP address. - Setup firewall rules:
- Enable incoming and outgoing TCP connections to ports 80, 443, 8443. Note that these connections MUST be direct connections and cannot go through a proxy. In particular, the port 8443 connections use client SSL authentication and will not work with proxies that try to step in the middle of an SSL connection, even if the server certificate is pre-loaded onto the proxy.
- Enable connections to an external NTP server or provide an internal NTP server.
- Allocating a hostname (typically
- Provide an X509 certificate for the allocated hostname issued by a CA trusted by major browsers.
- (There are no further requirements on the certificate, it would be only accessed from inside a browser)
- Access to an institutional LDAP server (with a system account allowed to read all attributes needed for the federation). This typically includes the following information:
- LDAP server hostname and port number
- Search base (subtree DN)
- Bind DN for a generic reader account
- Bind password for this account
- Search filter - i.e. what attribute contains the user's login name?
Modifications to Identity Management system
Your Identity Management System (IdMS) will very likely have most of the attributes asked for by the federation - or will have enough information to synthesize the specific attribute values on the fly inside the IdP. But for some attributes, the IdMS might not have enough information. The following information should be considered for adding into your IdMS:
eduPersonEntitlement: The eduPersonEntitlement attribute is a storage container for values representing privileges to access resources within the federation. It is a multi-valued string attribute. The values will have the form of a URI - with specific values that are yet to be defined. The attribute definition details are (source: Attribute Recommendation 2.1 (PDF), page 14):
Origin/ObjectClass: eduPerson [eduPerson] OID: 1.3.6.1.4.1.5923.1.1.1.7 SAML attribute name: urn:mace:dir:attribute-def:eduPersonEntitlement LDAP syntax: directoryString [1.3.6.1.4.1.1466.115.121.1.15] Number of values: Multiple Example values: eduPersonEntitlement: urn:mace:washington.edu:confocalMicroscope eduPersonEntitlement: http://publisher.example.com/contract/GL123
This attribute can also be defined as a static attribute. If you would prefer not to modify your IdMS schema and do not have any eduPersonEntitlement values to release, it is OK to initially only define the attribute as static inside the IdP. For more information on this option, please see the notes on configuring eduPersonEntitlement as a static attribute further below in this document.
auEduPersonSharedToken: The auEduPersonSharedToken uniquely identifies users when accessing certain resources - particularly within the computational grid and data grid. The values should be opaque, non-reassignable and persistent - and transferrable when a user moves between institutions. Even though the values are typically created as hash-values on first use, they MUST be stored and each institution must be ready to accept values users already have when coming from another institution. The attribute can be stored in either the IdMS directly (preferred) or in a database. The attribute definition details are (source: Attribute Recommendation 2.1 (PDF), pages 9-10, with OID updated to correct value):
Origin/ObjectClass: auEduPerson OID: 1.3.6.1.4.1.27856.1.2.5 SAML attribute name urn:mace:federation.org.au:attribute:auEduPersonSharedToken LDAP syntax: directoryString [1.3.6.1.4.1.27856.1.2.5] Number of values: Single Example values: ZsiAvfxa0BXULgcz7QXknbGtfxk
See also the auEduPerson LDAP Schema Definition(pages 45-52) for exact LDAP definition snippets.
This auEduPersonSharedToken values can also be stored locally in a MySQL database. If you would prefer not to modify your IdMS schema, you can also choose the local database option - at the cost of not having all of your primary identity information in your IdMS. Please see the instructions on defining the sharedToken attribute further below for more detail.
eduPersonAssurance: This attribute represents the Levels of Assurance. Either add the attribute into the IdMS directly, or start collecting enough information to synthesize the values later in a scripted attribute definition (like done for Affiliation below). The attribute definition details are (source: Attribute Recommendation 2.1 (PDF), page 13):
Origin/ObjectClass: eduPerson OID: 1.3.6.1.4.1.5923.1.1.1.11 SAML attribute name: urn:oid:1.3.6.1.4.1.5923.1.1.1.11 LDAP syntax: directoryString [1.3.6.1.4.1.1466.115.121.1.15] Number of values: multiple Example values: See AAF IdentityLoA Vocabulary
- For an overview of the requirements for individual assurance levels, please refer to the AAF documentation at http://www.aaf.edu.au/technical/levels-of-assurance/
For detailed information on the requirements, please refer to the NIST SP 800-63-1* standard
As the federation is moving to centralized management of Levels-Of-Assurance, it is recommend to at this moment only define the attribute as a static attribute releasing the floor-of-trust values. Please see the notes on configuring eduPersonAssurance as a static attribute further below in this document.
Preliminaries
System firewall configuration
Edit
/etc/sysconfig/iptables
and add rules to permit incoming traffic to ports 80, 443, and 8443; add the following just below the rule for port 22:-A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 80 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 443 -j ACCEPT -A RH-Firewall-1-INPUT -m state --state NEW -m tcp -p tcp --dport 8443 -j ACCEPT
Restart iptables:
service iptables restart
Bootstrapping the VM
We assume a standard install of either CentOS or RHEL, version 5 or 6. The IdP web application can run inside Tomcat either 5 or 6. CentOS/RHEL 5 comes with Tomcat5 (but Tomcat6 can be installed from JPackage), RHEL6 comes with Tomcat6. Further on, we'll be referring to the Tomcat of choice as $TOMCAT_NAME (either tomcat5
or tomcat6
).
Install packages
Apache with mod_ssl, Java (with javac) and Tomcat:
yum install httpd mod_ssl java-1.6.0-openjdk java-1.6.0-openjdk-devel ant $TOMCAT_NAME
- MySQL (needed for storing sharedToken values and uApprove attribute release approvals)
MySQL is not strictly required and an alternative database system may be used if already available on site - just use the corresponding JDBC drivers for the alternative database.
yum install mysql mysql-server
Install NTP (if time synchronization is to be done inside the VM)
yum install ntp
Useful debugging / sysadmin tools
yum install openldap-clients wireshark-gnome mc strace subversion
Local configuration
- Configure NTP: time synchronization is crucial for the Shibboleth IdP to correctly interact with Service Providers in the federation. Please gather beforehand the hostname or IP address of the time server provided within your organisation. Further on, we'll assume it's
ntp.institution.domain.ac.nz
. If your organisation is not providing one, you may use an external source (including the default servers listed in/etc/ntp.conf
) - but make sure your firewall allows the NTP traffic through (outgoing UDP port 123 traffic + reply packets).Do a one-off synchronization:
ntpdate -s ntp.institution.domain.ac.nz
Edit
/etc/ntp.conf
and:- Comment out local server (
server 127.127.1.0
andfudge 127.127.1.0
) - Comment out CentOS servers (all lines starting with
server
) The local time server:
server ntp.institution.domain.ac.nz
- Comment out local server (
Make ntpd start on system startup:
chkconfig ntpd on
Start ntpd now:
service ntpd start
Check ntpd is running and synchronizing: run
ntpdc -p
- Disable SELinux: the Apache LDAP module does not work with SELinux - SELinux would not allow the module to open outgoing TCP connections.
Disable SELinux now:
echo 0 > /selinux/enforce
And for future restarts, edit
/etc/sysconfig/selinux
and change:SELINUX=permissive
Basic Shibboleth IdP and uApprove installation
Rationale and planning
From the very beginning, we will install the Shibboleth IdP:
- as a web application WAR file managed by Tomcat
- with uApprove integrated into the web application
- with a Tomcat login screen used for authentication
Having done these steps early in the installation prevents them from slipping later on.
The installation paths will be (as close to defaults as possible, putting all IdP files under /opt
:
- IDP_HOME -
/opt/shibboleth-idp
(default) - Tomcat home:
/var/lib/$TOMCAT_NAME
(where Tomcat web applications and common files live)
Your IdP hostname will be idp.institution.domain.ac.nz
Your scope, home organization name and security domain will be institution.domain.ac.nz
Your IdP entityId will be https://idp.institution.domain.ac.nz/idp/shibboleth
- The Shibboleth IdP installation directory (from where Shibboleth IdP software is installed) will be
/root/inst/shibboleth-identityprovider-<version>
- and the name of the directory will be stored inSHIB_INST_HOME
(here, we assume version is 2.3.6) - The uApprove installation directory will be
/root/inst/uApprove-<version>
and the name of the directory will be stored inUAPPROVE_INST_HOME
(here, we assume version is 2.4.1)
Configure the corresponding environment variable: create /etc/profile.d/shib.sh with the following content (and make the file executable):
IDP_VERSION="2.3.6" UAPPROVE_VERSION="2.4.1" SHIB_HOME=/opt/shibboleth-idp SHIB_INST_HOME=/root/inst/shibboleth-identityprovider-$IDP_VERSION UAPPROVE_INST_HOME=/root/inst/uApprove-$UAPPROVE_VERSION IDP_HOME=/opt/shibboleth-idp JAVA_HOME=/usr/lib/jvm/java TOMCAT_NAME=tomcat5 # can be tomcat5 or tomcat6 TOMCAT_HOME=/var/lib/$TOMCAT_NAME export SHIB_HOME IDP_HOME JAVA_HOME TOMCAT_HOME SHIB_INST_HOME UAPPROVE_INST_HOME
Basic Shibboleth Installation
- Check for the most recent version of Shibboleth IdP at http://www.shibboleth.net/downloads/identity-provider/
Create an installation directory and download Shibboleth
mkdir /root/inst cd /root/inst wget http://www.shibboleth.net/downloads/identity-provider/${IDP_VERSION}/shibboleth-identityprovider-${IDP_VERSION}-bin.zip unzip shibboleth-identityprovider-${IDP_VERSION}-bin.zip cd $SHIB_INST_HOME
Invoke installer
sh ./install.sh
- When prompted, give the following non-default answers:
- FQDN is the hostname assigned to your IdP, typically idp.institution.domain.ac.nz
Keystore password would be used to create the java keystore containing the back-channel certificates. As the private key will be also stored on disk in an unencrypted X509 key file, there is no need to choose a secure keystore password...
FQDN: idp.institution.domain.ac.nz Keystore: changeit
- When prompted, give the following non-default answers:
Important
When re-running the installer in the future (you'll be asked to do so further on in this guide), you'll be asked whether to overwrite the configuration files.
It is important you answer no to that question - otherwise, all modifications made to the configuration files will be lost.
- This installs the Shibboleth IdP web application into
/opt/shibboleth-idp/war/idp.war
Configure Tomcat and deploy the IdP WAR
Create
/etc/$TOMCAT_NAME/Catalina/localhost/idp.xml
with the following content:<Context docBase="/opt/shibboleth-idp/war/idp.war" privileged="true" antiResourceLocking="false" antiJARLocking="false" unpackWAR="false" swallowOutput="true" />
Endorse XML libraries used by the IdP. This procedure is different for Tomcat6 (where the endorsed directory needs to be created and defined first) and for Tomcat5 (where the directory exists but contains other versions of the XML libraries that need to be deleted first).
- If installing with Tomcat6:
Create
/var/lib/tomcat6/common/endorsed
:mkdir -p /var/lib/tomcat6/common/endorsed
Add the following to
/etc/sysconfig/tomcat6
to make endorsed directories really work:JAVA_ENDORSED_DIRS="/var/lib/tomcat6/common/endorsed"
And copy all jars from
$SHIB_INST_HOME/endorsed/
into this endorsed directory:cp $SHIB_INST_HOME/endorsed/* /var/lib/tomcat6/common/endorsed
If installing with Tomcat5, remove
/var/lib/tomcat5/common/endorsed/*
(@[xml-commons-apis]
.jar
and@[jaxp_parser_impl]
.jar
, symbolic links to/usr/share/java/
) and install all jars from$SHIB_INST_HOME/endorsed/
into/var/lib/tomcat5/common/endorsed
ls -l /var/lib/tomcat5/common/endorsed/* rm /var/lib/tomcat5/common/endorsed/* cp $SHIB_INST_HOME/endorsed/* /var/lib/tomcat5/common/endorsed
Connectors: in
/etc/$TOMCAT_NAME/server.xml
, define a new AJP connector at port 8009.Note
Tomcat6 already has this connector defined, but in an insecure way that would be opening the connector to outside connections as well. Comment the original definition out and instead put this definition in.
<Connector port="8009" address="127.0.0.1" enableLookups="false" redirectPort="443" protocol="AJP/1.3" tomcatAuthentication="false" />
And comment out the existing http connector defined for port 8080:
<!-- <Connector port="8080" maxHttpHeaderSize="8192" maxThreads="150" minSpareThreads="25" maxSpareThreads="75" enableLookups="false" redirectPort="8443" acceptCount="100" connectionTimeout="20000" disableUploadTimeout="true" /> -->
- Tweak Tomcat memory settings: increase the default Java minimal and maximal heap size settings to at least 512MB (or more, depending the total RAM in your VM)
Edit
/etc/$TOMCAT_NAME/$TOMCAT_NAME.conf
and add:JAVA_OPTS="-Xms256m -Xmx768m"
Configure Apache
Apache needs to be configured to:
- Listen on ports 443 and 8443 - this is done via separate configuration files idp.conf and idp8443.conf (bypassing parts of the default configuration in ssl.conf)
- Disable SSL session cache to work around a bug
To make Apache listen at ports 443 and 8443, create
/etc/httpd/conf.d/ports.conf
withListen 443 Listen 8443
- To configure the two virtual hosts for the two ports, download the files attached to this page idp.conf and idp8443.conf into
/etc/httpd/conf.d
- In both files, replace all occurrences of idp.example.org with the hostname of your IdP
- In
idp.conf
, configure the SSL VirtualHost to use the commercial certificate issued for your IdP - Note that idp.conf is configured to disable all access to
<Location /idp/Authn/RemoteUser>
- all users will be authenticating via the Tomcat login screen. - Note that idp8443.conf is using the back-channel certificate generated when deploying Shibboleth IdP, stored in
/opt/shibboleth-idp/credentials
Make a backup of your ssl.conf
cd /etc/httpd/conf.d/ cp ssl.conf ssl.conf.dist
- Edit your ssl.conf and:
Disable SSL session cache by commenting out the default SSLSessionCache directive and instead setting the cache to none:
#SSLSessionCache shmcb:/var/cache/mod_ssl/scache(512000) SSLSessionCache none
- Delete the whole default <VirtualHost> section from
ssl.conf
(the definitions in idp.conf and idp8443.conf will be used instead). - Delete the entry for
Listen 443
(because we now have the directive inports.conf
).
Basic Shibboleth Configuration
Set symbolic links for your convenience. Link
/etc/shibboleth
to the Shibboleth IdP configuration directory and/var/log/shibboleth
to the Shibboleth IdP log directory:ln -s /opt/shibboleth-idp/conf /etc/shibboleth ln -s /opt/shibboleth-idp/logs /var/log/shibboleth
Backup Shibboleth IdP original configuration: to make it easier to track changes done to the Shibboleth configuration files, create a backup copy of each of the files with the ".dist" suffix:
for FILE in \ /opt/shibboleth-idp/conf/{attribute-filter.xml,attribute-resolver.xml,handler.xml,internal.xml,logging.xml,relying-party.xml,service.xml,login.config} \ /root/inst/shibboleth*/src/main/webapp/login.jsp /opt/shibboleth-idp/metadata/idp-metadata.xml ; do cp -i $FILE $FILE.dist ; done
Configure proper Scope in IdP metadata: edit
/opt/shibboleth-idp/metadata/idp-metadata.xml
and make sure the Scope is set to your institution.domain.ac.nz - both forIDPSSODescriptor
andAttributeAuthorityDescriptor
(two modifications)<Extensions> <shibmd:Scope regexp="false">institution.domain.ac.nz</shibmd:Scope> </Extensions>
Configure the IdP to load the Federation Metadata in
/opt/shibboleth-idp/conf/relying-party.xml
by adding the following snippet into theChaining
MetadataProvider
.<!-- Tuakiri --> <metadata:MetadataProvider id="Tuakiri" xsi:type="metadata:ResourceBackedMetadataProvider"> <metadata:MetadataFilter xsi:type="metadata:ChainingFilter" xmlns="urn:mace:shibboleth:2.0:metadata"> <metadata:MetadataFilter xsi:type="metadata:SignatureValidation" xmlns="urn:mace:shibboleth:2.0:metadata" trustEngineRef="shibboleth.MetadataTrustEngine" requireSignedMetadata="true" /> </metadata:MetadataFilter> <metadata:MetadataResource xsi:type="resource:FileBackedHttpResource" url="https://directory.tuakiri.ac.nz/metadata/tuakiri-metadata-signed.xml" file="/opt/shibboleth-idp/metadata/tuakiri-metadata.xml" /> </metadata:MetadataProvider>
The Tuakiri metadata should have their signature verified: add the trust engine definition as well (or uncomment and configure it further down in the file):
<!-- Trust engine used to evaluate the signature on loaded metadata. --> <security:TrustEngine id="shibboleth.MetadataTrustEngine" xsi:type="security:StaticExplicitKeySignature"> <security:Credential id="Tuakiri-FederationCredentials" xsi:type="security:X509Filesystem"> <security:Certificate>/opt/shibboleth-idp/credentials/tuakiri-metadata-cert.pem</security:Certificate> </security:Credential> </security:TrustEngine>
This definition is referring to a certificate used to verify the signature - store the certificate in
/opt/shibboleth-idp/credentials
wget https://directory.tuakiri.ac.nz/metadata/tuakiri-metadata-cert.pem -O $IDP_HOME/credentials/tuakiri-metadata-cert.pem
- Note that the relying-party.xml file also refers to:
- Our own metadata generated for the IdP in
/opt/shibboleth-idp/metadata/idp-metadata.xml
- Our own credentials stored in
/opt/shibboleth-idp/credentials/idp.crt
and/opt/shibboleth-idp/credentials/idp.key
- Our own entityId (also stored in the self-metadata in
/opt/shibboleth-idp/metadata/idp-metadata.xml
- Our own metadata generated for the IdP in
Configure IdP with a login screen
It is desirable to have a site-branded login screen - which makes it easier for users to recognize the proper login screen - and may be necessary for deploying site-wide login and password-handling policies. The credentials are then cached only for a given period of time - instead of the whole browser session.
For deploying a login screen for a Shibboleth 2.0 IdP:
- The primary documentation is at https://wiki.shibboleth.net/confluence/display/SHIB2/IdPAuthUserPass and https://wiki.shibboleth.net/confluence/display/SHIB2/IdPAuthUserPassLoginPage
- Edit
$IDP_HOME/conf/handler.xml
and- Uncomment
UsernamePassword
LoginHandler - Comment out
RemoteUser
LoginHandler Optionally, customize session duration (default 30 minutes): add the following attribute (with the duration either in minutes or using the PT notation) to the UsernamePassword login handler:
authenticationDuration="PT1H0M0.000S"
- Uncomment
Edit
$IDP_HOME/conf/login.config
and provide details for the LDAP server (uncomment and configure LdapLoginModule section). You may have to provide more attributes than what's in the default commented-out section: namelysubtreeSearch="true"
andserviceUser
andserviceCredential
with login details for a privileged account (to look up users). The following section has worked at Canterbury:edu.vt.middleware.ldap.jaas.LdapLoginModule required host="ldap.canterbury.ac.nz" base="ou=useraccounts,dc=canterbury,dc=ac,dc=nz" serviceUser="<ldap user DN here>" serviceCredential="<ldap password here>" subtreeSearch="true" ssl="false" tls="false" userField="uid";
- Customize login screen with site branding: edit
src/main/webapp/login.jsp
in your Shibboleth IdP source distributionRebuild and redeploy the WAR file afterwards by re-running the installer:
cd $SHIB_INST_HOME sh ./install.sh
LDAP connections with TLS/SSL with an untrusted certificate
The connection to the LDAP server can be established either over plain LDAP (no cryptographic protection), or over LDAP with either TLS/SSL. Some LDAP servers may be configured to only accept a bind operation over an cryptographically protected channel (TLS or SSL). Some LDAP servers might however be using a self-signed certificate - or a certificate issued by a CA not trusted by the default Java trust store. In that case, it is necessary to add the CA certificate issuing the LDAP server certificate (or alternatively the LDAP server cerificate itself) to the Java keystore.
- Get the CA certificate and save it into
/opt/shibboleth-idp/credentials/
local-ca
.crt
(picking an appropriate file name) Make a copy of the default Java keystore:
cp $JAVA_HOME/jre/lib/security/cacerts $JAVA_HOME/jre/lib/security/cacerts.orig
Import the CA certificate into the Java keystore:
keytool -import -trustcacerts -alias "Local-CA" -file /opt/shibboleth-idp/credentials/_local-ca_.crt -keystore $JAVA_HOME/jre/lib/security/cacerts
- Change the alias to something descriptive for the local CA
- You will get prompted for the passphrase protecting the Java keystore. The default password is "
changeit
" (literally).
- Note: an alternative approach is to configure the LDAP Resolver with an embedded TLS certificate. However, this:
- only works for TLS and not SSL
- only works for the LDAP resolver itself, but not for the login screen connector in
login.conf
Install uApprove
Privacy laws require the IdP to get an explicit consent from the user before releasing personal information about the user to other parties. Thus, before proceeding with a Shibboleth login and sending the user's attributes to the Service Provider, the IdP must first obtain the user's consent. The uApprove application takes care of this - it steps in the first time the user is logging in to a service, and asks the user for permission to release the required (and desired) attributes to the service. The user would be asked again if the set of attributes released to the service changes. The user also has the option of giving a Global consent - permission to release any attributes to any service the user accesses in the future. The Global consent can be later revoked (via the Reset-approvals feature) and can also be completely disabled in the system-wide configuration (if the institution decided their users shouldn't be allowed to give global consent).
More information about uApprove, as well as download links, can be found at http://www.switch.ch/aai/support/tools/uApprove.html.
As uApprove plugs into the IdP, the version of uApprove must be matched to be compatible with the version of IdP. At the time of writing (May 2012), the most recent version of uApprove (2.4.1) is compatible with IdP 2.3.6 (the most recent stable version).
As of version 2.4.1, uApprove installs directly into the IdP web applications (previous versions, up to 2.2.1, were a separate web application with install base in /opt/uApprove
). The uApprove configuration files are now located in /opt/shibboleth-idp/conf
. After installing uApprove into the IdP web application, it is necessary to re-run the IdP installer to rebuild the IdP WAR file.
The following instructions are closely based on the uApprove 2.4.1 installation manual, http://www.switch.ch/aai/downloads/uApprove-manual/
Please check at the uApprove website that 2.4.1 is still the most recent version - and otherwise refer to the new version's installation manual for updated instructions.
uApprove can store the approval information in either a SQL database, or in a flat file. Storing the information in a SQL database is more scalable, and it also allows to revoke consent already given. This guide documents installing uApprove configured to use a local MySQL database. Please refer to the uApprove installation manual for other alternatives.
To install uApprove:
Download the uApprove binary distribution, unpack it in
/root/inst
cd /root/inst wget http://www.switch.ch/aai/downloads/uApprove-${UAPPROVE_VERSION}.zip unzip uApprove-${UAPPROVE_VERSION}.zip
Copy uApprove libraries into the IdP lib directory:
# match the variable names used in uApprove manual export UAPPROVE_INSTALL=$UAPPROVE_INST_HOME export IDP_INSTALL=$SHIB_INST_HOME cp $UAPPROVE_INSTALL/lib/*.jar $IDP_INSTALL/lib cp $UAPPROVE_INSTALL/lib/jdbc/*.jar $IDP_INSTALL/lib
- If using a SQL database (e.g., MySQL), install the JDBC driver into
$IDP_INSTALL/lib
. Either download the version from the database vendor's site (for MySQL: http://dev.mysql.com/downloads/connector/j/), or use one packaged with uApprove in$UAPPROVE_INSTALL/lib/jdbc/optional
(has version 5.1.18 of the MySQL JDBC driver).
Copy configuration files into IdP configuration directory:
cp $UAPPROVE_INSTALL/manual/configuration/uApprove.properties $IDP_HOME/conf cp $UAPPROVE_INSTALL/manual/configuration/uApprove.xml $IDP_HOME/conf
Copy the uApprove web application files (JSPs, CSS, images) to the IdPs webapp directory:
mkdir $IDP_INSTALL/src/main/webapp/uApprove cp $UAPPROVE_INSTALL/webapp/* $IDP_INSTALL/src/main/webapp/uApprove
If running with MySQL:
Note on MySQL timeouts
By default, MySQL closes connections after 8 hours of inactivity. This breaks connections overnight - and the database clients running on the IdP (uApprove and also SharedToken) report errors when reconnecting to the database (even when using
autoReconnect=true
).As of September 2011 when this manual has been updated to use JDBC URLs that set the
wait_timeout
session variable to a very high value (one year), so changing the setting on the server side is no longer necessary.The original instructions were to edit
/etc/my.cnf
and add the following into the[mysqld]
section:wait_timeout=31536000 # 3600*24*365 - one year
Start MySQL server and make it start automatically:
service mysqld start chkconfig mysqld on
Set the MySQL root password (in a default installation, MySQL root user has no password):
/usr/bin/mysqladmin -u root password MYSQL-ROOT-PASSWORD
For convenience, create a
/root/.my.cnf
file that allows Unixroot
to login as MySQLroot
without entering a password:[client] password=MYSQL-ROOT-PASSWORD
Create a MySQL database (
uApprove
), a user (alsouApprove
), and grant the user full access over the database (replace DB-PASSWORD with a suitable password):mysql -u root mysql> CREATE DATABASE uApprove; CREATE USER 'uApprove'@'localhost' IDENTIFIED BY 'DB-PASSWORD'; GRANT ALL PRIVILEGES ON uApprove.* TO 'uApprove'@'localhost'; ALTER DATABASE uApprove DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
Create the database tables, logging in as uApprove: run
mysql -u uApprove -p
, and feeding the two table definition SQL files to mysql:mysql -u uApprove -p uApprove < $UAPPROVE_INSTALL/manual/storage/attribute-release-schema.sql mysql -u uApprove -p uApprove < $UAPPROVE_INSTALL/manual/storage/terms-of-use-schema.sql
Make a backup of original uApprove configuration files before modifying them:
for FILE in $IDP_HOME/conf/uApprove.properties $IDP_HOME/conf/uApprove.xml $SHIB_INST_HOME/src/main/webapp/WEB-INF/web.xml ; do cp $FILE ${FILE}.dist ; done
- Edit the IdP web application deployment descriptor (
$IDP_INSTALL/src/main/webapp/WEB-INF/web.xml
) and paste in the relevant snippet as per section 2.1 of the uApprove manual.- Add the
uApprove.xml
file to the list of contextConfigLocation URLs Add the uApprove
filter
,filter-mapping
,servlet
, andservlet-mapping
elements just before the end of the top-levelweb-app
element.<web-app ...> <context-param> <param-name>contextConfigLocation</param-name> <param-value>$IDP_HOME$/conf/internal.xml; $IDP_HOME$/conf/service.xml; $IDP_HOME$/conf/uApprove.xml; </param-value> </context-param> <!-- IdP Listeners, Filters and Servlets --> <!-- ... --> <!-- uApprove Filter and Servlets --> <filter> <filter-name>uApprove</filter-name> <filter-class>ch.SWITCH.aai.uApprove.Intercepter</filter-class> </filter> <filter-mapping> <filter-name>uApprove</filter-name> <url-pattern>/profile/Shibboleth/SSO</url-pattern> <url-pattern>/profile/SAML1/SOAP/AttributeQuery</url-pattern> <url-pattern>/profile/SAML1/SOAP/ArtifactResolution</url-pattern> <url-pattern>/profile/SAML2/POST/SSO</url-pattern> <url-pattern>/profile/SAML2/POST-SimpleSign/SSO</url-pattern> <url-pattern>/profile/SAML2/Redirect/SSO</url-pattern> <url-pattern>/profile/SAML2/Unsolicited/SSO</url-pattern> <url-pattern>/Authn/UserPassword</url-pattern> </filter-mapping> <servlet> <servlet-name>uApprove - Terms Of Use</servlet-name> <servlet-class>ch.SWITCH.aai.uApprove.tou.ToUServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>uApprove - Terms Of Use</servlet-name> <url-pattern>/uApprove/TermsOfUse</url-pattern> </servlet-mapping> <servlet> <servlet-name>uApprove - Attribute Release</servlet-name> <servlet-class>ch.SWITCH.aai.uApprove.ar.AttributeReleaseServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>uApprove - Attribute Release</servlet-name> <url-pattern>/uApprove/AttributeRelease</url-pattern> </servlet-mapping> </web-app>
- Add the
- Edit
$IDP_HOME/conf/uApprove.xml
and change property location from aclasspath
URL to:file:/opt/shibboleth-idp/conf/uApprove.properties
- Edit
$IDP_HOME/conf/uApprove.properties
and customize the following:Set services (services excluded from uApprove) to the SLCS servers (AU and NZ) - note that as of uApprove 2.4.1, this is now a set of regular expressions:
services = ^https://slcs1\.arcs\.org\.au/shibboleth$ \ ^https://slcs\.nesi\.org\.nz/shibboleth$ \ ^https://slcs1\.nesi\.org\.nz/shibboleth$
- Make the database URL automatically reconnect and use very long session timeouts:
database.url = jdbc:mysql://localhost:3306/uApprove?autoReconnect=true&sessionVariables=wait_timeout=31536000
- Set the database password for the uApprove user:
database.password = DB-PASSWORD
- Disable Terms-Of-Use:
tou.enabled = false
List the order in which attributes should appear (instead of letting them display in a random order each time: change the
ar.attributes.order
property (which lists only a few attributes by default) to cover all relevant attributes:ar.attributes.order = commonName \ displayName \ auEduPersonLegalName \ givenName \ surname \ email \ eduPersonPrincipalName \ uid \ auEduPersonSharedToken \ eduPersonTargetedID \ eduPersonEntitlement \ eduPersonAssurance \ eduPersonAffiliation \ eduPersonScopedAffiliation \ eduPersonPrimaryAffiliation \ auEduPersonAffiliation \ organizationName \ homeOrganization \ homeOrganizationType \ organizationalUnit \ postalAddress \ telephoneNumber \ mobileNumber
Add a checkbox into the login form that would give the user the option to reset all prior approvals: edit
$SHIB_INST_HOME/src/main/webapp/login.jsp
and add the following table row with a checkbox below the password prompt table row:<tr><td colspan="2"> <input id="uApprove.consent-revocation" type="checkbox" name="uApprove.consent-revocation" value="true"/> <label for="uApprove.consent-revocation">Clear my attribute release consent</label> <div class="infotext">Checking this option resets all of your previously given approvals for sending information about you to this site and any other services.</div> </td></tr>
Rebuild the Shibboleth IdP WAR:
cd $SHIB_INST_HOME sh ./install.sh
If you already have the IdP running, restart Tomcat and reload Apache (otherwise, if this is the first install, wait with starting Tomcat till instructed to do so in the next section):
service $TOMCAT_NAME restart
For additional documentation, see the uApprove installation manual at http://www.switch.ch/aai/downloads/uApprove-manual/.
Start Tomcat
Make all files under /opt/shibboleth-idp owned by Tomcat:
chown -R tomcat.tomcat /opt/shibboleth-idp
For extra security, you may consider making files where passwords to MySQL are stored readable only to the Tomcat users:
chmod 600 /opt/shibboleth-idp/conf/uApprove.properties /opt/shibboleth-idp/conf/attribute-resolver.xml /opt/shibboleth-idp/conf/login.config
Start MySQL, Tomcat and Apache and make them auto start:
service mysqld start service $TOMCAT_NAME start service httpd start chkconfig mysqld on chkconfig $TOMCAT_NAME on chkconfig httpd on
Configure Attribute Resolver
All attribute configuration is done in /opt/shibboleth-idp/conf/attribute-resolver.xml
.
Edit the file and implement the following changes:
Link your Attribute Resolver to your LDAP server
In /opt/shibboleth-idp/conf/attribute-resolver.xml
, uncomment the LDAP DataConnector
element and configure it with local LDAP connection parameters to connect to your LDAP server (ldapURL, baseDN, principal, principalCredential) and also set the property java.naming.referral
to "follow"
:
<resolver:DataConnector id="myLDAP" xsi:type="LDAPDirectory" xmlns="urn:mace:shibboleth:2.0:resolver:dc" ldapURL="*ldap://ldap.institution.domain.ac.nz*" baseDN="dc=institution,dc=domain,dc=ac,dc=nz" principal="LDAP-BIND-DN-HERE" principalCredential="PASSWORD-HERE"> <FilterTemplate> <![CDATA[ (cn=$requestContext.principalName) ]]> </FilterTemplate> <dc:LDAPProperty name="java.naming.referral" value="follow"/> </resolver:DataConnector>
Link existing attributes
- Define attributes available directly in LDAP:
mail
,sn
, andgivenName
: just uncomment the relevantAttributeDefinition
element for each of these attributes.
- Define attributes available as an attribute in the LDAP with a slightly different name - typically, in ActiveDirectory, cn would be the user's login name, while displayName would be the user's actual preferred (common) name. In that case, uncomment the relevant
AttributeDefinition
element and change the sourceAttributeID XML attribute to the name of the original attribute. If connecting to ActiveDirectory,- Define
cn
based ondisplayName
(sourceAttributeID="displayName") - Define
uid
based oncn
- Define
displayName
based ondisplayName
.
- Define
Define
eduPersonPrincipalName
define based oncn
with your institution's scope (in the form institution.domain.ac.nz): set thescope
attribute like:scope="institution.domain.ac.nz" sourceAttributeID="cn"
- If either
eduPersonAssurance
oreduPersonEntitlement
are available in your IdMS, expose them via the IdP by uncommenting their respective definition inattribute-resolver.xml
Define static attributes
We need to define several attributes that would have a static value for each user. We do so by first defining a StaticDataConnector
(close to where the commented-out example is):
- Provide actual meaningful values for your institution: full organization name, home organization name (same as scope), and home Organization Type.
- For full list of homeOrganizationType values, see http://www.terena.org/activities/tf-emc2/docs/schac/schac-20061212-1.3.0.schema.txt- the relevant values are:
- urn:mace:terena.org:schac:homeOrganizationType:int:university
- urn:mace:terena.org:schac:homeOrganizationType:int:research-institution
- urn:mace:terena.org:schac:homeOrganizationType:int:other
- For full list of homeOrganizationType values, see http://www.terena.org/activities/tf-emc2/docs/schac/schac-20061212-1.3.0.schema.txt- the relevant values are:
<!-- Static Connector --> <resolver:DataConnector id="staticAttributes" xsi:type="dc:Static"> <dc:Attribute id="o"> <dc:Value>The Institution</dc:Value> </dc:Attribute> <dc:Attribute id="homeOrganization"> <dc:Value>institution.domain.ac.nz</dc:Value> </dc:Attribute> <dc:Attribute id="homeOrganizationType"> <dc:Value>urn:mace:terena.org:schac:homeOrganizationType:int:university</dc:Value> </dc:Attribute> </resolver:DataConnector>
Now define the attributes:
- Define
organizationName
by uncommenting the definition and changing the connector dependency from "myLDAP" to "staticAttributes"- Note: the attribute constructed by the IdP is called
organizationName
, while the attribute defined in thestaticAttributes
connector used as the source for this attribute is called justo
. Don't get confused.
- Note: the attribute constructed by the IdP is called
- Pasting in the definitions for
homeOrganization
andhomeOrganizationType
, not provided in the default configuration:
<resolver:AttributeDefinition id="homeOrganization" xsi:type="ad:Simple" sourceAttributeID="homeOrganization"> <resolver:Dependency ref="staticAttributes" /> <resolver:AttributeEncoder xsi:type="enc:SAML1String" name="urn:oid:1.3.6.1.4.1.25178.1.2.9" /> <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="urn:oid:1.3.6.1.4.1.25178.1.2.9" friendlyName="homeOrganization" /> </resolver:AttributeDefinition> <resolver:AttributeDefinition id="homeOrganizationType" xsi:type="ad:Simple" sourceAttributeID="homeOrganizationType"> <resolver:Dependency ref="staticAttributes" /> <resolver:AttributeEncoder xsi:type="enc:SAML1String" name="urn:oid:1.3.6.1.4.1.25178.1.2.10" /> <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="urn:oid:1.3.6.1.4.1.25178.1.2.10" friendlyName="homeOrganizationType" /> </resolver:AttributeDefinition>
Define scripted attributes
The eduPersonAffiliation
and eduPersonPrimaryAffiliation
describe the affiliation type of the user authenticating. The typical question is: "Is this person staff or student?" The full set of values (with definitions available in the AAF Attribute Recommendation: eduPersonAffiliation) is: faculty / student / staff / employee / member / affiliate / alum / library-walk-in. The eduPersonAffiliation
attribute is multi-valued and should include all values that apply to the user, while eduPersonPrimaryAffiliation
should contain only a single, the most relevant value.
Typically, the LDAP server will not be directly providing values for these attributes, but it would have some attributes that allow to determine at least some of the affiliation type values applying to the user - e.g. to tell whether the user is a staff member or a student.
In this case, we recommend defining the attributes using a scriptlet, synthesizing the value from the LDAP attributes available.
This would be very specific for each institution. We illustrate this in an example (based on an actual setup), where we assume the LDAP server has attributes:
- isUnderGrad (boolean)
- isPostGrad (boolean)
- isStaff (boolean)
We decide to give anyone with isStaff=TRUE
the "staff"
affiliation, and to anyone with isUnderGrad=TRUE OR isPostGrad=TRUE
the "student"
affiliation. Also, anyone who is staff or student also gets the "member"
affiliation.
- We first define these attributes at the Shibboleth level, importing them from LDAP, using the following definitions. Note that as these attributes are not expected to be passed in Shibboleth assertions, the definitions don't have any
AttributeEncoder
elements. Otherwise, we would have to decide on attribute names / OIDs to use in the encoder definitions.
<!-- prerequisite to scripted eduPersonAffiliation --> <resolver:AttributeDefinition id="isUnderGrad" xsi:type="ad:Simple" sourceAttributeID="isUnderGrad"> <resolver:Dependency ref="myLDAP" /> <!-- no encoder needed --> </resolver:AttributeDefinition> <resolver:AttributeDefinition id="isPostGrad" xsi:type="ad:Simple" sourceAttributeID="isPostGrad"> <resolver:Dependency ref="myLDAP" /> <!-- no encoder needed --> </resolver:AttributeDefinition> <resolver:AttributeDefinition id="isStaff" xsi:type="ad:Simple" sourceAttributeID="isStaff"> <resolver:Dependency ref="myLDAP" /> <!-- no encoder needed --> </resolver:AttributeDefinition>
- We follow by defining
eduPersonAffiliation
using anAttributeDefinition
of typeScript
:
<resolver:AttributeDefinition id="eduPersonAffiliation" xsi:type="ad:Script"> <resolver:Dependency ref="isUnderGrad" /> <resolver:Dependency ref="isPostGrad" /> <resolver:Dependency ref="isStaff" /> <resolver:AttributeEncoder xsi:type="enc:SAML1String" name="urn:mace:dir:attribute-def:eduPersonAffiliation" /> <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1" friendlyName="eduPersonAffiliation" /> <ad:Script> <![CDATA[ importPackage(Packages.edu.internet2.middleware.shibboleth.common.attribute.provider); if (eduPersonAffiliation == null) { eduPersonAffiliation = new BasicAttribute("eduPersonAffiliation"); } is_UnderGrad = isUnderGrad != null && isUnderGrad.getValues().size()>0 && isUnderGrad.getValues().get(0).equals("TRUE"); is_PostGrad = isPostGrad != null && isPostGrad.getValues().size()>0 && isPostGrad.getValues().get(0).equals("TRUE"); is_Staff = isStaff != null && isStaff.getValues().size()>0 && isStaff.getValues().get(0).equals("TRUE"); if (is_Staff) { eduPersonAffiliation.getValues().add("staff"); }; if (is_UnderGrad || is_PostGrad ) { eduPersonAffiliation.getValues().add("student"); }; if (is_UnderGrad || is_PostGrad || is_Staff ) { eduPersonAffiliation.getValues().add("member"); }; ]]> </ad:Script> </resolver:AttributeDefinition>
- And a similar definition for
eduPersonPrimaryAffiliation
(which has to be a single valued attribute, hence the logic in the script is slightly different):
<resolver:AttributeDefinition id="eduPersonPrimaryAffiliation" xsi:type="ad:Script"> <resolver:Dependency ref="isUnderGrad" /> <resolver:Dependency ref="isPostGrad" /> <resolver:Dependency ref="isStaff" /> <resolver:AttributeEncoder xsi:type="enc:SAML1String" name="urn:mace:dir:attribute-def:eduPersonPrimaryAffiliation" /> <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.5" friendlyName="eduPersonPrimaryAffiliation" /> <ad:Script> <![CDATA[ importPackage(Packages.edu.internet2.middleware.shibboleth.common.attribute.provider); if (eduPersonPrimaryAffiliation == null) { eduPersonPrimaryAffiliation = new BasicAttribute("eduPersonPrimaryAffiliation"); } is_UnderGrad = isUnderGrad != null && isUnderGrad.getValues().size()>0 && isUnderGrad.getValues().get(0).equals("TRUE"); is_PostGrad = isPostGrad != null && isPostGrad.getValues().size()>0 && isPostGrad.getValues().get(0).equals("TRUE"); is_Staff = isStaff != null && isStaff.getValues().size()>0 && isStaff.getValues().get(0).equals("TRUE"); if (is_Staff) { eduPersonPrimaryAffiliation.getValues().add("staff"); } else if (is_UnderGrad || is_PostGrad ) { eduPersonPrimaryAffiliation.getValues().add("student"); }; ]]> </ad:Script> </resolver:AttributeDefinition>
- Finally, we define the
eduPersonScopedAffiliation
attribute by uncommenting the definition and:- setting your institution's scope, in the format
scope="institution.domain.ac.nz"
changing the dependency from LDAP to the previously defined attribute
eduPersonAffiliation
:<resolver:Dependency ref="eduPersonAffiliation" />
- setting your institution's scope, in the format
Define sharedToken
- The instructions below are based on the original ARCS instructions, now archived at https://github.com/University-of-Auckland/arcs-shibext/blob/master/INSTALL-SharedToken.md
- We will choose to store the SharedToken value in a MySQL database - to keep track of values issued and have a means of inserting a different value if someone asks for portability.
Download binary from https://github.com/University-of-Auckland/arcs-shibext/releases/download/1.5.5/arcs-shibext-1.5.5.jar
wget https://github.com/University-of-Auckland/arcs-shibext/releases/download/1.5.5/arcs-shibext-1.5.5.jar
The shared token value MUST be stored in either the LDAP server itself (preferred, keeps the values alongside primary identity information), or alternatively in a MySQL database (easier to get going by running a MySQL server directly on the IdP).
In this section, some instructions are specific to storing the shared token values in an LDAP server, some are specific to storing the values in a local MySQL server - please choose accordingly.
If storing the sharedToken value in your LDAP server, edit the conf/sharedtoken.properties inside the jar and change the following settings - the search filter should be the same as in your LDAP connector - configuring which LDAP attribute is the principal name:
DEFAULT_IDP_HOME=/opt/shibboleth-idp SEARCH_FILTER_SPEC=cn={0}
Copy the JAR into
$SHIB_INST_HOME/lib
and (later) rerun the Shibboleth IdP installer to rebuild the webapp WAR archive. (When rerunning the installer, accept the default install location (or specify your install location, stored also in$IDP_HOME
) and answer no to the question on overwriting configuration.)cp arcs-shibext-*.jar $SHIB_INST_HOME/lib cd $SHIB_INST_HOME sh ./install.sh
Configuring a MySQL database for storing sharedToken values
- If configuring with a MySQL database and a MySQL driver is not yet present in the IdP (should be installed with uApprove), download the MySQL JDBC driver from http://dev.mysql.com/downloads/connector/j/5.0.html
- Install the driver (
mysql-connector-java-5.0.8-bin.jar
) into$SHIB_INST_HOME/lib
and also into/opt/shibboleth-idp/lib
(and re-run the Shibboleth IdP installer - now)
- Install the driver (
Create a MySQL user: run "mysql" as root and enter the following commands:
create user 'idp_admin'@'localhost' identified by 'IDP_ADMIN_PASSWORD'; grant all privileges on idp_db.* to 'idp_admin'@'localhost';
Create a MySQL user: run "mysql" as idp_admin and enter the following commands:
mysql -u idp_admin -p CREATE DATABASE idp_db; use idp_db; CREATE TABLE tb_st ( uid VARCHAR(100) NOT NULL, sharedToken VARCHAR(50), PRIMARY KEY (uid) );
Defining sharedToken attribute (both LDAP and MySQL)
- Add schema definition to
attribute-resolver.xml
: addurn:mace:arcs.org.au:shibboleth:2.0:resolver:dc classpath:/schema/arcs-shibext-dc.xsd
to the list of schema locations at the top of the file.
- Add connector definition to
attribute-resolver.xml
(sharedToken) with the following customizations:- idPIdentifier - your IdP entityId
- sourceAttributeID: combination of attributes that is unique, non-reassignable and if possible persistent - if usernames are not reused at your institution, username is perfectly fine - so the "cn" or "uid" attribute would do
- If using a MySQL server, enter the database connection details, with the IDP_ADMIN_PASSWORD as defined just above
- If storing sharedToken in an LDAP server:
- Omit the
DatabaseConnection
element from the below snippet Change the values to
storeLdap="true"
andstoreDatabase="false"
<!-- ==================== auEduPersonSharedToken data connector ================== --> <resolver:DataConnector xsi:type="SharedToken" xmlns="urn:mace:arcs.org.au:shibboleth:2.0:resolver:dc" id="sharedToken" idpIdentifier="https://idp.institution.domain.ac.nz/idp/shibboleth" sourceAttributeID="cn" storeLdap="false" storeDatabase="true" salt="SALT-GOES-HERE"> <resolver:Dependency ref="myLDAP" /> <DatabaseConnection jdbcDriver="com.mysql.jdbc.Driver" jdbcURL="jdbc:mysql://localhost/idp_db?autoReconnect=true&sessionVariables=wait_timeout=31536000" jdbcUserName="idp_admin" jdbcPassword="IDP_ADMIN_PASSWORD" primaryKeyName="uid"/> </resolver:DataConnector>
Please note that the sharedToken module would be accessing the LDAP server from the connector specified in the dependency - so the same LDAP server as used for retrieving all other attributes, with the same credentials. Therefore, in order for this module to succeed in storing the generated sharedToken values, the account specified in the LDAP connector needs to have the permissions to write into the
auEduPersonSharedToken
attribute.
- Omit the
Note: on the first install, generate a suitable salt value with:
openssl rand -base64 36
- On subsequent installs, reuse the same value (stored somewhere carefully)
- Note also that the SharedToken value depends on the IdP entityID - which could be picked up from the environment, but is better set in the configuration.
- Note that the JdbcURL sets the
"autoReconnect=true"
option and sets thewait_timeout
session variable to a very high value (one year) - which is an extension from the original shared-token installation instructions.- As we are putting a URL with an ampersand (&) into an XML document, we need to encode the character as
&
amp;
- As we are putting a URL with an ampersand (&) into an XML document, we need to encode the character as
Add attribute definition to attribute-resolver.xml (auEduPersonSharedToken)
<!-- ==================== auEduPersonSharedToken attribute definition ================== --> <resolver:AttributeDefinition id="auEduPersonSharedToken" xsi:type="ad:Simple" sourceAttributeID="auEduPersonSharedToken"> <resolver:Dependency ref="sharedToken" /> <resolver:AttributeEncoder xsi:type="enc:SAML1String" name="urn:mace:federation.org.au:attribute:auEduPersonSharedToken" /> <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="urn:oid:1.3.6.1.4.1.27856.1.2.5" friendlyName="auEduPersonSharedToken" /> </resolver:AttributeDefinition>
- Release attribute in attribute-filter.xml (auEduPersonSharedToken)
- See attribute release later.
eduPersonTargetedID
Based on https://wiki.shibboleth.net/confluence/display/SHIB2/NativeSPTargetedID, define (uncomment) eduPersonTargetedID (in the "new" format only, ignore the "old" format). The steps are:
- Uncommenting AttributeDefinition id="eduPersonTargetedID"
- Uncommenting DataConnector where id="computedID and changing it in the following ways:
- Using just the username attribute (typically
cn
,uid
orsAMAccountName
) as the source attribute.- Note: the attribute chosen must be unique, persistent, and non-reassignable - if usernames are reused at your institution, you must choose a different attribute (e.g.,
objectGUID
on AD servers works well for this purpose)
- Note: the attribute chosen must be unique, persistent, and non-reassignable - if usernames are reused at your institution, you must choose a different attribute (e.g.,
Using a value of salt generated (only at the first install, to be reused later) with:
openssl rand -base64 36
- Using just the username attribute (typically
This is the final configuration of the ComputeID DataConnector (without the proper salt):
<resolver:DataConnector xsi:type="ComputedId" xmlns="urn:mace:shibboleth:2.0:resolver:dc" id="computedID" generatedAttributeID="computedID" sourceAttributeID="cn" salt="abcef123YOURVALUE"> <resolver:Dependency ref="myLDAP" /> </resolver:DataConnector>
eduPersonAssurance
The eduPersonAssurance expresses both levels of identity assurance and authentication assurance (i.e., both how sure an IdMS is about the identity of a user and how strong authentication mechanisms were used to establish the session). These attributes would ideally have per-user values, based on information captured about the users in the IdMS - e.g., an attribute tracking whether the business process for creating the user's credentials involved checking official photoID documents and e.g. what kind of password policy applies to the user.
In the absence of such information in the IdMS, we recommend to at least define this attribute as a static attribute (providing the same value for all users) at level 1 (floor of trust). The basic requirements for level 1 are that the institution has documented processes for issuing credentials and is following good practice in managing credentials.
To configure the level 1 values as static attributes:
Add the level1 identity and authentication assurance values to the
staticAttributes
connector (defined above) withid="eduPersonAssurance"
:<resolver:DataConnector id="staticAttributes" xsi:type="dc:Static"> <dc:Attribute id="eduPersonAssurance"> <dc:Value>urn:mace:aaf.edu.au:iap:id:1</dc:Value> <dc:Value>urn:mace:aaf.edu.au:iap:authn:1</dc:Value> </dc:Attribute> ... </resolver:DataConnector>
- Uncomment the
eduPersonAssurance
attribute definition and change the connector dependency from"myLDAP"
to"staticAttributes"
eduPersonEntitlement
The eduPersonEntitlement
attribute is a multivalued container for arbitrary strings (URNs) that identify privileges. Most values are yet-to-be-defined, one commonly used value is urn:mace:dir:entitlement:common-lib-terms
. If not adding the eduPersonEntitlement
to your IdMS, we recommend defining eduPersonEntitlement
as a static attribute with this value (representing "this user has library privileges") being the only value defined.
- Uncomment the
eduPersonEntitlement
attribute definition and change the connector dependency from"myLDAP"
to"staticAttributes"
Add single value to be released (can be multivalued if desired) to the
staticAttributes
connector (defined above) withid="eduPersonEntitlement"
:<resolver:DataConnector id="staticAttributes" xsi:type="dc:Static"> <dc:Attribute id="eduPersonEntitlement"> <dc:Value>urn:mace:dir:entitlement:common-lib-terms</dc:Value> </dc:Attribute> ... </resolver:DataConnector>
Configuring Attribute Release
- Attribute release is configured in
/opt/shibboleth-idp/conf/attribute-filter.xml
- The file can contain multiple policies.
- Each policy can apply to a number of hosts or hostgroups (federations) - linked with the
basic:OR
policy. - Attributes are referred to by the "friendly" ID they get assigned in
attribute-resolver.xml
. - Further documentation on policy rules is at https://wiki.shibboleth.net/confluence/display/SHIB2/IdPAddAttributeFilter.
- The following two policies release:
- All the required attributes to the Tuakiri Federation Registry - necessary for logging in there.
All available attributes to the Tuakiri Attribute Reflector (running on the virtualhome server) - very useful for testing.
<afp:AttributeFilterPolicy id="federationRegistryPolicy" > <afp:PolicyRequirementRule xsi:type="basic:AttributeRequesterString" value="https://registry.tuakiri.ac.nz/shibboleth" /> <afp:AttributeRule attributeID="displayName"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="surname"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="givenName"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="email"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="homeOrganization"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="homeOrganizationType"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="eduPersonTargetedID"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="auEduPersonSharedToken"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> </afp:AttributeFilterPolicy> <afp:AttributeFilterPolicy id="virtualHomePolicy" > <afp:PolicyRequirementRule xsi:type="basic:AttributeRequesterString" value="https://virtualhome.tuakiri.ac.nz/shibboleth" /> <afp:AttributeRule attributeID="displayName"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="commonName"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="surname"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="givenName"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="email"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="eduPersonPrincipalName"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="eduPersonScopedAffiliation"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="eduPersonAffiliation"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="eduPersonAssurance"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="eduPersonPrimaryAffiliation"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="homeOrganization"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="homeOrganizationType"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="organizationName"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="eduPersonTargetedID"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="auEduPersonSharedToken"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="eduPersonEntitlement"> <afp:PermitValueRule xsi:type="basic:AttributeValueString" value="urn:mace:dir:entitlement:common-lib-terms" /> </afp:AttributeRule> <afp:AttributeRule attributeID="auEduPersonAffiliation"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="auEduPersonLegalName"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="mobileNumber"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="postalAddress"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="organizationalUnit"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> <afp:AttributeRule attributeID="telephoneNumber"> <afp:PermitValueRule xsi:type="basic:ANY" /> </afp:AttributeRule> </afp:AttributeFilterPolicy>
- As needed, add more refined policies for hosts that need additional attributes. Instead of manually defining policies for all hosts, configure the automatic download of the Tuakiri attribute release policy synthesized for your IdP - see further below for that.
- You may also wish to configure additional attribute release policies - e.g., if establishing bilateral relations with some service providers outside Tuakiri or if registering your IdP into another federation that does not generate a per-SP attribute filter (in that case, releasing a set of attributes to all hosts in the federation via an RequesterInEntityGroup rule might be a good choice). For more information on such configuration, please see the Shibboleth 2 IdP attribute filter documentation.
Register the IdP into the federation
Please follow the instructions on registering an IdP into the Tuakiri federation (using Federation Registry URL https://registry.tuakiri.ac.nz/federationregistry/ for the Tuakiri federation or https://registry.test.tuakiri.ac.nz/federationregistry/ for Tuakiri-TEST)
Go to the respecting Federation Registry URL and: After having your IdP registration approved, click on the link sent to you to become an Administrator of the IdP's registration. Confirmation emailhttps://idp.example.org
).$IDP_HOME/credentials/idp.pem
).urn:oasis:names:tc:SAML:2.0:nameid-format:transient
is already selected.
Advanced IdP Configuration
Enabling automatic reload
To automatically reload a service configuration (such as the attribute-filter.xml file), one has to add two attributes to the service definition: configurationResourcePollingFrequency (in milliseconds) and configurationResourcePollingRetryAttempts.
The change done to /opt/shibboleth-idp/conf/service.xml
is thus:
<srv:Service id="shibboleth.AttributeResolver" + configurationResourcePollingFrequency="PT5.000S" configurationResourcePollingRetryAttempts="10" xsi:type="attribute-resolver:ShibbolethAttributeResolver"> <srv:ConfigurationResource file="/opt/shibboleth-idp/conf/attribute-resolver.xml" xsi:type="resource:FilesystemResource" /> </srv:Service> <srv:Service id="shibboleth.AttributeFilterEngine" + configurationResourcePollingFrequency="PT5.000S" configurationResourcePollingRetryAttempts="10" xsi:type="attribute-afp:ShibbolethAttributeFilteringEngine"> <srv:ConfigurationResource file="/opt/shibboleth-idp/conf/attribute-filter.xml" xsi:type="resource:FilesystemResource" /> </srv:Service>
and
<srv:Service id="shibboleth.RelyingPartyConfigurationManager" + configurationResourcePollingFrequency="PT5.000S" configurationResourcePollingRetryAttempts="10" xsi:type="relyingParty:SAMLMDRelyingPartyConfigurationManager" depends-on="shibboleth.SAML1AttributeAuthority shibboleth.SAML2AttributeAuthority"> <srv:ConfigurationResource file="/opt/shibboleth-idp/conf/relying-party.xml" xsi:type="resource:FilesystemResource" /> </srv:Service> <srv:Service id="shibboleth.HandlerManager" + configurationResourcePollingFrequency="PT5.000S" configurationResourcePollingRetryAttempts="10" depends-on="shibboleth.RelyingPartyConfigurationManager" xsi:type="profile:IdPProfileHandlerManager"> <srv:ConfigurationResource file="/opt/shibboleth-idp/conf/handler.xml" xsi:type="resource:FilesystemResource" /> </srv:Service>
Load Attribute Filter
This step should be done only after fully registering your IdP into the federation.
To automatically release attributes to new services registered in the federation, we will define inside the AttributeFilterEngine
a second ConfigurationResource
, loading the data from a remote HTTP URL (backed by a local file) (as documented in Shibboleth documentation on multiple policy group files).
If registering the IdP into multiple federations (such as into Tuakiri and AAF), load the attribute filter for each of the federations according to the respective instructions.
For Tuakiri: please follow the instructions at Configuring a Shibboleth Identity Provider to join the Tuakiri Federation#Configure attribute release/filtering through the federation (this process would provide you with a custom URL to download the metadata from).
- Contact the federation administrators (by emailing tuakiri@reannz.co.nz) and request a URL for the Attribute Filter for your IdP.
- In the request, please include:
- The name (hostname or entityID) of your IdP
- An email address that should receive notifications whenever the attribute filter changes (these are notifications only, no action will be required).
- The attribute filter may have to be manually added to the list of attribute filters published. Once created, the URL will have the form of:
https://directory.tuakiri.ac.nz/attribute-filter/
<institution-domain>.xml
- In the request, please include:
After requesting the attribute filter: Add the following entry into Note: if your If configuring this in Shibboleth IdP 2.1.x, do not use the srv: namespace prefix - i.e., use just: We also strongly recommend you configure your IdP to periodically reload this file - we recommend at 2 hour intervals. This is documented in detail in the IdP Install Manual: Reloading configuration section and Load Attribute Filter sections. The simple step is to add the <srv:Service id="shibboleth.AttributeFilterEngine"
in $IDP_HOME/conf/service.xml
(note that the URL varies for each IdP and has to be obtained from the federation administrators): <srv:ConfigurationResource xsi:type="resource:FileBackedHttpResource"
url="https://directory.tuakiri.ac.nz/attribute-filter/<institution-domain>.xml"
file="/opt/shibboleth-idp/conf/tuakiri-attribute-filter.xml" />
$IDP_HOME
is different from /opt/shibboleth-idp
, change the file path in the above snippet accordingly. <ConfigurationResource xsi:type="resource:FileBackedHttpResource"
url="https://directory.tuakiri.ac.nz/attribute-filter/<institution-domain>.xml"
file="/opt/shibboleth-idp/conf/tuakiri-attribute-filter.xml" />
configurationResourcePollingFrequency="PT2H0M0.000S"
and configurationResourcePollingRetryAttempts="10"
attributes to the <srv:Service id="shibboleth.AttributeFilterEngine"
element. If you already have these attributes set for reloading the local configuration file - with a shorter interval, please adjust them accordingly to 2 hours for the remotely loaded attribute filter: <srv:Service id="shibboleth.AttributeFilterEngine"
+ configurationResourcePollingFrequency="PT2H0M0.000S" configurationResourcePollingRetryAttempts="10"
xsi:type="attribute-afp:ShibbolethAttributeFilteringEngine">
For both federations, please note:
- The attribute names used in the download policy file must match the local attribute names. Check that the attribute names in the downloaded attribute filter against their names in existing configuration files:
- attribute-resolver.xml (attribute definitions, match against the ID in the AttributeDefinition element)
- attribute-filter.xml (local attribute filter)
/opt/uApprove/conf/attribute-list
(uApprove attribute list)
- But please note that no attributes need to be renamed with the Federation Registry as of December 2010.
ECP support
To allow your IdP to be used with the ECP profile (access via non-browser clients) to let your users access ECP-enabled services in the federation:
Enable the ECP profile in your
DefaultRelyingParty
configuration (following https://wiki.shibboleth.net/confluence/display/SHIB2/IdPSAML2ECPProfileConfig): check that your/opt/shibboleth-idp/conf/relying-party.xml
contains a definition ofrp:ProfileConfiguration xsi:type="saml:SAML2ECPProfile"
(and add if not present):<rp:ProfileConfiguration xsi:type="saml:SAML2ECPProfile" signAssertions="always" includeAttributeStatement="true"/>
Make sure the ECP handler is enabled: check that
/opt/shibboleth-idp/conf/handler.xml
contains the following (and add if not present):<ph:ProfileHandler xsi:type="ph:SAML2ECP" inboundBinding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" outboundBindingEnumeration="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"> <ph:RequestPath>/SAML2/SOAP/ECP</ph:RequestPath> </ph:ProfileHandler>
Protect the /idp/profile/SAML2/SOAP/ECP location on your IdP with authentication against your LDAP - add the following (customized for your LDAP server) into
/etc/httpd/conf.d/idp.conf
:<Location /idp/profile/SAML2/SOAP/ECP> AuthType Basic AuthName "Example Institution Shibboleth Identity Provider - ECP profile" AuthzLDAPAuthoritative Off AuthBasicProvider ldap AuthLDAPURL ldap://ldap.example.org/ou=People,dc=example,dc=org?uid AuthLDAPBindDN "cn=read,dc=example,dc=org" AuthLDAPBindPassword "password" Require valid-user # enable this only over SSL - not needed when defined in the context of a https VirtualHost SSLRequireSSL </Location>
- Note: the Apache LDAP module cannot handle LDAP referrals. When connecting to an Active Directory server (which typically includes referrals to other domains in the AD forest in the results), you will need to connect to the Global Catalog at port 3268.
- When registering your IdP in the Federation Registry, advertise also the ECP endpoint.
In order for the ECP handler (running as part of the IdP web application inside Tomcat) to receive the REMOTE_USER variable set by Apache, the AJP connector in Tomcat must have the tomcatAuthentication="false"
as instructed above.
ECP will not work if the AJP connector is left with the default settings.
ECP is only included in the IdP in the 2.3.x branch and above
Configuring Single Logout
As of version 2.4.0+, the Shibboleth IdP supports at least a minimalist implementation of Single Log Out (SLO).
The Shibboleth IdP (versions 2.4.0+) supports at least a minimalist SLO implementation: Nonetheless, except for the case where the user has established a session with only one SP where the session (including application-level if used) has been successfully terminated, the only reliable way to close all sessions is to close the browser window. Details on this minimalist implementation are available at https://wiki.shibboleth.net/confluence/display/SHIB2/IdPEnableSLO.
The software side of the SLO implementation comes out of the box on 2.4.0+ installations, however, the following changes must be made.
Step 1: Customize the Logout page. We have a suitable template (logout.jsp) that:
If you enable Single Logout without branding your Logout page, users utilizing the Logout functionality will see an unflattering page saying: "This logout page is an example and should be customized."
- Uses wording we deem suitable for use in the Tuakiri environment.
- Lists services the user has accessed by the ServiceName (from metadata) and the host name (derived from entityId) - instead of just plain displaying the entityId, which would look rather confusing to users.
You still need to further customize the page with:
- Your institution name (replace all occurrences of "Example University")
- Your institution logo (you can reuse the logo you are also using for the IdP login screen - just replace the image link "images/dummylogo.png").
Step 2: If you are reusing IdP configuration files created by a version prior to 2.4.0, you will need to update the configuration files to support the Logout handler in conf/handler.xml
and in the IdP metadata in metadata/idp-metadata.xml
. Refer to the src/installer/resources/conf-tmpl
and src/installer/resources/metadata-tmp
directories in the new version installation tree for up to date configuration files - and copy the respective entries from the templates into your configuration files under /opt/shibboleth-idp
.
Step 3: Register the following additional endpoints as Single Logout Service in your IdP metadata the Federation Registry, with the following bindings names and URL values (substituting your IdP hostname in the URLs):
Binding | URL |
---|---|
urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect | https://idp.example.org/idp/profile/SAML2/Redirect/SLO |
urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST | https://idp.example.org/idp/profile/SAML2/POST/SLO |
urn:oasis:names:tc:SAML:2.0:bindings:SOAP | https://idp.example.org:8443/idp/profile/SAML2/SOAP/SLO |
Customization and Branding
Customizing and branding IdP login screen
In a default install, the IdP login screen is displaying the Shibboleth project logo, a default prompt for username and password, and text saying that this screen should be customized. To establish trust with users, this page should at the very least have the proper institution logo and name and the instructions to customize the page should be removed. Each institution may also wish to customize the graphics to match the style of their login pages. The instructions below show how to change the style of the login screen to match the style of the uApprove screen.
The instructions add a bit of functional logic into the login page - instead of displaying just the entityId of the login page, displaying the full name of the service as configured in the metadata (if available), followed by the hostname of the service.
All of the customization has to be done in the Shibboleth installation directory ($SHIB_INST_HOME
, in particular to src/main/webapp/login.jsp
) - and after any changes, it is necessary to re-deploy the IdP web application (re-run ./install.sh
and restart Tomcat).
For reference, see the Shibboleth Login Page customization instructions at https://wiki.shibboleth.net/confluence/display/SHIB2/IdPAuthUserPassLoginPage.
To customize the login screen with your institutional branding:
- Copy your institution's logo into
$SHIB_INST_HOME/src/main/webapp/images/inst_logo.gif
(change the filename here and later on as suitable)
- Edit
$SHIB_INST_HOME/src/main/webapp/login.jsp
and:- Set head->title to "Institution-name Login" (with your institution name)
- Do the same for the
<h1>
element (and for formatting purposes, demote this to an<h2>
element) - Delete the paragraph saying this is a sample login page
- Change link to the logo image from
/images/logo.jpg
(Shibboleth logo) to/images/inst_logo.gif
(your institution's logo) Nice framing: wrap the whole HTML body in the following DIV element - applying the same style as what the uApprove screen is using:
<div style="width: 650px; margin-left:auto; margin-right:auto; border-style: solid; border-color: #00247D; border-width: 1px; padding: 10px; text-align: left; ">
If suitable, change the phrasing on the login prompt and change the formatting from "
<h2>
" to just plain paragraphs ("<p>
"):<p>You are accessing <strong><%= loginContext.getRelyingPartyId() %></strong></p> <p>Please login with your YOUR-INSTITUTION username and password.</p>
As of Shibboleth IdP 2.3.0 and newer, the default login page now displays not just the service entityID but also the service DisplayName and Description if available in the metadata. This is facilitated through tags from the idpui
tag library, documented at the IdPAuthUserPassLoginPage. However, some of the features used by the default login page (like the service logo) are not available in the metadata produced by the Federation Registry, so we still recommend that you customize this page heavily: remove the left/right frame arrangement, and also display the service hostname (extracted from the entityID.
Add the following code snippet into
login.jsp
to construct the hostname:<!-- Local extension: display the name of the service --> <%! String GetHostnameByURI(String uri) { /* reusing uApprove's Controller.getResourceHost code where I've contributed */ int i1 = uri.indexOf("//"); int i2 = uri.indexOf("/", i1+2); // LOG.debug("uri received = \"" + uri + "\""); // return just the sp.example.org component out of https://sp.example.org/shibboleth if ( i2 >= 0 ) uri = uri.substring(i1 + 2, i2); else if ( i1 >= 0 ) uri = uri.substring(i1 + 2); // return just the sp.example.org component out of urn:mace:federation.org:sp.example.org if (uri.indexOf(':')>=0) { uri = uri.substring(uri.lastIndexOf(':')+1); } //LOG.debug("hostname extracted = \"" + uri + "\""); return uri; } %> <!-- getting relying party full name --> <%@ page import="edu.internet2.middleware.shibboleth.common.relyingparty.RelyingPartyConfigurationManager" %> <%@ page import="edu.internet2.middleware.shibboleth.idp.util.HttpServletHelper" %> <%@ page import="org.opensaml.util.storage.StorageService" %> <%@ page import="edu.internet2.middleware.shibboleth.idp.authn.LoginContext" %> <%@ page import="org.opensaml.saml2.metadata.EntityDescriptor" %> <% StorageService storageService = HttpServletHelper.getStorageService(application); LoginContext loginContext = HttpServletHelper.getLoginContext(storageService,application, request); String hostname = (loginContext != null ? loginContext.getRelyingPartyId() : null); try { if (hostname != null) { hostname = GetHostnameByURI(loginContext.getRelyingPartyId()); }; } catch (Exception e) { /* Intentionally ignored: * Could not get detailed service name, will display basic name only */ }; %>
Note: this snippet uses code from https://wiki.shibboleth.net/confluence/display/SHIB2/IdPAuthUserPassLoginPage as well as code developed for the Tuakiri project.
- Further edits to login.jsp:
- Comment out the
<div class="rightpane">
section with the right panel. Comment out the opening and closing div tags for
loginbox
,leftpane
andcontent
.Replace the prompt "The web site described to the right has asked you to log in..." with:
<p>You are accessing service <strong><idpui:serviceName/><%= (hostname != null ? " at " + hostname : "" ) %></strong><br> <em><idpui:serviceDescription/></em></p> <p>This site has asked you to log in and you have chosen <strong>YOUR-INSTITUTION</strong> as your home institution.<br> Please login with your YOUR-INSTITUTION username and password.</p></p>
- Comment out the
Finally, re-deploy the IdP with:
cd $SHIB_INST_HOME ./install.sh service $TOMCAT_NAME restart
To see a sample implementation of all of the changes described above, please refer to the attached login-jsp-idp230.diff diff file (or see the older version for IdP 2.2.x: login-jsp-idp220.diff).
Customizing and branding uApprove
The uApprove by default displays "blank branding" (a logo placeholder). Customize this your institution - display the institution logo, and possibly adjust the page style to match local branding policies.
The files to customize are in $SHIB_INST_HOME/src/main/webapp/uApprove
. The logo itself (logo.png
) is referenced from attribute-release.jsp
(and terms-of-use.jsp
if used).
Backup the original files:
header.jsp
file:cd $SHIB_INST_HOME/src/main/webapp/uApprove for I in *.jsp *.css ; do cp $I $I.dist ; done
- Copy your institution logo into
$SHIB_INST_HOME/src/main/webapp/uApprove/inst_logo.gif
(adjust filename as suitable)
- Edit
$SHIB_INST_HOME/src/main/webapp/uApprove/attribute-release.jsp
- Replace link to logo placeholder (
logo.png
) with your institution logo (inst_logo.gif
in the above example)
- Replace link to logo placeholder (
Note also that the explanation message given to the user (for why the user is visiting this application) can be customized in messages/attribute-release.properties
inside $SHIB_INST_HOME/lib/uApprove-2.4.1.jar
.
Rebuild the IdP web application to pick up the uApprove changes and restart Tomcat:
cd $SHIB_INST_HOME ./install.sh service $TOMCAT_NAME restart
Friendly attribute names
By default, uApprove would be representing attributes by their local alias - which may not provide the best possible user experience. Names like "eduPersonPrincipalName" look quite cryptic to an ordinary user. The metadata syntax allows to provide friendly names (even locale-specific multiple names) in the attribute-resolver.xml
file, and uApprove will pick the attribute names from there.
The syntax for specifying the attribute names is:
<resolver:AttributeDefinition xsi:type="ad:Simple" id="email" sourceAttributeID="mail"> <resolver:Dependency ref="myLDAP" /> <resolver:DisplayName xml:lang="en">Email address</resolver:DisplayName> <resolver:AttributeEncoder xsi:type="enc:SAML1String" name="urn:mace:dir:attribute-def:mail" /> <resolver:AttributeEncoder xsi:type="enc:SAML2String" name="urn:oid:0.9.2342.19200300.100.1.3" friendlyName="mail" /> </resolver:AttributeDefinition>
Add the following attribute descriptions for the respective attributes into attribute-resolver.xml
, right between the Dependency
and AttributeEncoder
elements:
uid: <resolver:DisplayName xml:lang="en">Local user ID</resolver:DisplayName> email: <resolver:DisplayName xml:lang="en">Email address</resolver:DisplayName> commonName: <resolver:DisplayName xml:lang="en">Common name</resolver:DisplayName> surname: <resolver:DisplayName xml:lang="en">Surname</resolver:DisplayName> givenName: <resolver:DisplayName xml:lang="en">Given name</resolver:DisplayName> eduPersonPrincipalName: <resolver:DisplayName xml:lang="en">Global username (EPPN)</resolver:DisplayName> displayName: <resolver:DisplayName xml:lang="en">Display name</resolver:DisplayName> organizationName: <resolver:DisplayName xml:lang="en">Institution name</resolver:DisplayName> organizationalUnit: <resolver:DisplayName xml:lang="en">Organisational Unit</resolver:DisplayName> homeOrganization: <resolver:DisplayName xml:lang="en">Institution domain</resolver:DisplayName> homeOrganizationType: <resolver:DisplayName xml:lang="en">Institution type</resolver:DisplayName> eduPersonAffiliation: <resolver:DisplayName xml:lang="en">Affiliation type</resolver:DisplayName> eduPersonScopedAffiliation: <resolver:DisplayName xml:lang="en">Affiliation type (with institution)</resolver:DisplayName> eduPersonPrimaryAffiliation: <resolver:DisplayName xml:lang="en">Primary affiliation type</resolver:DisplayName> eduPersonEntitlement: <resolver:DisplayName xml:lang="en">Entitlements</resolver:DisplayName> eduPersonAssurance: <resolver:DisplayName xml:lang="en">Identity assurance level</resolver:DisplayName> eduPersonTargetedID: <resolver:DisplayName xml:lang="en">Targeted ID (opaque per-service username)</resolver:DisplayName> auEduPersonSharedToken: <resolver:DisplayName xml:lang="en">Shared token</resolver:DisplayName> auEduPersonLegalName: <resolver:DisplayName xml:lang="en">Legal name</resolver:DisplayName> auEduPersonAffiliation <resolver:DisplayName xml:lang="en">Affiliation type (Australian extensions)</resolver:DisplayName> postalAddress <resolver:DisplayName xml:lang="en">Business postal address</resolver:DisplayName> telephoneNumber <resolver:DisplayName xml:lang="en">Business phone number</resolver:DisplayName> mobileNumber <resolver:DisplayName xml:lang="en">Mobile phone number</resolver:DisplayName>
Testing
The best way to test an IdP is to try to log into a Service Provider in the federation. Tuakiri provides a service specifically designed for this purpose, the Attribute Validator. The Attribute Validator displays all of the attributes received from the IdP, and in addition to that performs a number of checks to confirm the values are valid. Tuakiri is running an attribute reflector in both Tuakiri-production and Tuakiri-TEST federations. Both reflectors are running as standalone services at URLs listed below and are requesting all attributes available in the federation - hence, they work very well for testing all the attributes released by your IdP.
The attribute reflector URLs are:
- Tuakiri: https://attributes.tuakiri.ac.nz/attributes/
- Tuakiri-TEST: https://attributes.staging.tuakiri.ac.nz/attributes/
An alternative tool for testing IdP is the Attribute Authority Command Line Interface client - aacli.sh
. For a given user TEST_USERNAME
, invoke the tool with:
# For Tuakiri Production environment $SHIB_HOME/bin/aacli.sh --principal $TEST_USERNAME --requester https://attributes.tuakiri.ac.nz/shibboleth # For Tuakiri Staging environment (Test Federation) $SHIB_HOME/bin/aacli.sh --principal $TEST_USERNAME --requester https://attributes.test.tuakiri.ac.nz/shibboleth
- The tool output is the whole set of attributes that would be released for this user to the given user (the Tuakiri Attribute Validator in this case). If testing for another service, pass the entityId of the service in the
--requester
option.
Note that the tool may fail with:
ClassNotFoundException: javax.servlet.ServletRequest
. To remedy this, link the Tomcat servlet.jar library into$SHIB_HOME/lib
(needs to be re-done after each rebuild of the Shibboleth IdP):ln -s /usr/share/java/servlet.jar $SHIB_HOME/lib/