PIV-I Identity Provider

From NIEF Wiki
Jump to navigation Jump to search

This guide describes how to implement a NIEF SAML Identity Provider (IDP) system that authenticates Personal Identification Verification Interoperable (PIV-I) cardholders using the Federal Bridge PKI Certificate Authority (CA).


PIV-I is a standard for smart cards issued by various non-federal organizations, typically operating at the state and local government level. The PIV-I standard is designed to be aligned/interoperable with the federal standard for PIV. There is tremendous information sharing value in being able to offer a turnkey SAML IDP capability to organizations that play a stakeholder role in the PIV-I cardholder community. This PIV-I IDP Implementation Guide provides detailed technical instructions that these PIV-I stakeholders can use to build such a capability and deploy it within NIEF.

This guide is designed around the use of free and open source software, primarily focusing on the use of the following:

Getting Started

This guide assumes the user is comfortable deploying a Linux (or equivalent) server with Apache HTTP Server, Java, and Apache Tomcat. No specific Shibboleth experience is required to follow this guide; however, if you are not comfortable deploying the prerequisites (Linux, Apache, Java, and Tomcat), then you should either acquire that experience or reach out to help@nief.org for assistance before you attempt to follow this guide. We have tested this guide with CentOS 7 Linux, but any modern Linux distribution that includes packages for the Apache HTTP Server should work. It is likely also possible to deploy within a Windows environment or other server environment, as long as you are able to adapt the HTTP configuration steps accordingly and as long as Java 8 is available for running Apache Tomcat and Shibboleth.

Enabling Authentication

