Relational Database Data Connector

The relational database data connector pulls attribute information from any JDBC capable relational database. The following steps walk through how to set up this connector.

1. Define the Connector

To define a new relational database data connector, create a <DataConnector xsi:type="RelationalDatabase" xmlns="urn:mace:shibboleth:2.0:resolver:dc"> with the following attribute:

The following advanced options may also be defined as attributes on the <resolver:DataConnector> element.

<resolver:DataConnector xsi:type="RelationalDatabase" xmlns="urn:mace:shibboleth:2.0:resolver:dc"
                        id="UNIQUE_ID">

     <!-- Remaining configuration from the next steps goes here -->

</resolver:DataConnector>

You have to set the "queryTimeout" attribute to "0". This feature is not yet supported by the PostgreSQL JDBC driver and the default value will cause a crash when starting the IdP.

2. Define Dependencies

This step is optional.

One component within the attribute resolver, like data connectors, can depend on information retrieved or constructed by another component. The values from these dependencies may then be used within the query template in the next step. This might be useful if your SQL query depended on the value retrieved from another connector. For example, if you wanted to use an employeeID retrieved from one source to get attributes from another, a dependency on that attribute would allow it to be used as a variable in the SQL query.

Dependencies are expressed by the <resolver:Dependency> with a ref attribute whose value is the unique ID of the attribute definition or the data connector that this connector depends on.

<resolver:DataConnector xsi:type="RelationalDatabase" xmlns="urn:mace:shibboleth:2.0:resolver:dc"
                        id="UNIQUE_ID">

     <resolver:Dependency ref="DEFINITION_ID_1" />
     <resolver:Dependency ref="DEFINITION_ID_2" />
     <resolver:Dependency ref="CONNECTOR_ID_3" />
     <resolver:Dependency ref="CONNECTOR_ID_4" />

     <!-- Remaining configuration from the next steps go here -->

</resolver:DataConnector>

3. Define Failover Data Connectors

This step is optional.

If the data connector encounters an error when trying to retrieve attribute information from the database, one or more failover data connectors can be defined. These connectors are only invoked if this data connector fails (not if simply finds no results) and they are invoked in the order they are listed until one succeeds.

Failover connectors are defined by the <resolver:FailoverDataConnector> element with a ref attribute whose value is the unique ID of the data connector to use in the event that this one fails.

<resolver:DataConnector xsi:type="dc:RelationalDatabase" xmlns="urn:mace:shibboleth:2.0:resolver:dc"
                                          id="UNIQUE_ID">

     <resolver:Dependency ref="DEFINITION_ID_1" />
     <resolver:Dependency ref="DEFINITION_ID_2" />
     <resolver:Dependency ref="CONNECTOR_ID_3" />
     <resolver:Dependency ref="CONNECTOR_ID_4" />

     <resolver:FailoverDataConnector ref="CONNECTOR_ID_1" />

     <!-- Remaining configuration from the next steps goes here -->

</resolver:DataConnector>

4a. Define Identity Provider (Application) Managed Connections

Deployers wishing to allow the data connector to manage connections to the database should follow these instructions; those wishing to allow the Servlet container to manage connections should use the instructions in step 4b.

Tips on Oracle connection configuration.

Identity Provider (application) managed connections are defined by a <ApplicationManagedConnection> element with the following attributes:

<resolver:DataConnector xsi:type="RelationalDatabase" xmlns="urn:mace:shibboleth:2.0:resolver:dc"
                        id="UNIQUE_ID">

     <!-- Dependency and Failover information would go here -->

     <ApplicationManagedConnection jdbcDriver="DRIVER_CLASS"
                                   jdbcURL="DATABASE_URL"
                                   jdbcUserName="DATABASE_USER"
                                   jdbcPassword="DATABASE_USER_PASSWORD" />

     <!-- Remaining configuration from the next steps goes here -->

</resolver:DataConnector>

In order to use a database you must place the JDBC driver, for your database, in the IDP_HOME/lib directory and the IDP_SRC/lib directory. You must then rerun the install script (to generate a new WAR) and restart your servlet container.

Advanced Options

The <ApplicationManagedConnection> element also allows the following, advanced, configuration attributes controlling how connections are pooled:

4b. Define Container Managed Connections Configuration

Configuration that use container managed connections can not be tested from the command line.

