Shibboleth IdP v4 deployment guide

Last Update: 14th June 2023

Introduction

The Shibboleth v4 IdP software was released in March 2020, and earlier versions are now unsupported by the Shibboleth Project, v3 having gone end-of-life at the end of 2020. This page contains general advice about installing and configuring the software, pointers to the Shibboleth project documentation, and some UK federation-specific configuration information. Please contact the UK federation helpdesk for further advice.

Anyone interested in deploying the Shibboleth v4 IdP software should start at the Shibboleth IdP v4 main page and read the system requirements and release notes.

Using the guide

Upgrading from earlier versions

Report your software version to UK federation

When you upgrade your IdP software to v4 from a pre-v4 release, afterwards please contact the UK federation and tell us your new software version. Having accurate software version statistics helps us make decisions about UK federation infrastructure developments.

Upgrading from Shibboleth IdP v3 releases

We have more detailed guidance about upgrading from v3 Shibboleth IdP releases on the UK federation website, including information about upgrading the supporting software. We recommend you read that guidance, and the guidance on the Shibboleth IdP website, and other linked guidance before preparing your upgrade plan and starting work:

Upgrading from Shibboleth IdP v3 releases to the latest v4 release can be summarised as follows:

  1. First check your Shibboleth IdP software version. If you are already running the latest Shibboleth IdP v3 release and you have no deprecation warnings in your IdP log files then go to step 3 in this list; otherwise go to step 2.
  2. If you are running an earlier Shibboleth IdP v3 release you must upgrade to the latest v3 release, and remove all deprecation warnings by making appropriate changes to configuration. When testing verifies that the deprecation warnings have been removed then go to step 3.
  3. Next you need to ensure that your versions of Java and servlet container meet the system requirements for v4. If they do not, you should generally upgrade those before attempting to upgrade the IdP software.
  4. Check your customisations in edit-webapp. There is a high chance that they are not compatible with v4 without changes. The Shibboleth IdP website advises that you may need to port them to or re-validate them on the new version.
  5. Having verified all of the above steps, install the new version on top of your previous installation following the instructions for Windows or for Linux as appropriate.

Upgrading from older Shibboleth IdP releases to v4

If you are running a Shibboleth IdP version earlier than v3 you may be best advised to deploy Shibboleth IdP v4 from scratch on a newly-provisioned platform. See our advice in the document you are currently reading about deploying Shibboleth IdP v4 on Linux or Windows. Special considerations apply with respect to metadata and attribute values when migrating from a functioning in-use older deployment to a new one, so please email the UK federation helpdesk and let us know about your migration plans, and ask for advice as necessary.

Upgrading from earlier v4 releases

Review the Shibboleth IdP v4 upgrade information and install the new version on top of your previous installation following the instructions for Windows or the instructions for Linux as appropriate.

Supported software versions

The supported software platforms and versions are listed on the Shibboleth IdP v4 system requirements page.

Operating systems

You should choose a version of Windows Server or Linux that is fully supported by the operating system vendor.

If deploying on Linux, the Linux version additionally should have a supported Java runtime. Examples are Red Hat Enterprise Linux, and CentOS 7 and 8.

Java

The supported Java versions are listed here.

Java versions 10 and earlier are not usable

Containers

A Java servlet container implementing Servlet API 3.1 is required. The only examples given by the Shibboleth IdP v4 system requirements page are Tomcat 9 or later, Jetty 9.4 and Jetty 10. The recommended servlet container is Jetty 9.4 (information taken on 2022-10-20).

Java versions 10 and earlier, Tomcat 7 and earlier, Jetty 9.3 and earlier, and Jetty 11 and later are not usable.

"Packaged" containers provided by OS vendors are not officially supported by the Shibboleth Project; though in practice we have not encountered issues when using containers packaged with popular Linux versions. However you use them at your own risk, and you might not be able to get support from the Shibboleth Project if you do run into problems.

SAML 1

Warning: please note that SAML 1 is deprecated and should no longer be used.

To the best of our knowledge, all SPs in the UK federation support SAML 2 now; so your IdP should not need to support SAML 1. It requires significant additional configuration which may be avoided in most cases.

If you feel you need to support SAML 1 in your IdP deployment then please contact the UK federation support team for discussion and further guidance.

Firewall rules

  • The Shibboleth IdP software requires TCP port 443 to be open to incoming traffic from all sources at the firewall (assuming use of the recommended standard HTTPS port).
  • The IdP software requires outbound access to TCP port 80 (HTTP) for access to the UK federation metadata
  • The IdP software requires access to an authentication source, which is usually LDAP or Active Directory. If authenticating using LDAP or Active Directory then it will probably require one or more of the following (you can open all of them while configuring and testing, then close all that are not needed)
    • TCP port 389 for LDAP (plaintext and/or startTLS)
    • TCP port 636 for LDAPS (SSL/TLS)
    • TCP port 3268 for LDAP Domain Controller Global Catalogue (plaintext and/or startTLS)
    • TCP port 3269 for LDAPS Domain Controller Global Catalogue (SSL/TLS)

If you need to support the deprecated SAML 1 protocol then you will also need to have TCP port 8443 open to incoming traffic from all sources in order to support the attribute query back channel.

Browser-facing certificate

You will need to acquire an SSL certificate from a certification authority to secure the IdP.

Important: the CN (Common Name) you specify when requesting the certificate must match the DNS hostname aka FQDN of the IdP deployment discussed in the Preparation section.

Please see our guides at these links:

If you plan to proxy the IdP through Apache httpd then you should not need to build a keystore file; the browser-facing certificate is configured in Apache using PEM format certificate files.

Preparation

Before you start you should review this documentation and make your decisions about platform and supporting software.

  • Make any necessary changes to firewall rules as set out in the firewall rules section
  • Acquire a browser-facing certificate according to the advice in the browser-facing certificate section. Create a keystore file as part of this process, unless you plan to proxy through Apache httpd

You will need to have the following information ready:

  • the FQDN a.k.a. DNS hostname of the IdP; this should be something well-chosen and stable, that reflects the function eg. idp.example.ac.uk, and not the physical name of a server that may change, because it will be used to generate the IdP's metadata. Make sure it is set up in the DNS before you start.
  • the scope that your IdP will assert; this is normally your organisation's DNS domain name eg. example.ac.uk. The domain in the scope must verifiably be owned by your organisation and comply with our Metadata Registration Practice Statement.
  • the entityID you plan to use for your IdP. You can usually accept the entityID created by the Shibboleth installer, which it bases on the hostname, but you must check it and make sure it is suitable; you can override its choice at installation time. It must be an https URL based on a domain name verifiably owned by your organisation, and must comply with our entityID policy and our Metadata Registration Practice Statement. It should be concise and descriptive, eg. https://idp.example.ac.uk/idp. It must be unique and not already registered in the UK federation.
  • your LDAP or Active Directory domain name eg. ad.example.ac.uk
  • the username and password of a service account that can be used to access the LDAP or Active Directory; this should not be the account of a real person. The account should have minimal privileges; in Active Directory it should be a member of Domain Guests only, and in the account Properties it should have:
    • 'User cannot change Password' ticked
    • 'Password never expires' ticked
    • 'User must change password at next logon' should be not be ticked
    • Account Expires: Never
  • if using another LDAP directory then the service account should have equivalent properties configured as those described above for Active Directory

Load balancers

Load balancers are generally classified into two categories, layer 4 load balancers and layer 7 load balancers.

In both cases, the load balancer sends and receives internet traffic on HTTPS port 443, but can be configured to route traffic to and from another port on the back-end server nodes, allowing the servlet container software on the server nodes to use an unprivileged port and thus run as an unprivileged user.

If you're upgrading from an earlier release you may need to enable HTML Local Storage which negates the need to share session state between IdP instances.

Layer 4 load balancer

With a layer 4 load balancer, the connection is established between the client and the server, and TLS is not offloaded to the load balancer. This means that the browser-facing certificate configuration on port 443, and all other TLS configuration, must be done at the server, which for us is either the Java servlet container or Apache httpd.

If you are using a layer 4 load balancer with the Shibboleth IdP software then you need to enable session stickiness aka affinity aka persistence at the load balancer to ensure that once a session has been opened with a given node it remains only on that node for the first few HTTP requests. Consult the documentation for your load balancer for information.

Layer 7 load balancer

With a layer 7 load balancer, the load balancer acts as a proxy, and maintains two TCP connections, one with the client and one with the server. TLS is offloaded to the load balancer. This means that the browser-facing certificate on port 443, and all other TLS configuration, must be done at the load balancer.

As with a layer 4 load balancer, you want every session opened to remain only on the node where it was opened for the first few HTTP requests. Layer 7 load balancers have more complex mechanisms for handling this, eg. with cookies. Consult the documentation for your load balancer for information.

Handling X-Forwarded-For headers

With a Layer 7 HTTP load balancer the only IP address that appears in the logs is that of the load balancer. If the proxy sends X-Forwarded-For headers then you can use that to log the client IP addresses; add the appropriate configurations from those below after you have installed and configured your Java servlet container according to subsequent instructions (and Apache httpd if being used).

X-Forwarded-For: Jetty

in jetty.xml within the <New id="httpConfig" ..> section:

 
  <Call name="addCustomizer">
      <Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg>
  </Call>
 

X-Forwarded-For: Tomcat

Replace __TRUSTED_IPs__ with a list of IP addresses:

in server.xml:

 
  <Valve className="org.apache.catalina.valves.RemoteIpValve"
         internalProxies="__TRUSTED_IPs__"
         remoteIpHeader="x-forwarded-for"
         remoteIpProxiesHeader="x-forwarded-by"
         protocolHeader="x-forwarded-proto"
  />

  <Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
         prefix="localhost_access_log" suffix=".txt"
         pattern="%h %l %u %t &quot;%r&quot; %s %b"
         requestAttributesEnabled="true"
  />
 
X-Forwarded-For: Apache httpd

in 0-logformat.conf:

  
  LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""  proxy
 

in port443.conf:

 
  SetEnvIf X-Forwarded-For "^.*\..*\..*\..*" forwarded
  CustomLog logs/proxy_log proxy
 