The following section describes how to enable client certificate authentication (CCA) within the Apache HTTP Server. The server will need a valid server certificate in addition to all of this configuration, but the server certificate does not need to be issued by the same chain. In fact, it usually should NOT be from the same certificate chain, as the server certificate should come from a well-known CA (e.g., Let's Encrypt), and the client certificates should come from an organizational CA.

Certificate Authority Specification

Apache requires the full certificate chain, including an anchor (self-signed certificate), to be specified in the HTTP Server configuration. This is an important thing to understand, as typically with PIV-I (and with PIV) you are working with cross certified CAs, and if you only include cross certified certs in the CA certificate chain, Apache will fail with errors about chain length being too long (it gets stuck in a loop going through the chain back and forth).

Here is a copy of a sample valid chain (uni-directional chain) from the Foundation for Trusted Identity (FTI) Test CA to the Federal Test PKI CA: File:Fti-test-ca-chain.txt.

Within the Apache configuration, typically within the file ssl.conf you specify this CA file like this:

    SSLCACertificateFile /etc/httpd/trust/fti-test-ca-chain.pem

For a production deployment, the CA chain would be different and would need to be constructed by following the chain and combining the certificates into a single PEM file.

Certificate Status / Revocation Checking

If Online Certificate Status Protocol (OCSP) is available for verifying that a certificate is current, then it is the simplest option to enable it with a single Apache HTTP Server directive:

   SSLOCSPEnable On

In some cases (for example, in the current test CA chain), OCSP is not fully implemented, and it is necessary to instead use CRL (Certificate Revocation List) checking. This is enabled within the the Apache HTTP Server configuration:

   SSLCARevocationFile /etc/httpd/trust/fti-crl.pem

This file must be updated regularly, as it only works if it is current, and by design the file has an expiration date to ensure software checking against the CRL is using a current copy of the CRL. The following script may be useful in configuring this in an automated fashion:

   cd /etc/httpd/trust
   if [ -f FTITestCA.crl ]; then rm FTITestCA.crl; fi
   wget --quiet http://pki.fti.org/fti_ca/crl/FTITestCA.crl
   openssl crl -in FTITestCA.crl -inform DER -out fti-crl.pem
   systemctl restart httpd

A script such as this can then be configured in a crontab to ensure the CRL is up to date.

Configuring Client Certificate Authentication (CCA)

It is very rare that you will want to require CCA for the entire server. Typically, CCA is constrained to specific URL paths. At the top level of the HTTP Server SSL configuration, you should include this directive:

   SSLVerifyClient none

Possibly in another configuration file (or in another section of the SSL configuration file) you would enable TLS CCA like this:

  <Location "/pivi-test">
     SSLOptions +StdEnvVars +ExportCertData
     SSLVerifyClient require
     SSLVerifyDepth 4

A useful way to verify all Apache HTTP Server configuration is correct is to put a simple test page at the location used for testing. As long as this test page is only viewable after engaging in PIV-I authentication, you know that the server is configured correctly.

To enable CCA for use by the Shibboleth IDP, you will need a section like the following (the path could be different if the IDP was installed to a non-standard URL):

  <Location "/idp/Authn/X509">
     SSLOptions +StdEnvVars +ExportCertData
     SSLVerifyClient require
     SSLVerifyDepth 4

Installing Shibboleth

Prior to installing Shibboleth, Java must be available. For most Linux distrubtions java-1.8.0-openjdk is a viable package; java-11-openjdk likely viable as well.

Downloading Shibboleth

The latest version of the Shibboleth IDP is available for download here: https://shibboleth.net/downloads/identity-provider/latest/.

The Shibboleth Wiki is a critical resource for understanding components and how to operate a Shibboleth IDP. While some configuration and installation details are specified in this guide, many other subtle details may be overlooked, and the content of the Shibboleth Wiki is almost always fresher and more useful than this guide.

Running the Shibboleth Installer

After you have downloaded and extracted the installer, run it as seen below. You may need to define JAVA_HOME based on the installed Java package. The values that should populate each question should all be largely self explanatory.

   [shibboleth-identity-provider-3.4.3]# bin/install.sh
   Error: JAVA_HOME is not defined correctly.
     We cannot execute java
   shibboleth-identity-provider-3.4.3]# export JAVA_HOME=/etc/alternatives/jre_1.8.0/
   [shibboleth-identity-provider-3.4.3]# bin/install.sh
   Source (Distribution) Directory (press <enter> to accept default): [/home/krug/src/idp-install/shibboleth-identity-provider-3.4.3]
   Installation Directory: [/opt/shibboleth-idp]
   Hostname: [new.nief.org]
   SAML EntityID: https://piv.nief.org/idp/shibboleth
   Attribute Scope: [nief.org]
   Backchannel PKCS12 Password:
   Re-enter password:
   Cookie Encryption Key Password:
   Re-enter password:
   Warning: /opt/shibboleth-idp/bin does not exist.
   Warning: /opt/shibboleth-idp/edit-webapp does not exist.
   Warning: /opt/shibboleth-idp/dist does not exist.
   Warning: /opt/shibboleth-idp/doc does not exist.
   Warning: /opt/shibboleth-idp/system does not exist.
   Generating Signing Key, CN = piv.nief.org URI = https://piv.nief.org/idp/shibboleth ...
   Creating Encryption Key, CN = piv.nief.org URI = https://piv.nief.org/idp/shibboleth ...
   Creating Backchannel keystore, CN = piv.nief.org URI = https://piv.nief.org/idp/shibboleth ...
   Creating cookie encryption key files...
   Rebuilding /opt/shibboleth-idp/war/idp.war ...
   Total time: 2 minutes 18 seconds

All further configuration is handled by editing the installed configuration files in the chosen installation directory's conf directory.

Configuring Shibboleth Authentication

To enable X.509 CCA, you must specify it in the conf/idp.properties file (it defaults to using the Password login flow):

   # Regular expression matching login flows to enable, e.g. IPAddress|Password

Then you must configure the mechanism for determining the user identity based on the certificate. There is significant flexibility in how the certificate is parsed, and that is configured in conf/c14n/x500-subject-c14n-config.xml. Within this file you can parse out certificate fields by OID and/or by Subject Alt Name Types. The recommended mechanism for production is TBD, but in a test environment, the best option is to use the email subject alt name type. Enable this by removing the XML comments around the value:

   <!-- First priority is given to any subjectAltNames specified (emailAddress is 1) -->
   <util:list id="shibboleth.c14n.x500.SubjectAltNameTypes">
       <!-- <value>1</value> -->

Configuring Shibboleth Trust with Partner Systems

There are many ways to enable trusted partners, and you can read about this in detail on the Shibboleth Wiki. But for our purposes, we are simply documenting how to quickly enable trust of the NIEF Testbed or NIEF Production environment. This configuration is done within the conf/metadata-providers.xml file. You need to enable the Metadata Provider that looks like this (by removing the comments):

   <MetadataProvider id="HTTPMetadata"
       <MetadataFilter xsi:type="SignatureValidation" certificateFile="%{idp.home}/credentials/metaroot.pem" />
       <MetadataFilter xsi:type="RequiredValidUntil" maxValidityInterval="P30D"/>
       <MetadataFilter xsi:type="EntityRoleWhiteList">