Deployers wishing to have their Servlet container manage connections to a database should follow these instructions, those wishing to allow the data connector to manage connections should use the instructions in step 4a.

Servlet container managed connections are defined by a <ContainerManagedConnection> element with the following attribute:

The <ContainerManagedConnection> may also contain any number of <JNDIConnectionProperty> elements that specify the JNDI connection properties appropriate for the container. Refer to your container documentation for these properties. Some common JNDI connection parameters are listed by Sun.

<resolver:DataConnector xsi:type="RelationalDatabase" xmlns="urn:mace:shibboleth:2.0:resolver:dc"
                        id="UNIQUE_ID">

     <!-- Dependency and Failover information would go here -->

     <ContainerManagedConnection resourceName="RESOURCE_NAME"  />

     <!-- Remaining configuration from the next steps go here -->

</resolver:DataConnector>

In order to use a database you must place the JDBC driver, for your database, in your servlet's classpath and restart your servlet container. Refer to your servlet container's documentation for instructions.

5. Define the SQL Query

The SQL query used to retrieve attribute information from the database is specified within a single <QueryTemplate> element. The content of the element is a template resulting in a well formed SQL statement and should always be encapsulated in CDATA to ensure proper handling. Variables may be used, including those passed in through dependencies and a special one, $requestContext.principalName, which is always the principal name as supplied by the user authentication.

<resolver:DataConnector xsi:type="RelationalDatabase" xmlns="urn:mace:shibboleth:2.0:resolver:dc"
                        id="UNIQUE_ID">

     <!-- Dependency and Failover information would go here -->

     <ContainerManagedConnection resourceName="RESOURCE_NAME" />

     <QueryTemplate>
          <![CDATA[
               SELECT * FROM PEOPLE WHERE userid='$requestContext.principalName'
          ]]>
     </QueryTemplate>

     <!-- Remaining configuration from the next steps go here -->

</resolver:DataConnector>

More information on the template language is available here explaining how variable substitution is accomplished.

6. Define Column Mappings

This step is optional.

By default, the data connector will produce one attribute per column retrieved, using the column name as the attribute's ID, each row as an attribute value, and the column's type as the object type for each value. For example, consider a SQL query SELECT firstname, personid FROM PERSON WHERE userid='${requestContext.principalName}' with a firstname column of type VARCHAR and a personid column of type NUMBER(9). The data connector would create two attributes with ID's of firstname and personid. Each of the values of firstname would be a String and each of the values of personid would be an Integer.

Column mappings allow you to change this behavior by mapping a column name to a specified name and/or specifying an object type for the values retrieved from that column. The mappings are defined by one or more <Column> element with the following attributes:

<resolver:DataConnector xsi:type="RelationalDatabase" xmlns="urn:mace:shibboleth:2.0:resolver:dc"
                        id="UNIQUE_ID">

     <!-- Dependency and Failover information would go here -->

     <ContainerManagedConnection resourceName="RESOURCE_NAME"  />

     <QueryTemplate>
          <![CDATA[
               SELECT * FROM PEOPLE WHERE userid='$principal'
          ]]>
     </QueryTemplate>

     <Column columnName="firstname" attributeID="fname" />
     <Column columnName="personid" type="String" />

</resolver:DataConnector>

7. Result Caching

The data connector may cache query results for a period of time or until too many results are in memory.

To enable and configuration result caching add the <ResultCache> element as the last element in the data connector. The element has the following attributes:

8. Putting It Together

A final, complete RDBMS <DataConnector> could look like this.

<resolver:DataConnector xsi:type="RelationalDatabase" xmlns="urn:mace:shibboleth:2.0:resolver:dc"
                        id="UNIQUE_ID">

     <resolver:Dependency ref="DEFINITION_ID_1" />
     <resolver:Dependency ref="CONNECTOR_ID_3" />

     <resolver:FailoverDataConnector ref="CONNECTOR_ID_1" />

     <ContainerManagedConnection resourceName="RESOURCE_NAME"  />

     <QueryTemplate>
          <![CDATA[
               SELECT * FROM PEOPLE WHERE cn='$DEFINITION_ID_1'
          ]]>
     </QueryTemplate>

     <Column columnName="firstname" attributeID="fname" />
     <Column columnName="personid" type="String" />

     <ResultCache elementTimeToLive="PT1H" />
</resolver:DataConnector>