Also see: https://httpd.apache.org/docs/2.4/mod/mod_remoteip.html#remoteiptrustedproxy

X-Forwarded-For: Shibboleth IdP

It may also be useful to add %a to the standard audit log to include the IP

in conf/audit.xml:

 
  <util:map id="shibboleth.AuditFormattingMap">
      <entry key="Shibboleth-Audit" value="%a|%ST|%T|%u|%SP|%i|%ac|%t|%attr|%n|%f|%SSO|%XX|%XA|%b|%bb|%e|%S|%SS|%s|%UA" />
  </util:map>
 

New Linux deployment

Linux operators deploying from scratch will need to determine whether to use the Tomcat or the Jetty container and follow the instructions here in conjunction with those at the appropriate links in the "Non-Windows Installation" section of the installation page to set up their chosen container and install the software.

This documentation here is being written using the CentOS 7 Linux distribution as the test platform. The Shibboleth IdP installation documentation for Linux is here.

Privileged port 443

The IdP software requires use of the privileged https port 443; this means that Linux deployers need to find a way of handling this without running the Java servlet container as root, which is insecure.

Proxy through load balancer or Apache

If you proxy through a load balancer or through Apache httpd then the servlet container can use an unprivileged port and run as an unprivileged user; and the load balancer or Apache can handle the external traffic to and from port 443. Apache switches to non-root operation at completion of start-up so does not suffer from the same issue.

Other mechanisms

Other possibilities include a setuid mechanism or port forwarding. The Shibboleth wiki provides links to information for Tomcat, Jetty 9.4, and Jetty 10.0.

Apache web server

It is no longer necessary to proxy the Shibboleth IdP through Apache httpd, and has not been since Shibboleth IdP v2.x onwards. However, for various reasons, such as easier certificate management and operation of privileged ports, many deployers prefer to use the Apache httpd web server as a proxy, so we continue to provide some guidance for this, as well as for deployment in a standalone Java servlet container.

Most deployers proxying through Apache prefer to use the Tomcat servlet container, so we focus on the Apache httpd with Tomcat combination here. For those wishing to use Apache httpd in combination with the Jetty container, there is some configuration advice in the Shibboleth wiki.

Apache configuration

You will need to edit the Apache httpd configuration file httpd.conf to configure Apache to pass requests for "/idp/" to the Java servlet container, which we will ensure listens on localhost port 8009. Add this line to the end of the file:

 ProxyPass /idp/ ajp://localhost:8009/idp/
Apache port 443

Apache needs to listen on port 443:

 Listen 443

In the following VirtualHost configuration you configure your IdP server's fully qualified domain name, your browser-facing certificate file, intermediate certificate(s) file and private key file (all in PEM text format), TLS settings, and logging settings.

 <VirtualHost _default_:443>

   ServerName idp.example.ac.uk:443
   SSLEngine on
   SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 -TLSv1.2
   SSLHonorCipherOrder On
   #
   # SSL certificate config
   #
   SSLCertificateFile /opt/shibboleth-idp/credentials/ssl-cert.crt
   SSLCertificateKeyFile /opt/shibboleth-idp/credentials/ssl-cert.key
   SSLCertificateChainFile /opt/shibboleth-idp/credentials/intermediate.pem

   ErrorLog logs/ssl_443_error_log
   TransferLog logs/ssl_443_access_log
   LogLevel warn
   CustomLog logs/ssl_request_log "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

 </VirtualHost>

Important note: the configuration above is informed by, but not identical to, the one recommended at the Mozilla link below for a "modern" configuration at the time of writing. We do not guarantee it represents current good practice at the time you are reading this document. You should research current good practice for TLS settings and adjust the configuration accordingly.

We think that it is better to have SSLHonorCipherOrder On to allow the server to force the client to use the best ciphersuite supported by both client and server.

Tomcat configuration with Apache proxy

Ensure that Tomcat is not listening on any ports except port 8009 by commenting out all <Connector> elements in the Tomcat server.xml file. Modify the port 8009 <Connector> as necessary so it looks like this:

 <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" secretRequired="false" />

The secretRequired setting strictly speaking is only needed when the proxy traverses a network.

Install Java

Using the Linux distribution's package manager (yum, dnf, apt etc) is the most convenient way to manage the available Java.

First check which version is currently installed:

 $ java -version
 openjdk version "1.8.0_262"
 OpenJDK Runtime Environment (build 1.8.0_262-b10)
 OpenJDK 64-Bit Server VM (build 25.262-b10, mixed mode)

If you need to upgrade then find the appropriate package name using the package manager's search function:

  • CentOS / RedHat: yum search openjdk
  • Debian / Ubuntu: apt-cache search openjdk

When you've found the package, install it using the package manager. Below are some examples but check first:

 # CentOS / RedHat 
 yum install -y java-11-openjdk

 # Debian / Ubuntu
 apt-get install -y openjdk-11-jdk

Verify the new version is being used by default:

 $ java -version
 openjdk version "11.0.8" 2020-07-14
 OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1)
 OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu118.04.1, mixed mode, sharing)

If the install process has not enabled it as the default then you will need to use the update-alternatives system to select it:

 update-alternatives --config java

Install Shibboleth

1. Visit https://shibboleth.net/downloads/identity-provider/latest/ and get the URL for the .tar.gz file (currently https://shibboleth.net/downloads/identity-provider/latest/shibboleth-identity-provider-4.2.1.tar.gz)

2. Download the new release to the server:

 cd /usr/local/src
 curl -O https://shibboleth.net/downloads/identity-provider/latest/shibboleth-identity-provider-4.2.1.tar.gz

3. Extract the new release:

    tar xf shibboleth-identity-provider-4.2.1.tar.gz

4. Run the installer for the new release:

 cd shibboleth-identity-provider-4.2.1
   ./bin/install.sh

5. Ensure the correct default responses have been generated for the release location and deployment location (either press ENTER to accept or enter the correct location)

Install and configure Java servlet container

The popular containers are Tomcat and Jetty. The Shibboleth project does not officially support packaged containers; but in practice we have not seen issues with containers packaged with popular Linux versions. However you use them at your own risk. Please see the documentation for your Linux distribution for installation and upgrade documentation if you decide to use a packaged container.

We provide manual installation guidance here for Tomcat and Jetty; you need only one of these; you should choose one based on your requirements and environment.

Jetty installation and configuration

Please see our upgrade documentation for manual Jetty installation information and instructions for deployment of the Shibboleth jetty-base. Instructions are given there for configuration of the browser-facing certificate and the back-channel certificate; please note that the back-channel certificate configuration is not required unless you plan to use the deprecated SAML 1 protocol.

Tomcat installation and configuration

Please see our upgrade documentation for manual Tomcat installation information.

We provide the configuration here for the HTTPS "virtual host" with browser-facing certificate configuration:

 
    <Connector port="443"
               protocol="org.apache.coyote.http11.Http11NioProtocol"
               maxThreads="150"
               SSLEnabled="true"
               scheme="https"
               secure="true"
               keystoreFile="/opt/shibboleth-idp/credentials/idp-browser.p12"
               keystorePass="privatekey"
               keystoreType="PKCS12"
               clientAuth="false"
               honorCipherOrder="true"
               sslProtocol="TLSv1.3" />
  

Important note: the configuration above is informed by, but not identical to, the one recommended at the Mozilla link below for a "modern" configuration at the time of writing. We do not guarantee it represents current good practice at the time you are reading this document. You should research current good practice for TLS settings and adjust the configuration accordingly.

We think that it is better to have SSLHonorCipherOrder On to allow the server to force the client to use the best ciphersuite supported by both client and server.

New Windows deployment

For a new Windows deployment most deployers should use the Windows installer with the packaged "captive" Jetty container, but please read the main Shibboleth IdP installation page and the Shibboleth Windows installation page before making your deployment decisions and starting work on the installation.

We summarise the instructions here.

Install software on Windows

Install Visual C++

Download and install the "Visual C++ redistributable packages for Visual Studio 2015, 2017 and 2019". At the time of writing this is available from this link: https://support.microsoft.com/en-gb/help/2977003/the-latest-supported-visual-c-downloads

You need the file vc_redist.x64.exe (or vc_redist.x86.exe for a 32-bit Windows installation).

Install Java

Download and install a supported version of Java for Windows. At time of writing these are Amazon Corretto versions 11 and 17; download your chosen version from the appropriate link below. Always choose the 64-bit version unless you have a 32-bit Windows installation.

Install Java with the default settings, then locate the path of the Java installation using 'File Explorer', for example C:\Program Files\Amazon Corretto\jdknn.n.n_nn. The path you are looking for will have a bin folder within it.

Install Shibboleth

Download the appropriate MSI package for your system from https://shibboleth.net/downloads/identity-provider/latest4/

Set a JAVA_HOME environmental variable to point to the Java installation path located in the previous section:

  • type environment into the search box and select edit the system environment variables
  • you should be presented with the System Properties Advanced tab. Click Environment Variables
  • on the Environment Variables box under System Variables click New
  • set the variable name to JAVA_HOME and the variable value to the Java installation path

Run the .msi file and enter the information into the "Configure Shibboleth" box as described on the Shibboleth Windows installation page. You should tick the "Install Jetty" and "Configure for Active Directory" boxes to allow it to install a "captive" Jetty container for you, and to partially configure Shibboleth to use Active Directory for user authentication (you will need to complete the configuration yourself, this is described later in this document). Enter the DNS name of the IdP and the scope as described above in Preparation in the appropriate boxes. Check and click "Next".

You will then be presented with a "Configure for Active Directory" box (unless you left the "Configure for Active Directory" box unchecked previously). Enter the Active Directory domain and the username and password of the Active Directory service account as in Preparation in the appropriate boxes.

You may wish to tick 'Use Global Catalog'. The issues around using Standard LDAP vs Global Catalog are documented under LDAP Servers Issues

Check and click "Next" and the installation should then complete.

Configure jetty on Windows