The metadataURL is http://ref.gfipm.net/gfipm-signed-ref-metadata.xml for the NIEF Testbed and https://nief.org/trust-fabric/nief-trust-fabric.xml for NIEF in production. The signing certificates for each are http://ref.gfipm.net/ref-gfipm-ca.crt and https://nief.org/trust-fabric/nief-ca.crt respectively. You also need to either increase the max validity interval for NIEF to 45 days or simply remove it in the case of the NIEF Testbed which typically allows trust fabric to last for a year or more. The following is a fully configured example for the NIEF Testbed with inline certificate:

       <MetadataProvider id="nief-testbed"
               <MetadataFilter xsi:type="SignatureValidation"
               <MetadataFilter xsi:type="EntityRoleWhiteList">

Here is a sample provider for NIEF production:

    <MetadataProvider id="nief-main"
              <MetadataFilter xsi:type="SignatureValidation"
              <MetadataFilter xsi:type="RequiredValidUntil" maxValidityInterval="P45D"/>
              <MetadataFilter xsi:type="EntityRoleWhiteList">

Running Shibboleth

The Shibboleth IDP can likely run in any supported servlet container. For simplicity's sake, these instructions assume the use of Apache Tomcat 8. The simplest and quickest way to enable the IDP within Tomcat is to create a file named idp.xml in the [TOMCAT_HOME]/conf/Catalina/localhost directory. The contents of this file specify the war file like this (the path specified in docBase will likely need to be updated to the installation path of Shibboleth):

   <Context docBase="/opt/idp/war/idp.war"
        swallowOutput="true" />

Since it is more common to install Tomcat directly rather than via a package manager, it may be useful to have a Linux startup script. One can be downloaded here: File:Tomcat.sh.

Proxying Shibboleth

Assuming Apache httpd was used from the earlier section as the web server, you will need to configure it to proxy the application server that runs the IDP. This is typically done with a small snippet of proxy configuration within Apache configuration files:

  <Location /idp>
    ProxyPass ajp://localhost:8009/idp

Configuring NIEF Attributes

Shibboleth supports a rich XML configured and API driven capability for attribute resolution. Attributes can be filtered by relying party, by user, or conditionally based on various logic. The attribute values can be sourced from nearly anywhere, as long as code can be written to interact with the source (e.g., databases, web services, directories, programmatic derivation, etc.)

Attribute Filtering

Within the configuration file conf/attribute-filter.xml you can specify attribute release policies. The simplest such policy is to release all configured attributes to all trusted partners. A slightly more sophisticated example, that filters based on test user accounts and assumes a specific test attribute set, is available for download here: File:Attribute-filter.xml.

Attribute Resolution

Within the configuration file conf/attribute-resolver.xml you specify attributes and how to resolve their values. This is one of the most complex and flexible configuration points for Shibboleth, and detailed documentation is available on the Shibboleth Wiki. The flexibility is nearly endless, given the ability to write scripts and custom data connectors. Two samples are available here:

  1. This sample is an extremely simple sample that sends the UserName and a couple of statically defined attributes: File:Minimum-resolver.xml.
  2. This complicated sample configuration file sources attributes from a SQL database, statically for the organization, and from the filesystem in user files is available for download here: File:Attribute-resolver.xml.

Data Connectors

Shibboleth supports the development of new data connectors using their integration APIs. GTRI has developed many such data connectors over the years, and they are available for download on github:

  • Texas DPS Data Connectors - This project consists of three data connectors developed for Texas DPS and supports querying two different web services, one external and one internal, as well as a copy of the GTRI local file system data connector, useful for testing.
  • GTRI Test Data Connector - This is a simple test data connector, but also offers a convenient reference for implementing additional web services, as it is a simple sample of the API.
  • BAE Data Connector - This data connector functions as a Backend Attribute Exchange (BAE) client. It is rather outdated and has really only ever been tested with the retired BAE service from IIR. NOT recommended for use.
  • Shibboleth HTTP Dataconnector - This is a capability of Shibboleth to use a combination of Javascript and templates to call webservices to retrieve attributes. The link will lead to a sample GTRI created for using the IIR 28 CFR service.


It is always a good idea to test and validate a new IDP deployment within a test environment. The NIEF Testbed is intended for exactly this purpose.