Moving away from StoredID

This document hasn’t been peer-reviewed. Your mileage may vary!

The Attribute Definitions in this example use the SAML2NameID type which has been deprecated since V3 and will go away in V5.

There are many reasons why you may be using the https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631589 but may also wish to move away from it.

In moving away to a purely https://shibboleth.atlassian.net/wiki/spaces/IDP4/pages/1265631565 you risk losing the existing persistent IDs that your users may be relying on to get access to resources.

It’s possible to configure the IdP to:

  1. Check the existing StoredID database for a value and return it if present

  2. If a value is not present, request one from the ComputedID generator instead

An approximation in pseudo-code:

1 2 3 4 stored_id = get_stored_value(user, service); if is_defined(stored_id) then return stored_id; else return get_computed_value(user, service);

Caveats

This example uses SQLite as a target database engine for the (read-only) data set. Firstly because it’s really simple. Secondly, if you’re making this jump then no “new” data will be added to the database so the file can be statically deployed to your IdP nodes with no need to worry about another RDBMS and replication etc.

Starting point

This assumes you have a working StoredID connector servicing requests for persistent IDs, for example:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 <DataConnector xsi:type="StoredId" id="storedID" generatedAttributeID="storedID" salt='%{idp.persistentId.salt}'> <InputAttributeDefinition ref="uid" /> <BeanManagedConnection>sqlite-dataconnector</BeanManagedConnection> </DataConnector> <AttributeDefinition id="eduPersonTargetedID" xsi:type="SAML2NameID" nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"> <InputDataConnector ref="storedID" attributeNames="storedID"/> <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="eduPersonTargetedID" /> </AttributeDefinition>

This configuration will be happily servicing requests for eduPersonTargetedID by first looking them up in the database, returning the value if it’s present and, otherwise, generating one, storing it and returning it.

Changes

Switching this basic config to the desired model… I’ve switched from the examples generating storedID to persistentId as it’s more descriptive.

Add the ComputedID connector

1 2 3 4 5 6 <DataConnector xsi:type="ComputedId" id="computedID" generatedAttributeID="persistentId" salt='%{idp.persistentId.salt}'> <InputAttributeDefinition ref="uid" /> </DataConnector>

Be sure to use the same Salt, which may be configured as a property elsewhere.

Add the new RDBMs connector

1 2 3 4 5 6 7 8 9 10 11 12 13 14 <DataConnector id="sqlite-db" xsi:type="RelationalDatabase" noResultIsError="true"> <FailoverDataConnector ref="computedID"/> <SimpleManagedConnection jdbcDriver="%{datasource.driverClass}" jdbcURL="%{datasource.jdbcUrl}" /> <QueryTemplate> <![CDATA[ SELECT persistentId FROM shibpid WHERE peerEntity='$resolutionContext.attributeRecipientID' AND principalName='$resolutionContext.principal'; ]]> </QueryTemplate> <Column columnName="persistentId" attributeID="persistentId" /> </DataConnector>

This new data connector will be queried first and will return an error if no results are available from the database. This signals to the resolver to try the Failover connector.

The SELECT statement looks up the required value based on the requesting Service Provider and the principal already. You may need to tweak this for your setup depending on what’s being used now.

Update the Attribute definition

Switch the InputDataConnector to use the new data connector and attribute name:

1 2 3 4 5 <!-- OLD --> <InputDataConnector ref="storedID" attributeNames="storedID"/> <!-- NEW --> <InputDataConnector ref="sqlite-db" attributeNames="persistentId"/>

So it should look like:

1 2 3 4 5 6 7 <AttributeDefinition id="eduPersonTargetedID" xsi:type="SAML2NameID" nameIdFormat="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"> <InputDataConnector ref="sqlite-db" attributeNames="persistentId"/> <AttributeEncoder xsi:type="SAML2XMLObject" name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10" friendlyName="eduPersonTargetedID" /> </AttributeDefinition>