At installation the Windows IdP generates a PKCS12 file for the browser-facing SSL certificate called C:\Program Files(x86)\Shibboleth\IdP\credentials\idp-userfacing.p12. It is configured into Jetty in %{idp-home}/jetty-base/start.d/idp.ini, using the following options. Whilst the default is a PKCS12 type, it can also use a JKS (Java Keystore) type.

 jetty.browser.keystore.path=
 jetty.browser.keystore.password=
 jetty.browser.keystore.type=.    

That keystore file is for test purposes only and not suitable to be used in service, so it needs to be replaced by the keystore file containing the browser-facing certificate/key pair and intermediate certificates; you should have created this keystore file already using one of the methods suggested in the browser-facing certificate? section.

Place your keystore file in the C:\Program Files(x86)\Shibboleth\IdP\credentials folder and make the necessary changes to the options jetty.browser.keystore.path=, jetty.browser.keystore.password=, and jetty.browser.keystore.type= in the %{idp-home}/jetty-base/start.d/idp.ini file.

Important notes for Jetty as part of the Windows installer

  • Do not accidentally adjust the similarly named 'jetty.backchannel.keystore' options; this is not needed for a new deployment
  • You should only need to modify %{idp-home}/jetty-base/start.d/idp.ini, it is not necessary to modify other aspects of the Jetty installation, or configure certificate information elsewhere; and any changes made to other jetty configuration files will be lost in an upgrade

Register IdP in UK federation

Register your IdP metadata after you have installed Shibboleth and before you start to configure it, because it needs to be registered in the UK federation for you to be able to test your configuration as described in the Testing IdP deployments section. You will need the idp-metadata.xml file from the metadata directory.

You should register it as "hidden" in the first instance, so it can't be seen in discovery services and used in error by users who aren't aware that it is not ready for production use. When you are ready to put it into production use, ask the UK federation Helpdesk to make it visible.

See the UK federation Shibboleth IdP registration page.

Testing IdP deployments

After you have configured the browser-facing certificate you should test the security of the TLS/SSL configuration. We suggest you use the SSL Labs SSL Server Test tool for this. You should check the "Do not show the results on the boards" box before you start.

Once you have registered your IdP in the federation, you can test its configuration using this UK federation test service provider:

The index page contains a number of links, which invoke different versions of the Discovery Service. If you click one of these links and select your IdP from the Discovery Service page and successfully authenticate, you should see the UK federation Attribute Viewer, which shows you the attributes released by the IdP to the SP, and some header variables. This allows you to test attribute generation and release as well as simple authentication.

Note that when your IdP is hidden you will need to click the "Search over All sites" link at the bottom of the Discovery Service page, in order to be able to select it. You can start typing in the organisation display name in the box until your IdP is the only one displayed, and select it; or click the "Let me choose from a list" link and find it in the list of all IdPs. The former option is generally preferable, as the list is very long.

It is normally sufficient to test it with the link "Default DS flow with the UK federation CDS". The "Default DS" link uses the federation Discovery Service and should invoke a SAML2 session, which produces a single displayed assertion. We do not expect many SPs to require SAML2 Artifact, but it's advisable to test with that flow too, just in case.

If you are testing a Shibboleth IdP, and you have trouble authenticating or releasing attributes, then ensure your log levels are turned up to DEBUG before re-testing, and check the logs; the idp-process.log is generally the most informative. See the Logging section for more information. If nothing is being written to the Shibboleth logs then check the Tomcat or Jetty logs; it is advisable to keep checking the Tomcat or Jetty logs anyway during the earlier stages of the installation.

You should not attempt to gain access to any live service until you have verified, by the use of the test page noted above, that your IdP is properly configured and releasing attributes correctly.

Important container settings

Ephemeral Diffie-Hellman key size

Ensure you have the Ephemeral Diffie-Hellman key size set to 2048 bits. This is important for TLS security. This can be supplied via the java -D command line flag:

 -Djdk.tls.ephemeralDHKeySize=2048

and can be added in a systemd service file, as in the example jetty.service file in the Jetty deployment instructions in our upgrade documentation.

Increase memory if necessary

We recommend you use the MDQ metadata configuration as recommended in the metadata configuration section. This reduces the resources required by the IdP deployment and the need for future changes to adapt to increasing metadata file sizes.

If you must use the federation aggregate metadata for some reason then you will need to increase maximum Java memory for the application. It's conceivable that you may need to do so even if not. Around 4G is recommended if using the aggregate metadata file; if not then you should not need so much. This can also be supplied via a java -X command line flag in a start-up file:

 -Xmx4000m

or alternatively if using Jetty then in $JETTY_BASE/start.d/idp.ini as described in the Shibboleth Jetty 9.4 documentation or the Shibboleth Jetty 10.0 documentation.

Windows

On Windows you can also change the maximum Java memory allocation using the shibd_idpw.exe utility that is installed with the Shibboleth IdP software. Browse to C:\Program Files (x86)\Shibboleth\ProcRun and double-click shibd_idpw.exe. Select the Java tab. You can edit change the maximum Java memory by editing the value in the Maximum memory pool box.

The ephemeral Diffie-Hellman key size is already set to 2048 bits in shibd_idpw.exe. Please note that the only change made in shibd_idpw.exe that will persist across upgrades is the maximum Java memory allocation.

Shibboleth configuration - Linux and Windows

General guidance

Typically the IdP installation directory is /opt/shibboleth-idp on Linux, or C:\Program Files\Shibboleth\IdP or C:\Program Files (x86)\Shibboleth\IdP on Windows. The installation directory is referred to in configuration files as %{idp.home}, and we refer to it as such here. Configuration files are located in the conf subdirectory of the IdP installation directory, that is to say %{idp.home}/conf.

Take configuration a step at a time; work on a particular configuration task, and test and modify your configuration until you have achieved the desired result. Check the %{idp.home}/logs/idp-process.log and the container logs.

Generally we suggest the following order for configuring the IdP:

Logging

You can get more information by turning the logging level up to DEBUG while you're configuring the IdP. To get details for many of the important processes in the IdP, add the following four properties to %{idp.home}/conf/idp.properties and set them to DEBUG. To change any of them back to default values add a # symbol to the beginning of the line to comment out the property in question (the properties and their default values are declared in the %{idp.home}/conf/logback.xml file).

Note that LDAP logging can be very verbose, so the default level is WARN, and INFO level may be sufficient to troubleshoot LDAP issues.

 # Logging
 # idp.loglevel.idp - log level for the IdP proper - default level INFO
 idp.loglevel.idp=DEBUG
 # idp.loglevel.ldap - log level for LDAP events - default level WARN
 idp.loglevel.ldap=DEBUG
 # idp.loglevel.messages - set to DEBUG for protocol message tracing - default level INFO
 idp.loglevel.messages=DEBUG
 # idp.loglevel.encryption - set to DEBUG to log encrypted content in cleartext - default level INFO
 idp.loglevel.encryption=DEBUG

The IdP writes log messages to the %{idp.home}/logs/idp-process.log file. Reference documentation for logging configuration is available in the Shibboleth IdP v4 wiki.

UK federation metadata configuration

The UK federation metadata is required for the IdP to validate UK federation service providers (SPs), and for the SPs to validate IdPs. It contains SAML metadata for all registered UK federation IdP and SP deployments; and also IdPs and SPs from other federations throughout the world. The UK federation now recommends using Metadata Query (MDQ) in preference to the UK federation metadata aggregate, which has grown very large due to growing UK federation membership; and the import of entities from other federations via eduGAIN interfederation.

We provide configuration information here for both of those options; full details about metadata configuration for the Shibboleth IdP software are provided in the Shibboleth IdP wiki.

You should choose ONE out of the two following metadata configuration options, NOT both.

Metadata Query (MDQ) configuration (recommended)

This is the UK federation MDQ URL:

To secure against compromise, metadata from the UK federation MDQ URL is signed using a private key belonging to the UK federation, and the corresponding public key must be used to verify the signature. Note that a different signing key is used to sign MDQ metadata from that which is used to sign the metadata aggregates. The MDQ public key is available at this URL in the form of a self-signed X509 certificate:

The certificate is required in the IdP configuration so that it can be used to verify the signature on the UK federation metadata. It needs to be downloaded and saved to the %{idp.home/credentials} directory.

However, as this certificate secures the entire UK Federation, you should not rely on it until you have checked its authenticity. To do this, you should verify the certificate's SHA-256 fingerprint. You can use this openssl command to find out the SHA-256 fingerprint of the certificate that you have downloaded:

 openssl x509 -sha256 -fingerprint -noout -in ukfederation-mdq.pem

To verify it you need to compare the resulting value with the correct fingerprint value, which can be obtained from the UK federation team. To guard against the possibility of this web site being compromised, you should contact them by telephone. Their phone number can be found on the UK federation helpdesk contact information page.

Configuration of MDQ in metadata-providers.xml

Having downloaded the UK federation MDQ signing certificate and verified its authenticity as described above, configure the IdP to use the MDQ metadata by adding the following MetadataProvider element to %{idp.home}/conf/metadata-providers.xml. There are comments in the default file distributed with the IdP that describe where this element should be placed.

 
    <!-- UK federation MDQ service -->
    <MetadataProvider id="UKfederationMDQ" xsi:type="DynamicHTTPMetadataProvider">
        <!-- Verify the signature on the root element (i.e., the EntityDescriptor element) -->
        <MetadataFilter xsi:type="SignatureValidation" requireSignedRoot="true"
                certificateFile="%{idp.home}/credentials/ukfederation-mdq.pem" />

        <!-- Require a validUntil XML attribute no more than 30 days into the future -->
        <MetadataFilter xsi:type="RequiredValidUntil" maxValidityInterval="P30D" />

        <!-- The MetadataQueryProtocol element specifies the base URL for the query protocol -->
        <MetadataQueryProtocol>http://mdq.ukfederation.org.uk/</MetadataQueryProtocol>
      </MetadataProvider>
 

Standard metadata aggregate configuration

In case for some reason you cannot use MDQ as above, we provide configuration details here for the standard production UK federation metadata aggregate. It is available at this URL:

To secure against compromise, the UK federation metadata is signed using the UK federation's private key, and the corresponding public key must be used to verify the signature. Note that a different signing key is used to sign the metadata aggregates from that which is used to sign MDQ metadata. The public key for the metadata aggregates is available at this URL in the form of a self-signed X509 certificate:

The certificate is required in the IdP configuration so that it can be used to verify the signature on the UK federation metadata. It needs to be downloaded and saved to the %{idp.home/credentials} directory.

However, as this certificate secures the entire UK Federation, you should not rely on it until you have checked its authenticity. To do this, you should verify the certificate's SHA-256 fingerprint. You can use this openssl command to find out the SHA-256 fingerprint of the certificate that you have downloaded:

 openssl x509 -sha256 -fingerprint -noout -in ukfederation.pem

To verify it you need to compare the resulting value with the correct fingerprint value, which can be obtained from the UK federation team. To guard against the possibility of this web site being compromised, you should contact them by telephone. Their phone number can be found on the UK federation helpdesk contact information page.

Configuration of metadata aggregate in metadata-providers.xml

Having downloaded the UK federation aggregate signing certificate and verified its authenticity as described above, configure the IdP to use the aggregate metadata by editing %{idp.home}/conf/metadata-providers.xml and adding the following MetadataProvider element. There are comments in the default file distributed with the IdP that describe where this element should be placed, and there are two example configuration elements.

 
    <!-- UK federation metadata aggregate -->
    <MetadataProvider id="UKfederationMetadata"
                      xsi:type="FileBackedHTTPMetadataProvider"
                      backingFile="%{idp.home}/metadata/ukfederation-metadata.xml"
                      metadataURL="http://metadata.ukfederation.org.uk/ukfederation-metadata.xml"
                      failFastInitialization="false">

        <MetadataFilter xsi:type="SignatureValidation" requireSignedRoot="true"
                        certificateFile="%{idp.home}/credentials/ukfederation.pem" />
        <MetadataFilter xsi:type="RequiredValidUntil" maxValidityInterval="P30D"/>
        <MetadataFilter xsi:type="SchemaValidation"/>
        <MetadataFilter xsi:type="EntityRole">
            <RetainedRole>md:SPSSODescriptor</RetainedRole>
        </MetadataFilter>
    </MetadataProvider>
 

User authentication

The Shibboleth v4 IdP software natively supports four types of password authentication, being LDAP, JAAS, Kerberos and HTPasswd. For detailed configuration information please see the Shibboleth IdP v4 documentation pages:

Of the above, we expect more UK federation IdP operators to use Active Directory or another LDAP (Lightweight Directory Access Protocol) directory for user authentication and attribute generation, so we focus on that here.

Proxying with Azure Active Directory (AAD) is now a popular choice, and has been simplified by the introduction of a proxying module in Shibboleth IdP v4. This allows you to offload user authentication onto AAD and make use of its MFA (multi-factor authentication) services. We include here configuration guidance for authentication and attribute release with AAD; and for hybrid attribute release using a combination of AAD and Shibboleth's native LDAP support.

Active Directory and other LDAP directories

For detailed configuration information please see the Shibboleth IdP v4 documentation pages:

On Linux, to configure Shibboleth to use LDAP authentication (or one of the other three password login flows) you may need to enable the password authentication module as described in the Shibboleth IdP wiki. The Windows installer does this for you automatically.

You then configure the module in the %{idp.home}/conf/ldap.properties file as described in the Shibboleth IdP wiki and the following sections.

You will also need the CA or server certificate for the LDAP server, the baseDN to search for your users, and to know whether a subtree search is required.

Configuration stages

Active Directory: authentication

If using the Windows installer then some of the configuration in ldap.properties will have been done for you already, but some values are essentially guessed, and you will need to refine it further to fit your real Active Directory configuration. In Active Directory, the variable sAMAccountName is most commonly used to hold the username of someone authenticating at the IdP, so we assume that in the following.

Going through the ldap.properties file in order we look at the properties that you may need to change; any that we do not cover here will usually not need to be changed.

 ## Authenticator strategy, either anonSearchAuthenticator, bindSearchAuthenticator, directAuthenticator, adAuthenticator
 idp.authn.LDAP.authenticator=adAuthenticator

This will normally be adAuthenticator for Active Directory; the Windows Installer with the 'Use Active Directory' box ticked sets this for you.

 idp.authn.LDAP.ldapURL=ldaps://dc0.ad.example.ac.uk:636

This is the URL of your Active Directory server. The Windows installer makes a guess at this based on the Active Directory domain name entered at installation, and it will probably need to be changed. Check whether it is ldaps or ldap, and the hostname and port number, and change as necessary.

 idp.authn.LDAP.useStartTLS                     = false
 idp.authn.LDAP.useSSL                          = true

You should use a secure protocol, either startTLS or SSL, to connect to your Active Directory domain controller using LDAP. Modify the above properties according to which protocol you will use.

 ## SSL configuration, either jvmTrust, certificateTrust, or keyStoreTrust
 idp.authn.LDAP.sslConfig                       = certificateTrust
 ## If using certificateTrust above, set to the trusted certificate's path
 idp.authn.LDAP.trustCertificates=%{idp.home}/credentials/ldap-server.crt
 ## If using keyStoreTrust above, set to the truststore path
 # idp.authn.LDAP.trustStore=%{idp.home}/credentials/ldap-server.truststore

Then configure the public key certificate of the server(s) in %{idp.home}/credentials/ldap-server.crt, or alternatively modify the above configuration to use one of the other trust methods.

The default Active Directory configuration does not have a certificate installed for StartTLS or LDAP over SSL/TLS to be enabled, so many organisations may be using unencrypted LDAP on port 389. This is insecure.

We strongly recommended you configure your Active Directory service to support either StartTLS or SSL/TLS LDAP over SSL/TLS with a Certificate, and configure your Shibboleth IdP accordingly.

 #idp.authn.LDAP.subtreeSearch                   = true
 idp.authn.LDAP.userFilter=(sAMAccountName={user})
 # bind search configuration
 # for AD: idp.authn.LDAP.bindDN=adminuser@domain.com
 idp.authn.LDAP.bindDN=ldap-search@dc0.ad.example.ac.uk

The bindDN account is configured in the idp.authn.LDAP.bindDN property in %{idp.home}/conf/ldap.properties; the password for this account is configured in the %{idp.home}/credentials/secrets.properties file. Note that the bindDN must be in the form adminuser@domain.com when using the adAuthenticator strategy. Uncomment the idp.authn.LDAP.subtreeSearch line if you need subtree searching, and check that sAMAccountName is the correct variable name to hold the authenticating individual's username; if not then change accordingly.

 idp.attribute.resolver.LDAP.searchFilter= (sAMAccountName=$resolutionContext.principal)

Again, check that sAMAccountName is the correct variable name to hold the authenticating individual's username; if not then change accordingly.

Other LDAP directories: authentication

Other LDAP directories tend to have different naming conventions from Active Directory, so a number of the variable names in the configuration will be different from those in the Active Directory examples above. They will probably use the bindSearchAuthenticator strategy and thus require the service account to be specified in a different form.

Therefore, you will need to make similar changes to ldap.properties as set out for Active Directory above, but with some differences:

 ## Authenticator strategy, either anonSearchAuthenticator, bindSearchAuthenticator, directAuthenticator, adAuthenticator
 idp.authn.LDAP.authenticator=bindSearchAuthenticator

Specify bindSearchAuthenticator for the authenticator strategy.

 # Search DN resolution, used by anonSearchAuthenticator, bindSearchAuthenticator
 # for AD: CN=Users,DC=example,DC=org
 idp.authn.LDAP.baseDN=ou=users,DC=ad,DC=example,DC=ac,DC=uk
 #idp.authn.LDAP.subtreeSearch                   = true
 idp.authn.LDAP.userFilter=(uid={user})
 # bind search configuration
 # for AD: idp.authn.LDAP.bindDN=adminuser@domain.com
 idp.authn.LDAP.bindDN=uid=ldap-search,ou=users,dc=ad,dc=example,dc=ac,dc=uk

The bindDN account is configured in the idp.authn.LDAP.bindDN property in %{idp.home}/conf/ldap.properties; the password for this account is configured in the %{idp.home}/credentials/secrets.properties file. Note that the bindDN is in a different form when using the bindSearchAuthenticator strategy from the form used with adAuthenticator. Uncomment the idp.authn.LDAP.subtreeSearch line if you need subtree searching, and check that uid is the correct variable name to hold the authenticating individual's username; if not then change accordingly.

 idp.attribute.resolver.LDAP.searchFilter= (uid=$resolutionContext.principal)

Again, check that uid is the correct variable name to hold the authenticating individual's username; if not then change accordingly.

As with Active Directory, you should always be using a secure protocol to connect to any LDAP directory service.

We strongly recommended you configure your LDAP directory service to support either StartTLS or SSL/TLS LDAP over SSL/TLS with a Certificate, and configure your Shibboleth IdP accordingly.

Active Directory and other LDAP Directories: attribute release

The IdP releases SAML attributes to SPs to provide information about the organisation and user that the IdP represents for a given authentication. Some are privacy-preserving and some are not, so your organisation needs to give consideration to which attributes are released to which SPs. For the UK federation's attribute release recommendations generally, please see section 7 of the UK federation's Technical Recommendations for Participants. There are four attributes that the UK federation regards as "core" attributes: eduPersonScopedAffiliation, eduPersonTargetedID, eduPersonPrincipalName and eduPersonEntitlement. The most commonly used of these are eduPersonScopedAffiliation and eduPersonTargetedID, so we focus on those here.

Each attribute must have a definition in the attribute-resolver.xml file, which gives instructions for generating the attribute value and format; and a filter in the attribute-filter.xml file, which gives instructions on which SPs it can be released to and under which circumstances.

The Attribute Registry service is a new addition to V4 that provides a more advanced way to configure the relationship between the internal IdPAttribute objects that are (for the most part) produced by the Attribute Resolver and the way the data is represented in the protocols supported by software like SAML, CAS, or OpenID.

For the details of this please see the Shibboleth link above; but one consequence of the introduction of the Attribute Registry service is that AttributeEncoder elements are no longer required in attribute definitions in most cases. The documentation here is intended for setting up new deployments so we provide attribute definitions here without AttributeEncoder elements. If you are migrating an older deployment we recommend you update your attribute definitions accordingly; the inclusion of AttributeEncoder elements may resulting in duplicate attribute values being released, which might result in issues with some SPs.

