i2b2 now includes support for SAML-based enterprise authentication via an institutional Identity Provider. This guide walks through the webclient, user, and server configuration. This should be done after both server and client install.
This guide uses sp.example.org as the domain name. Please replace sp.example.org with your domain name.
Prerequisites
The following applications and services must be already setup and running:
i2b2 core server 1.7.13 release
i2b2 web client release 1.7.13 (using the Apache web server)
i2b2 database
We recommend all software frameworks are updated to the latest supported version:
Requirements
Administrative privileges.
The specific commands for installing packages are for CentOS 7. Commands might be slightly different in other versions and flavors of Linux.
It is generally best practice to update the operating system to get the latest security patches and software updates before installing any new software.
Execute the following command to update the operating system:
sudo yum -y update
Restart the server for the changes to apply.
Please visit Extra Packages for Enterprise Linux for more information.
Execute the following command to install additional open source packages:
sudo yum -y install epel-release
Run update again to pull the packages:
sudo yum -y update
Add Shibboleth repository:
sudo wget <http://download.opensuse.org/repositories/security://shibboleth/CentOS_7/security:shibboleth.repo> \
-P /etc/yum.repos.d
Update the repository:
sudo yum -y update
Install Shibboleth:
sudo yum -y install shibboleth
Enable Shibboleth and restart Apache HTTP server:
sudo systemctl enable shibd
sudo systemctl start shibd
sudo systemctl restart httpd
Verify that Shibboleth has been properly installed.
sudo shibd -t
You should see output response that ends with overall configuration is loadable, check console or log for non-fatal problems
sudo apachectl configtest
You should see the output Syntax OK.
Open up a web browser and navigate to https://sp.example.org/Shibboleth.sso/Session
Note: replace sp.example.org with your domain name.
You should see the message A valid session was not found. in your browser.
Modify the shib.conf located in the directory /etc/httpd/conf.d.
Delete the following configuration:
<Location /secure>
AuthType shibboleth
ShibRequestSetting requireSession 1
require shib-session
</Location>
Add the following configuration:
<Location />
AuthType shibboleth
ShibRequestSetting requireSession 0
require shibboleth
</Location>
Your institution should provide you the IdP metadata to register your application or service with their Identity Provider (IdP). For an example, the Harvard University Information Technology (HUIT) provides a guide and files to register with their IdP: https://iam.harvard.edu/resources/saml-shibboleth-integration.
Modify the /etc/shibboleth/shibboleth2.xml file.
Modify the attributes of the ApplicationDefaults element as follows:
<!-- The ApplicationDefaults element is where most of Shibboleth's SAML bits are defined. -->
<ApplicationDefaults entityID="<https://sp.example.org/shibboleth">
REMOTE_USER="eduPersonPrincipalName,eppn"
cipherSuites="DEFAULT:!EXP:!LOW:!aNULL:!eNULL:!DES:!IDEA:!SEED:!RC4:!3DES:!kRSA:!SSLv2:!SSLv3:!TLSv1:!TLSv1.1"
signing="true"
attributePrefix="AJP_">
Remember to replace sp.example.org with your domain name.
Modify the <SSO> tag as follow:
<SSO entityID="<https://example.org/saml2/idp/metadata.php>">
SAML2
</SSO>
Remember to replace https://example.org/saml2/idp/metadata.php with your IdP entity.
Replace the following:
<!-- Extension service that generates "approximate" metadata based on SP configuration. -->
<Handler type="MetadataGenerator" Location="/Metadata" signing="true"/>
<!-- Session diagnostic service. -->
<Handler type="Session" Location="/Session" showAttributeValues="true"/>
The IdP metadata file should be placed in the directory /etc/shibboleth. In this example, the IdP metadata file is /etc/shibboleth/federation-metadata.xml.
Add the following:
<!-- Example of locally maintained metadata. -->
<MetadataProvider type="XML" validate="true" path="federation-metadata.xml"/>
Remember to replace federation-metadata.xml with the name of your IdP metadata file located in the directory /etc/shibboleth.
The attribute-map.xml, located in the directory /etc/shibboleth, contains the names of the SAML 2.0 attributes that can be mapped to the IdP attributes.
Add the following attribute mapping to the file /etc/shibboleth/attribute-map.xml.
<Attribute name="uid" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" id="uid"/>
<Attribute name="eduPersonPrincipalName" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" id="eduPersonPrincipalName"/>
<Attribute name="eduPersonAffiliation" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" id="eduPersonAffiliation"/>
<Attribute name="mail" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" id="mail"/>
<Attribute name="displayName" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" id="displayName"/>
<Attribute name="givenName" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" id="givenName"/>
<Attribute name="sn" nameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic" id="sn"/>
Note that your IdP attributes may be different. Please change the attribute name to the correct IdP attribute name. Do NOT change the id attribute.
Open up a web browser and navigate to https://sp.example.org/Shibboleth.sso/Metadata. You should see a dialog for opening the metadata file Metadata. Instead of opening it up, download it onto your computer.
You can rename the file Metadata to Metadata.xml for readability.
The metadata file contains information about the Service Provider (SP) including the entity ID and the public certificates for signing and encryption. Regisiter this file with your Identity Provider (IdP).
Note that the signing certificate and encryption certificate included in the metadata file are from /etc/shibboleth/sp-signing-cert.pem and /etc/shibboleth/sp-encrypt-cert.pem, respectively. If you want to use your own certificates, just replace them along with the private keys and regenerate the metadata.
With the latest version of i2b2, the request to the Hive is no longer made directly to Wilfly. Instead, the request is made to the Apache HTTP server and then gets proxied over to Wildfly via AJP.
AJP is a trusted protocol and should never be exposed to untrusted clients. The communication between the clients is insecure (data is sent in clear text) and assumes that your network is safe. The configuration below will prevent AJP from being exposed.
Create a secret key to used by the Apache HTTP server and Wildfly. You can generate a random key here https://randomkeygen.com/ .
For the purpose of this guide, we will use 5F6C696F56D37BCFD1296C3E33A11 as the secret key.
Modify the file httpd.conf located in the directory /etc/httpd/conf/ to restrict Apache to listen to port 80 only to IP 127.0.0.1 (localhost):
# Listen 80
Listen 127.0.0.1:80
Create a file named ajp.conf in the directory /etc/httpd/conf.d/ with the following content, depending on what version of CentOS or Apache you are running:
CentOS 6 / Apache 2.0 | CentOS 7 / Apache 2.2 (recommended) | CentOS 8 |
---|---|---|
|
| Not Supported |
Remember to replace the secret key 5F6C696F56D37BCFD1296C3E33A11 with your own.
Modify the file standalone.xml in the directory /opt/wildfly/standalone/configuration to enable AJP:
Ensure that AJP port is enable and set to 8009:
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
...
...
<socket-binding name="ajp" port="${jboss.ajp.port:8009}"/>
...
...
</socket-binding-group>
Set AJP listener and secret key:
<subsystem xmlns="urn:jboss:domain:undertow:9.0" default-server="default-server" default-virtual-host="default-host" default-servlet-container="default" default-security-domain="other" statistics-enabled="${wildfly.undertow.statistics-enabled:${wildfly.statistics-enabled:false}}">
<buffer-cache name="default"/>
<server name="default-server">
<ajp-listener name="ajp" socket-binding="ajp" max-post-size="10485760000" scheme="http"/>
...
...
<host name="default-host" alias="localhost">
...
<filter-ref name="secret-checker" predicate="equals(%p, 8009)"/>
...
</host>
</server>
...
...
<filters>
<expression-filter name="secret-checker" expression="not equals(%{r,secret}, '5F6C696F56D37BCFD1296C3E33A11') -> response-code(403)"/>
</filters>
</subsystem>
Remember to replace the secret key 5F6C696F56D37BCFD1296C3E33A11 with your own.
Execute the command below to restart Apache HTTP server and Wildfly:
sudo systemctl restart wildfly.service
sudo systemctl restart httpd.service
Stop Wildfly:
systemctl stop wildfly.service
Download the latest i2b2 core server from Github: https://github.com/i2b2/i2b2-core-server
Configure, compile, and install the latest version. For more information, please see the installation guide
Start Wildfly:
systemctl start wildfly.service
Modify the i2b2_config_data.js file located in the directory /var/www/html/webclient/ as needed. In particular, you will want a domain entry with loginType = "federated" (see 1.4.2 Domain Configuration) and you will want to update the URL to begin with 127.0.0.1 (to use the AJP proxy to the Hive).
{
urlProxy: "index.php",
urlFramework: "js-i2b2/",
startZoomed: true,
lstDomains": [
{
domain: "i2b2demo",
name: "HarvardDemo SAML",
allowAnalysis: true,
urlCellPM: "http://127.0.0.1/i2b2/services/PMService/",
registrationMethod: "saml",
loginType: "federated",
showRegistration: true,
installer: "/webclient/plugin_installer/",
debug: true
},
{
domain: "i2b2demo",
name: "HarvardDemo",
allowAnalysis: true,
urlCellPM: "http://127.0.0.1:9090/i2b2/services/PMService/",
registrationMethod: "",
loginType: "local",
showRegistration: false,
debug: true
}
]
}
Optionally, you can follow these directions to customize the SAML IdP login button:
i2b2 SAML: Customize Identity Provider (IdP) Login Button
Restart the Apache web server:systemctl restart httpd.service
Run the following SQL queries to update the pm_cell_data table. This will change your URL to begin with 127.0.0.1, which will use the AJP proxy. Note that your specific URL could be different depending on configuration.
UPDATE pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/QueryToolService/'> WHERE cell_id = 'CRC';
UPDATE pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/FRService/'> WHERE cell_id = 'FRC';
UPDATE pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/OntologyService/'> WHERE cell_id = 'ONT';
UPDATE pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/WorkplaceService/'> WHERE cell_id = 'WORK';
UPDATE pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/IMService/'> WHERE cell_id = 'IM';
UPDATE i2b2pm.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/QueryToolService/'> WHERE cell_id = 'CRC';
UPDATE i2b2pm.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/FRService/'> WHERE cell_id = 'FRC';
UPDATE i2b2pm.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/OntologyService/'> WHERE cell_id = 'ONT';
UPDATE i2b2pm.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/WorkplaceService/'> WHERE cell_id = 'WORK';
UPDATE i2b2pm.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/IMService/'> WHERE cell_id = 'IM';
UPDATE i2b2pm.dbo.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/QueryToolService/'> WHERE cell_id = 'CRC';
UPDATE i2b2pm.dbo.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/FRService/'> WHERE cell_id = 'FRC';
UPDATE i2b2pm.dbo.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/OntologyService/'> WHERE cell_id = 'ONT';
UPDATE i2b2pm.dbo.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/WorkplaceService/'> WHERE cell_id = 'WORK';
UPDATE i2b2pm.dbo.pm_cell_data SET url = '<http://127.0.0.1/i2b2/services/IMService/'> WHERE cell_id = 'IM';
Note that your database schema may be different.
Note: The original version of the setup guide is here: https://github.com/kvb2univpitt/i2b2-saml-demo/tree/main/doc/saml_setup