Attribute resolver configuration examples

Details of the Shibboleth IdP attribute resolver configuration are given in the Shibboleth attribute resolver configuration documentation. The attribute resolver configuration specifies how attributes are retrieved or generated on behalf of your users; the conf/attribute-resolver.xml file is used for this.

Some simple attribute definitions follow, with an example LDAP connector and ComputedId connector. These are based on examples in the file %{idp.home}/conf/examples/attribute-resolver-ldap.xml. Your attribute definitions will depend on which attributes are available in your LDAP.

Copy the file %{idp.home}/conf/examples/attribute-resolver-ldap.xml to %{idp.home}/conf/attribute-resolver.xml and use that as a starting point. You will need to make some changes according to your organisation's local set-up.

 <AttributeResolver
        xmlns="urn:mace:shibboleth:2.0:resolver"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver
        http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">

     <AttributeDefinition xsi:type="Scoped" id="eduPersonPrincipalName" scope="%{idp.scope}">
         <InputDataConnector ref="myLDAP" attributeNames="sAMAccountName"/>
     </AttributeDefinition>

     <AttributeDefinition xsi:type="Scoped" id="eduPersonScopedAffiliation" scope="%{idp.scope}">
         <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation"/>
     </AttributeDefinition>

     <AttributeDefinition xsi:type="Scoped" id="samlPairwiseID" scope="%{idp.scope}">
         <InputDataConnector ref="computed" attributeNames="computedId"/>
     </AttributeDefinition>

     <AttributeDefinition xsi:type="Scoped" id="samlSubjectID" scope="%{idp.scope}">
         <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}"/>
     </AttributeDefinition>

     <!-- Deprecated eduPersonTargetedID attribute -->

     <AttributeDefinition xsi:type="SAML2NameID" id="eduPersonTargetedID"
         nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
         <InputDataConnector ref="computed" attributeNames="computedId"/>
         <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
         <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"
                           friendlyName="eduPersonTargetedID"/>
     </AttributeDefinition>

     <!-- Example LDAP DataConnector based on conf/examples/attribute-resolver-ldap.xml -->

     <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
         ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
         baseDN="%{idp.attribute.resolver.LDAP.baseDN}"
         principal="%{idp.attribute.resolver.LDAP.bindDN}"
         principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
         useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
         connectTimeout="%{idp.attribute.resolver.LDAP.connectTimeout}"
         trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"
         responseTimeout="%{idp.attribute.resolver.LDAP.responseTimeout}"
         connectionStrategy="%{idp.attribute.resolver.LDAP.connectionStrategy}"
         noResultIsError="true"
         multipleResultsIsError="true"
         excludeResolutionPhases="c14n/attribute"
         exportAttributes="sAMAccountName eduPersonAffiliation">
         <FilterTemplate>
             <![CDATA[
                 %{idp.attribute.resolver.LDAP.searchFilter}
             ]]>
         </FilterTemplate>
         <ConnectionPool
             minPoolSize="%{idp.pool.LDAP.minSize:3}"
             maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
             blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
             validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
             validateTimerPeriod="%{idp.pool.LDAP.validatePeriod:PT5M}"
             validateDN="%{idp.pool.LDAP.validateDN:}"
             validateFilter="%{idp.pool.LDAP.validateFilter:(objectClass=*)}"
             expirationTime="%{idp.pool.LDAP.idleTime:PT10M}"/>
     </DataConnector>

     <!--
     DataConnector for pairwise-id (example depends in part on saml-nameid.properties).
     Note that this relies on BASE32 encoding in accordance with the attribute definition.
     Older uses of this plugin for legacy eduPersonTargetedID/NameID values may require
     different settings.
     -->

     <DataConnector id="computed" xsi:type="ComputedId"
             excludeResolutionPhases="c14n/attribute"
             generatedAttributeID="computedId"
             salt="%{idp.persistentId.salt}"
             algorithm="%{idp.persistentId.algorithm:SHA}"
             encoding="BASE32">
         <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}" />
     </DataConnector>

 </AttributeResolver>

The example above gives attribute definitions for the SAML attributes eduPersonPrincipalName eduPersonScopedAffiliation, samlPairwiseID, samlSubjectID and eduPersonTargetedID. The attribute definitions depend on the DataConnector with id="myLDAP". If your LDAP connection is secured with SSL or StartTLS then you should not need to make any changes; if it is not secured then you may need to remove or comment out the following lines from the myLDAP DataConnector:

 useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
 trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"

We strongly recommend you configure your LDAP Server to support either StartTLS or SSL/TLS LDAP over SSL/TLS with a Certificate, and re-configure your Shibboleth IdP accordingly.

You will probably need to make changes to the following line:

 exportAttributes="sAMAccountName eduPersonAffiliation">

In our example, the sAMAccountName and eduPersonAffiliation directory attributes are retrieved from the LDAP directory to be used as the basis for building your SAML attributes. You may need to change these, and/or add others to the list, depending on which attributes are stored in your LDAP directory and what your SAML attribute requirements are. sAMAccountName (the username of the authenticating user) is used in this example as a source attribute for the SAML attribute eduPersonPrincipalName. eduPersonAffiliation, a multi-valued directory attribute containing one or more user affiliations, such as (staff, member) or (student, member), is used in this example as a source attribute for the SAML attribute eduPersonScopedAffiliation.

eduPersonScopedAffiliation

Assuming you have a DataConnector configuration with id="myLDAP", and the LDAP has been populated with the eduPersonAffiliation attribute for all your users, then you can use the eduPersonAffiliation attribute as the basis to generate eduPersonScopedAffiliation with the following snippet in attribute-resolver.xml:

 <AttributeDefinition xsi:type="Scoped" id="eduPersonScopedAffiliation" scope="%{idp.scope}">
     <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation"/>
 </AttributeDefinition>

If the LDAP has not been populated with eduPersonAffiliation and it is not possible to arrange for it to be populated then you may need to use an alternative attribute definition for eduPersonAffiliation, based on other attributes or groups in the LDAP directory.

eduPersonTargetedID

This attribute again depends on having a DataConnector configuration to connect to your LDAP. It also requires a ComputedId DataConnector. See the DataConnector with id="computed" in the example above.

You should not need to make any changes to that; but you will need to make some changes to the file saml-nameid.properties. In saml-nameid.properties, set the idp.persistentId.sourceAttribute be the name of a directory attribute suitable for use as a source attribute for eduPersonTargetedID and other persistent SAML attributes. Whichever source attribute is chosen, it should not change over time. Commonly the username is used; in OpenLDAP this is often called uid.

 idp.persistentId.sourceAttribute=uid

In Active Directory, the username is often called sAMAccountName, although this has been known to change during the lifetime of a user's account. Depending on your system, either objectGUID or objectSid could be used.

The objectGUID is binary, so if it is to be used as the source attribute it should be declared as binary by adding this line to the LDAP DataConnector with id="myLDAP":

 <LDAPProperty name="java.naming.ldap.attributes.binary" value="objectGUID"/>

If you use objectSid, you'll need to add a similar element to the LDAP DataConnector.

You also need to set the property idp.persistentId.salt in %{idp.home}/credentials/secrets.properties. It is a random string of at least 16 bytes which you choose. It should be kept secret.

 idp.persistentId.salt=0123456789abcdef

Important: if you are migrating from an earlier deployment you should use the same source attribute and salt value as you used previously, and set idp.persistentId.encoding = BASE64 in saml-nameid.properties, to ensure that the same values are generated for each of your users as were previously. This is necessary to retain access to personalisations saved on SPs that are keyed to eduPersonTargetedID values.

 idp.persistentId.encoding = BASE64

And here then is the configuration snippet in attribute-resolver.xml for eduPersonTargetedID:

 <AttributeDefinition xsi:type="SAML2NameID" id="eduPersonTargetedID"
     nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
     <InputDataConnector ref="computed" attributeNames="computedId"/>
     <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
     <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"
                       friendlyName="eduPersonTargetedID"/>
 </AttributeDefinition>
Attribute filter configuration

Details of the Shibboleth IdP attribute filter configuration are given in the Shibboleth attribute filter configuration documentation. The attribute filter configuration determines which attributes are released to which service providers, and is configured in the conf/attribute-filter.xml file. Most service providers in the UK federation require the attribute eduPersonScopedAffiliation with an affiliation value equivalent to full membership, eg. member, staff or student. The affiliation values released for a given user must be determined on the basis of the user's genuine affiliation with your organisation from your organisation's point of view.

In general the UK federation considers there to be very little personally identifying information carried by either eduPersonScopedAffiliation or eduPersonTargetedID so considers it safe to release them to any SP; the following configuration snippet does just that. However, your organisation should do its own risk analysis in consultation with its data protection officer rather than taking our word for it.

Note that this snippet would release these two attributes to any SP with which the IdP successfully authenticated; this might be a UK federation SP, or an SP imported from another federation via eduGAIN interfederation, or another SP for which the IdP has the metadata configured one way or another. More sophisticated attribute filters are possible; please see the Shibboleth documentation.

This simple example releases eduPersonScopedAffiliation and eduPersonTargetedID to any SP.

 <AttributeFilterPolicyGroup id="ShibbolethFilterPolicy"
        xmlns="urn:mace:shibboleth:2.0:afp"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp
        http://shibboleth.net/schema/idp/shibboleth-afp.xsd">

    <!-- Release eduPersonScopedAffiliation and eduPersonTargetedID attributes to any SP. -->
    <AttributeFilterPolicy id="releaseToAnyone">
        <PolicyRequirementRule xsi:type="ANY" />
        <AttributeRule attributeID="eduPersonScopedAffiliation" permitAny="true" />
        <AttributeRule attributeID="eduPersonTargetedID" permitAny="true" />
    </AttributeFilterPolicy>

 </AttributeFilterPolicyGroup>

Azure Active Directory

For detailed configuration information please see the Shibboleth IdP v4 documentation page:

Please also see this "how-to" guide on the Shibboleth wiki for information about configuring Azure as a user authentication and attribute source. Note that the guide is out of date with respect to changes from Shibboleth IdP v4.1 onwards. In this section we provide advice that incorporates those changes and is up to date as of v4.3.

Configuration stages

We provide here guidance for configuring Azure AD as an authentication source for the Shibboleth IdP, and also as an attribute source. When AAD is the authentication source and the sole attribute source then we refer to it as pass-through proxying.

We also provide guidance for configuring Azure AD as authentication source and (possibly) attribute source in combination with Active Directory (or other LDAP directory) as attribute source; this we refer to as hybrid proxying.

When hybrid proxying we choose a single attribute from AAD which corresponds to (and typically would be synchronised with) an attribute in Active Directory/other LDAP directory. We call this the join attribute; we suggest using user.onpremisessamaccountname as the join attribute, and have done so in the examples here.

If you plan to use Active Directory (or other LDAP directory) as an attribute source then it may be easier to configure the IdP to authenticate and resolve attributes via LDAP first, according to our Active Directory/LDAP configuration guidance, then switch to hybrid proxying using the configuration stages below.

Configure Trust between AAD and Shibboleth IdP

These first three stages involve registering the Shibboleth IdP with Azure AD and providing the Shibboleth IdP and Azure AD with each other's metadata.

Register Shibboleth IdP with AAD
  • Sign into the Azure Active Directory portal
  • Click Azure Active Directory
  • Click Enterprise applications
  • Click New application
  • Click Create your own application
  • Choose the "Integrate any other application you don't find in the gallery (Non-gallery)" radio button
  • Type in a name for your IdP eg. Shibboleth IdP
  • Click Create

You should then see an overview of the application with several options under the "Getting Started" heading.

  • In the "Set up single sign on" option click "Get started"
  • Under the "Select a single sign-on method" heading click SAML
  • Under "Set up Single Sign-On with SAML" click "Edit" in "Basic SAML Configuration"
  • Under "Basic SAML Configuration" click "Add identifier". Copy your Shibboleth IdP entityID into the box and click Add identifier again
  • Still under "Basic SAML Configuration" click "Add reply URL". Paste your IdP's <AssertionConsumerService> URL as created above into the box
  • Click Save
  • Click the cross at top right of the page to exit Basic SAML Configuration, and keep the SAML-based Sign-on page open for the next step
Edit Shibboleth IdP metadata provider configuration

Still in Azure, under "SAML Certificates" next to "Federation Metadata XML" click "Download" to download the Azure IdP metadata. The file will be easier to edit if you use an XML editor to format or "pretty print" the metadata. Edit the metadata file. You can remove some unnecessary elements to reduce the size of the file and make it easier to edit and understand; the unnecessary elements are:

  • the Signature element at the top of the file
  • the Fed:ClaimTypesOffered section

Then make additions as follows:

  • Add this namespace to the EntityDescriptor: xmlns:shibmd="urn:mace:shibboleth:metadata:1.0"
  • Add an <Extensions> block inside the IDPSSODescriptor containing a Scope element with your Shibboleth IdP's scope, eg.
 <Extensions>
   <shibmd:Scope regexp="false">example.ac.uk</shibmd:Scope>
 </Extensions>

Save the file and copy it to to the Shibboleth IdP's %{idp.home}/metadata/ directory; name the file AAD.xml.

Edit the Shibboleth IdP's %{idp.home}/conf/metadata-providers.xml file and add an entry for the Azure IdP metadata, eg:

 <!-- AD.xml - local metadata file for test Azure Active Directory -->  
 <MetadataProvider id="LocalMetadata" xsi:type="FilesystemMetadataProvider"
                   metadataFile="%{idp.home}/metadata/AAD.xml"/>

Note about Azure AD certificates: the Azure AD certificate has a three-year lifetime, meaning that the IdP administrators need to handle Azure AD certificate rollover every three years shortly before the certificate is due to expire to maintain trust between Shibboleth and AAD.

Edit Shibboleth IdP metadata file
  • Edit the %{idp.home}/metadata/idp-metadata.xml file to include an <SPSSODescriptor> block
  • Copy the <KeyDescriptor> elements containing the signing and encryption certificates from the IdP part of the metadata into the <SPSSODescriptor> block
  • Add an <AssertionConsumerService> URL immediately before the closing </SPSSODescriptor> tag of the form https://idp.example.ac.uk/idp/profile/Authn/SAML2/POST/SSO, replacing idp.example.ac.uk with your IdP hostname

Change IdP authentication flow to SAML

In this step we change the IdP's authentication flow to SAML, to enable it to proxy with Azure AD; and provide the IdP with the Azure AD entityID.

  • Edit the Shibboleth IdP's %{idp.home}/conf/authn/authn.properties file
  • change the value of idp.authn.flows to SAML:
 idp.authn.flows=SAML
  • set the value of idp.authn.SAML.proxyEntityID to the AAD IdP entityID as found in the AAD IdP metadata, eg:
 idp.authn.SAML.proxyEntityID=https://sts.windows.net/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx/

Test authentication

At this point users configured in AAD should be able to authenticate with the IdP using AAD as an authentication proxy. Test authentication using the UK federation test SP. You don't expect attributes to be released at this stage, but users should be authenticated and redirected to the test SP page. Make sure this is working before moving on the next section.

Information about testing using the UK federation test SP is in the Testing IdP deployments section.

Configure AAD attribute release to the Shibboleth IdP

As mentioned previously, if all the attributes we wish to release to service providers are stored in AAD then we call it pass-through proxying. If some or all of the attributes we wish to release are stored in Active Directory or other LDAP directory then we call it hybrid proxying. We might combine the two approaches and release attributes from both AAD and Active Directory/other directory.

Pass-through proxy

All attributes originate from Azure AD and must be released to the Shibboleth IdP, which will transform them and release to the SP. Configure attribute release in AAD as follows:

  • In Azure AD click "Enterprise application"
  • Click the name of the enterprise application you created previously, eg. "Shibboleth IdP"
  • Under "Set up single sign on" click "Get started"
  • Click "Edit" on "Attributes & Claims"
  • Configure release of all the attributes you want to release to SPs
Hybrid proxy

One attribute is needed from AAD which can then be used for user lookup in Active Directory/other LDAP directory: the join attribute. We suggest using user.onpremisessamaccountname as the join attribute. However if a combined approach, ie. releasing attributes from both AAD and a directory, is being taken then more attributes may be released from AAD as above. Configure release of the join attribute in AAD as follows:

  • In Azure AD click "Enterprise application"
  • Click the name of the enterprise application you created previously, eg. "Shibboleth IdP"
  • Under "Set up single sign on" click "Get started"
  • Click "Edit" on "Attributes & Claims"
  • Configure release of user.onpremisessamaccountname or other attribute designated as join attribute
Update IdP attribute filter

You need to update the IdP attribute filter to permit attributes to be released by Azure AD to the IdP. Edit %{idp.home}/conf/attribute-filter.xml and add a suitable AttributeFilterPolicy rule. You can base it on this example, setting value to the AAD IdP entityID as found in the AAD IdP metadata:

 <AttributeFilterPolicy id="FilterPolicyObject-Proxy-FromAzure-byIssuer-Type">
    <PolicyRequirementRule xsi:type="Issuer"
        value="https://sts.windows.net/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx/" />

    <AttributeRule attributeID="azureDisplayname" permitAny="true" />
    <AttributeRule attributeID="azureGivenname" permitAny="true" />
    <AttributeRule attributeID="azureSurname" permitAny="true" />
    <AttributeRule attributeID="azureAuthnmethodsreferences" permitAny="true" />
    <AttributeRule attributeID="azureIdentityprovider" permitAny="true" />
    <AttributeRule attributeID="azureTenantid" permitAny="true" />
    <AttributeRule attributeID="azureEmailaddress" permitAny="true" />
    <AttributeRule attributeID="azureObjectidentifier" permitAny="true" />
    <AttributeRule attributeID="azureName">
        <PermitValueRule xsi:type="ScopeMatchesShibMDScope" />
    </AttributeRule>
    <AttributeRule attributeID="azureOnPremisessAMAccountName" permitAny="true" />
 </AttributeFilterPolicy>

You probably don't need all the attributes above, and you may want to use others not listed above. If you plan to base some or all of your SAML attributes for release to service providers on attributes in Azure AD then you will need to include all the Azure AD attributes necessary for that in your attribute filter.

Note that the ScopeMatchesShibMDScope rule above for azureName is based on the assumption that your Azure AD uses the same scope as your Shibboleth IdP. If it does not then you will need to use another rule, such as permitAny="true".

If you plan to base all your SAML attributes for release to service providers on the attributes in Active Directory (or other LDAP directory) then you only need a single attribute from Azure AD to use as the "join" attribute to retrieve attributes from the directory. You can use the example below to do this, based on our recommendation of user.onpremisessamaccountname as the join attribute. Set value to the AAD IdP entityID as found in the AAD IdP metadata.

 <AttributeFilterPolicy id="FilterPolicyObject-Proxy-FromAzure-byIssuer-Type">
    <PolicyRequirementRule xsi:type="Issuer"
        value="https://sts.windows.net/xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxx/" />

    <AttributeRule attributeID="azureOnPremisessAMAccountName" permitAny="true" />
 </AttributeFilterPolicy>
Configure IdP to recognise AAD claims
Add attribute mapping file

Create a file in %{idp.home}/conf/attributes called azureClaims.xml. This file includes all of the attributes from Azure AD that you need to use in the Shibboleth IdP attribute resolver. The example below is not exhaustive. We need to add sAMAccountName to this.

There needs to be a transcoder bean for each attribute that is being retrieved from Azure AD, whether it is to be used just as a join attribute for retrieving attributes from directory, or as the basis of an attribute definition in attribute-resolver.xml.

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"

       default-init-method="initialize"
       default-destroy-method="destroy">

    <bean parent="shibboleth.TranscodingRuleLoader">
    <constructor-arg>
    <list>
        <!-- claims relevant to person record -->
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureOnPremisessAMAccountName</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/samaccountname</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">onPremises sAMAccountName</prop>
                    <prop key="description.en">Azure on-premises sAMAccountName</prop>
                </props>
            </property>
        </bean>
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureName</prop>
                    <prop key="transcoder">SAML2ScopedStringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">Name</prop>
                    <prop key="description.en">Azure UPN of an account expected to be scoped thus transcoded that way</prop>
                </props>
            </property>
        </bean>
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureEmailaddress</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">Mail</prop>
                    <prop key="description.en">Azure emailaddress field of an account</prop>
                </props>
            </property>
        </bean>
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureDisplayname</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.microsoft.com/identity/claims/displayname</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">Mail</prop>
                    <prop key="description.en">Azure displayname field of an account</prop>
                </props>
            </property>
        </bean>
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureGivenname</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">Given name</prop>
                    <prop key="description.en">Azure given name of an account</prop>
                </props>
            </property>
        </bean>
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureSurname</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">Surname</prop>
                    <prop key="description.en">Azure surname of an account</prop>
                </props>
            </property>
        </bean>

        <!-- default claims from Azure for any entity -->
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureTenantid</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.microsoft.com/identity/claims/tenantid</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">Tenant ID</prop>
                    <prop key="description.en">Azure tenantid</prop>
                </props>
            </property>
        </bean>
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureObjectidentifier</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.microsoft.com/identity/claims/objectidentifier</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">Object Identifier</prop>
                    <prop key="description.en">Azure object identifier of an account</prop>
                </props>
            </property>
        </bean>
         <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureIdentityprovider</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.microsoft.com/identity/claims/identityprovider</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">Identity Provider entityid</prop>
                    <prop key="description.en">Azure entityID of the tenant in Azure</prop>
                </props>
            </property>
        </bean>
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureAuthnmethodsreferences</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.microsoft.com/claims/authnmethodsreferences</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">Authnmethodsreferences</prop>
                    <prop key="description.en">Azure authentication method (password, modern auth? etc)</prop>
                </props>
            </property>
        </bean>

    </list>
    </constructor-arg>
    </bean>

 </beans>

If you only plan to release attributes from Active Directory/other LDAP directory then you only need to include the join attribute in the attribute mapping file, for example:

 <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:util="http://www.springframework.org/schema/util"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
                           http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"

       default-init-method="initialize"
       default-destroy-method="destroy">

    <bean parent="shibboleth.TranscodingRuleLoader">
    <constructor-arg>
    <list>
        <!-- claims relevant to person record -->
        <bean parent="shibboleth.TranscodingProperties">
            <property name="properties">
                <props merge="true">
                    <prop key="id">azureOnPremisessAMAccountName</prop>
                    <prop key="transcoder">SAML2StringTranscoder</prop>
                    <prop key="saml2.name">http://schemas.xmlsoap.org/ws/2005/05/identity/claims/samaccountname</prop>
                    <prop key="saml2.nameFormat">urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified</prop>
                    <prop key="displayName.en">onPremises sAMAccountName</prop>
                    <prop key="description.en">Azure on-premises sAMAccountName</prop>
                </props>
            </property>
        </bean>

    </list>
    </constructor-arg>
    </bean>

 </beans>
Add reference to attribute mapping file

Update %{idp.home}/conf/attributes/default-rules.xml to refer to the new attribute mapping file by adding this line after the last import:

 <import resource="azureClaims.xml" />

Release attributes from AAD

Follow the steps in this section to release attributes that are stored in Azure AD.

Update IdP attribute resolver

Add a data connector to %{idp.home}/conf/attribute-resolver.xml to reveal the attributes from Azure AD as follows:

 <DataConnector id="passthroughAttributes" xsi:type="Subject"
     exportAttributes="azureName azureEmailaddress azureDisplayname azureGivenname
         azureSurname azureTenantid azureObjectidentifier azureIdentityprovider
         azureAuthnmethodsreferences" />

You only need to include the attributes stored in Azure AD that you will be releasing to SPs. If you are using a join attribute to retrieve attributes from Active Directory/other LDAP directory then you do not need to include it. If you are only releasing attributes that are stored in Active Directory/other LDAP directory then you do not need the above passthroughAttributes DataConnector at all.

Add attribute definitions as follows. Notice that the value of principalAttributeName will be one of the exported attributes from the above DataConnector:

 <AttributeDefinition xsi:type="SubjectDerivedAttribute"
     forCanonicalization="false"
     id="mail"
     principalAttributeName="azureEmailaddress" />

 <AttributeDefinition xsi:type="SubjectDerivedAttribute"
     forCanonicalization="false"
     id="displayName"
     principalAttributeName="azureDisplayname" />

 <AttributeDefinition xsi:type="SubjectDerivedAttribute"
     id="eduPersonPrincipalName"
     principalAttributeName="azureName" />

Release attributes from directory

Follow the steps in this section to release attributes stored in Active Directory, or other LDAP directory. As has been discussed previously, you need to select an attribute in AAD that corresponds to an attribute in the LDAP directory and acts as a username to use as your join attribute. We are using user.onpremisessamaccountname as the "join" attribute in our examples here.

Configure join attribute and subject canonicalisation

To configure the join attribute, edit %{idp.home}/conf/c14n/subject-c14n.properties, putting the attribute being used for join in the idp.c14n.attribute.attributeSourceIds property, eg.

 idp.c14n.attribute.attributeSourceIds = azureOnPremisessAMAccountName
 # Allows direct use of attributes via SAML proxy authn, bypasses resolver
 idp.c14n.attribute.resolveFromSubject = true
 idp.c14n.attribute.resolutionCondition = shibboleth.Conditions.FALSE

We need to perform subject canonicalisation on the "join" attribute. Edit %{idp.home}/conf/c14n/subject-c14n.xml and uncomment this bean:

      <!-- Remove comment tags to enable Attribute-based c14n -->
      <bean id="c14n/attribute" parent="shibboleth.PostLoginSubjectCanonicalizationFlow" />
Update IdP attribute resolver

To configure attribute resolution for attributes stored in Active Directory/other LDAP directory, please refer to our Active Directory and other LDAP directories section. You will need to configure authentication and attribute release as described in that section.

Update IdP attribute filter

To configure attribute filtering, ie. to determine which attributes are released to which SPs, please refer to our Active Directory and other LDAP directories attribute filter configuration section, for which configuration is the same.

Attribute release configuration

The IdP releases SAML attributes to SPs to provide information about the organisation and user that the IdP represents for a given authentication. Some are privacy-preserving and some are not, so your organisation needs to give consideration to which attributes are released to which SPs. For the UK federation's attribute release recommendations generally, please see section 7 of the UK federation's Technical Recommendations for Participants. There are four attributes that the UK federation regards as "core" attributes: eduPersonScopedAffiliation, eduPersonTargetedID, eduPersonPrincipalName and eduPersonEntitlement. The most commonly used of these are eduPersonScopedAffiliation and eduPersonTargetedID, so we focus on those here.

Each attribute must have a definition in the attribute-resolver.xml file, which gives instructions for generating the attribute value and format; and a filter in the attribute-filter.xml file, which gives instructions on which SPs it can be released to and under which circumstances.

Attribute resolver configuration

Details of the Shibboleth IdP attribute resolver configuration are given in the Shibboleth attribute resolver configuration documentation. The attribute resolver configuration specifies how attributes are retrieved or generated on behalf of your users; the conf/attribute-resolver.xml file is used for this.

Many organisations will be using Active Directory/LDAP for authentication and attribute retrieval, so we focus on that here. Some simple attribute definitions follow, with an example LDAP connector and ComputedId connector. These are based on examples in the file %{idp.home}/conf/examples/attribute-resolver-ldap.xml. Your attribute definitions will depend on which attributes are available in your LDAP.

Copy the file %{idp.home}/conf/examples/attribute-resolver-ldap.xml to %{idp.home}/conf/attribute-resolver.xml and use that as a starting point. You will need to make some changes according to your organisation's local set-up.

 <AttributeResolver
        xmlns="urn:mace:shibboleth:2.0:resolver"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:mace:shibboleth:2.0:resolver
        http://shibboleth.net/schema/idp/shibboleth-attribute-resolver.xsd">

     <AttributeDefinition xsi:type="Scoped" id="eduPersonPrincipalName" scope="%{idp.scope}">
         <InputDataConnector ref="myLDAP" attributeNames="sAMAccountName"/>
     </AttributeDefinition>

     <AttributeDefinition xsi:type="Scoped" id="eduPersonScopedAffiliation" scope="%{idp.scope}">
         <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation"/>
     </AttributeDefinition>

     <AttributeDefinition xsi:type="Scoped" id="samlPairwiseID" scope="%{idp.scope}">
         <InputDataConnector ref="computed" attributeNames="computedId"/>
     </AttributeDefinition>

     <!-- Deprecated eduPersonTargetedID attribute -->

     <AttributeDefinition xsi:type="SAML2NameID" id="eduPersonTargetedID"
         nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
         <InputDataConnector ref="computed" attributeNames="computedId"/>
         <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
         <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"
                           friendlyName="eduPersonTargetedID"/>
     </AttributeDefinition>

     <!-- Example LDAP DataConnector based on conf/examples/attribute-resolver-ldap.xml -->

     <DataConnector id="myLDAP" xsi:type="LDAPDirectory"
         ldapURL="%{idp.attribute.resolver.LDAP.ldapURL}"
         baseDN="%{idp.attribute.resolver.LDAP.baseDN}"
         principal="%{idp.attribute.resolver.LDAP.bindDN}"
         principalCredential="%{idp.attribute.resolver.LDAP.bindDNCredential}"
         useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
         connectTimeout="%{idp.attribute.resolver.LDAP.connectTimeout}"
         trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"
         responseTimeout="%{idp.attribute.resolver.LDAP.responseTimeout}"
         connectionStrategy="%{idp.attribute.resolver.LDAP.connectionStrategy}"
         noResultIsError="true"
         multipleResultsIsError="true"
         excludeResolutionPhases="c14n/attribute"
         exportAttributes="sAMAccountName eduPersonAffiliation">
         <FilterTemplate>
             <![CDATA[
                 %{idp.attribute.resolver.LDAP.searchFilter}
             ]]>
         </FilterTemplate>
         <ConnectionPool
             minPoolSize="%{idp.pool.LDAP.minSize:3}"
             maxPoolSize="%{idp.pool.LDAP.maxSize:10}"
             blockWaitTime="%{idp.pool.LDAP.blockWaitTime:PT3S}"
             validatePeriodically="%{idp.pool.LDAP.validatePeriodically:true}"
             validateTimerPeriod="%{idp.pool.LDAP.validatePeriod:PT5M}"
             validateDN="%{idp.pool.LDAP.validateDN:}"
             validateFilter="%{idp.pool.LDAP.validateFilter:(objectClass=*)}"
             expirationTime="%{idp.pool.LDAP.idleTime:PT10M}"/>
     </DataConnector>

     <!--
     DataConnector for pairwise-id (example depends in part on saml-nameid.properties).
     Note that this relies on BASE32 encoding in accordance with the attribute definition.
     Older uses of this plugin for legacy eduPersonTargetedID/NameID values may require
     different settings.
     -->

     <DataConnector id="computed" xsi:type="ComputedId"
             excludeResolutionPhases="c14n/attribute"
             generatedAttributeID="computedId"
             salt="%{idp.persistentId.salt}"
             algorithm="%{idp.persistentId.algorithm:SHA}"
             encoding="BASE32">
         <InputDataConnector ref="myLDAP" attributeNames="%{idp.persistentId.sourceAttribute}" />
     </DataConnector>

 </AttributeResolver>

The example above gives attribute definitions for the SAML attributes eduPersonPrincipalName eduPersonScopedAffiliation, samlPairwiseID, and eduPersonTargetedID. The attribute definitions depend on the DataConnector with id="myLDAP". If your LDAP connection is secured with SSL or StartTLS then you should not need to make any changes; if it is not secured then you may need to remove or comment out the following lines from the myLDAP DataConnector:

 useStartTLS="%{idp.attribute.resolver.LDAP.useStartTLS:true}"
 trustFile="%{idp.attribute.resolver.LDAP.trustCertificates}"

We strongly recommend you configure your LDAP Server to support either StartTLS or SSL/TLS LDAP over SSL/TLS with a Certificate, and re-configure your Shibboleth IdP accordingly.

You will probably need to make changes to the following line:

 exportAttributes="sAMAccountName eduPersonAffiliation">

In our example, the sAMAccountName and eduPersonAffiliation directory attributes are retrieved from the LDAP directory to be used as the basis for building your SAML attributes. You may need to change these, and/or add others to the list, depending on which attributes are stored in your LDAP directory and what your SAML attribute requirements are. sAMAccountName (the username of the authenticating user) is used in this example as a source attribute for the SAML attribute eduPersonPrincipalName. eduPersonAffiliation, a multi-valued directory attribute containing one or more user affiliations, such as (staff, member) or (student, member), is used in this example as a source attribute for the SAML attribute eduPersonScopedAffiliation.

eduPersonScopedAffiliation

Assuming you have a DataConnector configuration with id="myLDAP", and the LDAP has been populated with the eduPersonAffiliation attribute for all your users, then you can use the eduPersonAffiliation attribute as the basis to generate eduPersonScopedAffiliation with the following snippet in attribute-resolver.xml:

 <AttributeDefinition xsi:type="Scoped" id="eduPersonScopedAffiliation" scope="%{idp.scope}">
     <InputDataConnector ref="myLDAP" attributeNames="eduPersonAffiliation"/>
 </AttributeDefinition>

If the LDAP has not been populated with eduPersonAffiliation and it is not possible to arrange for it to be populated then you may need to use an alternative attribute definition for eduPersonAffiliation, based on other attributes or groups in the LDAP directory.

eduPersonTargetedID

This attribute again depends on having a DataConnector configuration to connect to your LDAP. It also requires a ComputedId DataConnector. See the DataConnector with id="computed" in the example above.

You should not need to make any changes to that; but you will need to make some changes to the file saml-nameid.properties. In saml-nameid.properties, set the idp.persistentId.sourceAttribute be the name of a directory attribute suitable for use as a source attribute for eduPersonTargetedID and other persistent SAML attributes. Whichever source attribute is chosen, it should not change over time. Commonly the username is used; in OpenLDAP this is often called uid.

 idp.persistentId.sourceAttribute=uid

In Active Directory, the username is often called sAMAccountName, although this has been known to change during the lifetime of a user's account. Depending on your system, either objectGUID or objectSid could be used.

The objectGUID is binary, so if it is to be used as the source attribute it should be declared as binary by adding this line to the LDAP DataConnector with id="myLDAP":

 <LDAPProperty name="java.naming.ldap.attributes.binary" value="objectGUID"/>

If you use objectSid, you'll need to add a similar element to the LDAP DataConnector.

You also need to set the property idp.persistentId.salt in %{idp.home}/credentials/secrets.properties. It is a random string of at least 16 bytes which you choose. It should be kept secret.

 idp.persistentId.salt=0123456789abcdef

Important: if you are migrating from an earlier deployment you should use the same source attribute and salt value as you used previously, and set idp.persistentId.encoding = BASE64 in saml-nameid.properties, to ensure that the same values are generated for each of your users as were previously. This is necessary to retain access to personalisations saved on SPs that are keyed to eduPersonTargetedID values.

 idp.persistentId.encoding = BASE64

And here then is the configuration snippet in attribute-resolver.xml for eduPersonTargetedID:

 <AttributeDefinition xsi:type="SAML2NameID" id="eduPersonTargetedID"
     nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">
     <InputDataConnector ref="computed" attributeNames="computedId"/>
     <AttributeEncoder xsi:type="SAML1XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"/>
     <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"
                       friendlyName="eduPersonTargetedID"/>
 </AttributeDefinition>

Attribute filter configuration

Details of the Shibboleth IdP attribute filter configuration are given in the Shibboleth attribute filter configuration documentation. The attribute filter configuration determines which attributes are released to which service providers, and is configured in the conf/attribute-filter.xml file. Most service providers in the UK federation require the attribute eduPersonScopedAffiliation with an affiliation value equivalent to full membership, eg. member, staff or student. The affiliation values released for a given user must be determined on the basis of the user's genuine affiliation with your organisation from your organisation's point of view.

In general the UK federation considers there to be very little personally identifying information carried by either eduPersonScopedAffiliation or eduPersonTargetedID so considers it safe to release them to any SP; the following configuration snippet does just that. However, your organisation should do its own risk analysis in consultation with its data protection officer rather than taking our word for it.

Note that this snippet would release these two attributes to any SP with which the IdP successfully authenticated; this might be a UK federation SP, or an SP imported from another federation via eduGAIN interfederation, or another SP for which the IdP has the metadata configured one way or another. More sophisticated attribute filters are possible; please see the Shibboleth documentation.

This simple example releases to any SP.

 <AttributeFilterPolicyGroup id="ShibbolethFilterPolicy"
        xmlns="urn:mace:shibboleth:2.0:afp"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="urn:mace:shibboleth:2.0:afp
        http://shibboleth.net/schema/idp/shibboleth-afp.xsd">

    <!-- Release eduPersonScopedAffiliation and eduPersonTargetedID attributes to any SP. -->
    <AttributeFilterPolicy id="releaseToAnyone">
        <PolicyRequirementRule xsi:type="ANY" />
        <AttributeRule attributeID="eduPersonScopedAffiliation" permitAny="true" />
        <AttributeRule attributeID="eduPersonTargetedID" permitAny="true" />
    </AttributeFilterPolicy>

 </AttributeFilterPolicyGroup>

Customise login page

We give here details for a basic configuration that should be suitable for most organisations.

 idp.title = Example College Login
 idp.url.helpdesk = https://www.example.ac.uk/it/helpdesk
 idp.url.password.reset = https://www.example.ac.uk/it/password
 idp.logo = /images/examplelogo.jpg
 idp.logo.alt-text = Example College Logo
 idp.footer = &copy; Example College
 idp.css = /css/examplecss.css
  • If you have installed the Shibboleth IdP software on Windows using the Windows .msi installer then you can place an image file with an appropriate logo for your organisation in the %{idp-home}/static folder and configure the filename as the value of idp.logo as in the example below, and you don't need to rebuild the war file. You can also configure it as above using %{idp-home}/edit-webapp/images and rebuild the war file etc.
 idp.logo = ../../examplelogo.jpg
  • Again, if you have installed the Shibboleth IdP software on Windows using the Windows .msi installer then you can place your stylesheet file in the %{idp-home}/static folder and configure the filename as the value of idp.css as in the example below, and you don't need to rebuild the war file. You can also configure it as above using %{idp-home}/edit-webapp/images and rebuild the war file etc.
 idp.css = ../../examplecss.css

Depending on your container and possible Apache proxy or load balancer, the images and css directories may be publicly visible at the https://hostname/idp/images/ and https://hostname/idp/css/. Hide them by placing an empty index.html file in %{idp-home}/edit-webapp/images and %{idp-home}/edit-webapp/css and rebuild the war file according to the instructions on the Shibboleth IdP documentation pages

Your organisation may require a more sophisticated configuration. Please see the Shibboleth IdP user interface configuration documentation for more details of the possibilities available. Files that may need to be modified are messages/error-messages.properties, views/login.vm, and views/login-error.vm.

Get ready for production

At this point you should review your set-up for security and reliability issues.

One known potential issue is cookie security. Check your idp.properties file for idp.cookie.secure to ensure cookies are not sent over insecure connections:

 idp.cookie.secure=true

If the line has a # at the start then it's commented out so takes the default. In version 4, the default is true; in previous versions the default was false.

The Shibboleth wiki has some topics to consider when putting the IdP into production

Other recommendations:

  • test TLS/SSL security (see Testing section)
  • test failover if load-balanced
  • test with different user types and check the correct attribute values are released (see Testing section)
  • check logging is correctly configured and working, and set up log rotations as required
  • configure and test back-ups
  • subscribe to the shibboleth-announce mailing list to receive important announcements about security fixes and new releases.