X

Tips and HowTos for Single Sign-On & Federation Oracle Identity Management Integrations

  • July 28, 2015

Persistent Federation Data Store

When performing Federation SSO operations, the user will be referenced in the SSO message via a unique identifier that will then be used by the SP to map the incoming SSO response to a local user.

Sometimes the unique identifier is an attribute part of the existing LDAP user record, such as the email address or the username, while other times, the identifier only exists for the Federation SSO operation between the SP and IdP for a specific user. In the latter case, the identifier and the user it is attached to need to be stored as account linking information in a Federation Data Store.

In this article, I will show how to configure OIF to use an RDBMS as the Federation Data Store.

Important note: a persistent Federation Data Store is only required for cases where the identifiers used in the SSO responses (persistent NameID in SAML 2.0 for example) are used. It is best not to use a persistent Federation Data Store when not needed.

Identifiers in Federation Messages


Each Federation protocol uses an identifier to reference the user in the SSO message, though there are variations and differences

SAML 2.0

SAML 2.0 uses three kinds of identifiers:

  • User attributes:
    • These identifiers are user attributes that are typically know by both SP and IdP and stored in the LDAP user account
    • SAML 2.0 defines the following formats, though in OIF you can use any formats:
      • urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
      • urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
      • urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
      • urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName
      • urn:oasis:names:tc:SAML:2.0:nameid-format:Kerberos
    • Typically, using those identifiers does not require a persistent Federation Store, as the values are stored in the LDAP user entry
  • One time identifier
    • This is a specific identifier defined in the SAML 2.0 specifications where the IdP creates a random and onetime identifier when creating the assertion. This means that the next time the same user does a Federation SSO operation with the same SP, another random and one-time-use identifier will be used
    • The name of that identifier is transient and defined by urn:oasis:names:tc:SAML:2.0:nameid-format:transient
    • Since this is a onetime identifier, this will never be stored in a persistent Federation Store
  • Random persistent identifier
    • This identifier is a random string, unique to the triplet IdP/SP/User
    • This identifier will always be the same one sent by the IdP in a SAML 2.0 Assertion for that SP and for that user
    • It needs to be stored in a persistent Federation Store at the IdP, but it is optional for the SP, if the SP is mapping the Assertion to an LDAP user record using SAML Attributes contained in the SAML Assertion
    • Note: with OIF as an IdP, it is possible to use the Persistent NameID format and to populate the value based on expressions, the same way other NameID formats are used. If the NameID value field is filled for the Persistent NameID format in the SP Partner screen, then OIF/IdP will use that expression to set the NameID value.

An example of an Assertion issued by an IdP with an Email Address NameID would be:

<samlp:Response ...>
    <saml:Issuer ...>https://idp.com/oam/fed</saml:Issuer>
    <samlp:Status>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </samlp:Status>
    <saml:Assertion ...>
        <saml:Issuer ...>https://idp.com/oam/fed</saml:Issuer>
        <dsig:Signature>
            ...
        </dsig:Signature>
        <saml:Subject>
<saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">bob@oracle.com</saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData .../>
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions ...>
            <saml:AudienceRestriction>
                <saml:Audience>https://acme.com/sp</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
        <saml:AuthnStatement AuthnInstant="2014-03-21T20:53:55Z" SessionIndex="id-6i-Dm0yB-HekG6cejktwcKIFMzYE8Yrmqwfd0azz" SessionNotOnOrAfter="2014-03-21T21:53:55Z">
            <saml:AuthnContext>
                <saml:AuthnContextClassRef>
                       urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
                </saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>
    </saml:Assertion>
</samlp:Response>

An example of an Assertion issued by an IdP with a persistent NameID would be:

<samlp:Response ...>
    <saml:Issuer ...>https://idp.com/oam/fed</saml:Issuer>
    <samlp:Status>
        <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
    </samlp:Status>
    <saml:Assertion ...>
        <saml:Issuer ...>https://idp.com/oam/fed</saml:Issuer>
        <dsig:Signature>
            ...
        </dsig:Signature>
        <saml:Subject>
<saml:NameID NameQualifier="https://idp.com/oam/fed" SPNameQualifier="https://acme.com/sp" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">id-424129fa23490ded8eab00cc</saml:NameID>
            <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
                <saml:SubjectConfirmationData .../>
            </saml:SubjectConfirmation>
        </saml:Subject>
        <saml:Conditions ...>
            <saml:AudienceRestriction>
                <saml:Audience>https://acme.com/sp</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
       
<saml:AuthnStatement AuthnInstant="2014-03-21T20:53:55Z"
SessionIndex="id-6i-Dm0yB-HekG6cejktwcKIFMzYE8Yrmqwfd0azz"
SessionNotOnOrAfter="2014-03-21T21:53:55Z">
            <saml:AuthnContext>
                <saml:AuthnContextClassRef>
                       urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
                </saml:AuthnContextClassRef>
            </saml:AuthnContext>
        </saml:AuthnStatement>
    </saml:Assertion>
</samlp:Response>

SAML 1.1

SAML 1.1 only uses user attributes as NameIDs:

  • These identifiers are user attributes that are typically know by both SP and IdP and stored in the LDAP user account
  • SAML 1.1 defines the following formats, though in OIF you can use any formats:
    • urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
    • urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress
    • urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName
    • urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName

There is no need to use a persistent Federation Data Store for SAML 1.1

An example of an Assertion issued by an IdP with an Email Address NameID would be:

<samlp:Response>
    <samlp:Status>
        <samlp:StatusCode Value="samlp:Success"/>
    </samlp:Status>
    <saml:Assertion Issuer="https://idp.com/oam/fed" ...>
        <saml:Conditions ...>
            <saml:AudienceRestriction>
                <saml:Audience>https://acme.com/sp/ssov11</saml:Audience>
            </saml:AudienceRestriction>
        </saml:Conditions>
        <saml:AuthnStatement AuthenticationInstant="2014-03-21T20:53:55Z" AuthenticationMethod="urn:oasis:names:tc:SAML:1.0:am:password">
            <saml:Subject>
<saml:NameIdentifier Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">bob@oracle.com</saml:NameIdentifier>
                <saml:SubjectConfirmation>
                   <saml:ConfirmationMethod>
                       urn:oasis:names:tc:SAML:1.0:cm:bearer
                   </saml:ConfirmationMethod>
                </saml:SubjectConfirmation>
            </saml:Subject>
        </saml:AuthnStatement>
        <dsig:Signature>
            ...
        </dsig:Signature>
    </saml:Assertion>
</samlp:Response>

OpenID 2.0

OpenID 2.0 only uses random persistent identifiers as NameIDs:

  • This identifier is a random string, unique to the triplet IdP/SP/User
  • This identifier will always be the same one sent by the IdP in a OpenID 2.0 SSO Response for that SP and for that user
  • It needs to be stored in a persistent Federation Store at the IdP, but it is optional for the SP, if the SP is mapping the SSO Response to an LDAP user record using OpenID Attributes contained in the OpenID SSO Response

An example of an OpenID SSO Response issued by an IdP would be:

https://acme.com/openid?refid=id-9PKVXZmRxAeDYcgLqPm36ClzOMA-&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.mode=id_res&openid.op_endpoint=https%3A%2F%2Fidp.com%2Fopenid&openid.claimed_id=https%3A%2F%2Fidp.com%2Fopenid%3Fid%3Did-38iCmmlAVEXPsFjnFVKArfn5RIiF75D5doorhEgqqPM%3D&openid.identity=https%3A%2F%2Fidp.com%2Fopenid%3Fid%3Did-38iCmmlAVEXPsFjnFVKArfn5RIiF75D5doorhEgqqPM%3D&openid.return_to=https%3A%2F%2Facme.com%2Fopenid%3Frefid%3Did-9PKVXZmRxAeDYcgLqPm36ClzOMA-&openid.response_nonce=2014-03-24T19%3A20%3A06Zid-YPa2kTNNFftZkgBb460jxJGblk2g--iNwPpDI7M1&openid.assoc_handle=id-6a5S6zhAKaRwQNUnjTKROREdAGSjWodG1el4xyz3&openid.ns.ax=http%3A%2F%2Fopenid.net%2Fsrv%2Fax%2F1.0&openid.ax.mode=fetch_response&openid.ax.type.attr0=http%3A%2F%2Fsession%2Fcount&openid.ax.value.attr0=1&openid.ax.type.attr1=http%3A%2F%2Fopenid.net%2Fschema%2FnamePerson%2Ffriendly&openid.ax.value.attr1=My+name+is+Bobby+Smith&openid.ax.type.attr2=http%3A%2F%2Fschemas.openid.net%2Fax%2Fapi%2Fuser_id&openid.ax.value.attr2=bob&openid.ax.type.attr3=http%3A%2F%2Faxschema.org%2Fcontact%2Femail&openid.ax.value.attr3=bob%40oracle.com&openid.ax.type.attr4=http%3A%2F%2Fsession%2Fipaddress&openid.ax.value.attr4=10.145.120.253&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0&openid.pape.auth_time=2014-03-24T19%3A20%3A05Z&openid.pape.auth_policies=http%3A%2F%2Fschemas.openid.net%2Fpape%2Fpolicies%2F2007%2F06%2Fphishing-resistant&openid.signed=op_endpoint%2Cclaimed_id%2Cidentity%2Creturn_to%2Cresponse_nonce%2Cassoc_handle%2Cns.ax%2Cax.mode%2Cax.type.attr0%2Cax.value.attr0%2Cax.type.attr1%2Cax.value.attr1%2Cax.type.attr2%2Cax.value.attr2%2Cax.type.attr3%2Cax.value.attr3%2Cax.type.attr4%2Cax.value.attr4%2Cns.pape%2Cpape.auth_time%2Cpape.auth_policies&openid.sig=mYMgbGYSs22l8e%2FDom9NRPw15u8%3D

Federation Data Store


As seen earlier, a Federation Data Store is required for the following use cases:

  • IdP
    • SAML 2.0 when using Persistent NameID format
    • OpenID 2.0
  • SP
    • SAML 2.0 when using Persistent NameID format and not mapping the user via SAML Attributes
    • OpenID 2.0 and not mapping the user via OpenID SSO Attributes

A Federation Data Store is used to store Account Linking Information which is made of:

  • The user ID
  • The opaque identifier used
  • The ProviderID of the remote partner for which the opaque identifier was created

IdP

As an IdP, the Federation Data Store is required in order to send the same unique opaque identifier that was randomly generated the first time the user performed a Federation SSO operation between the IdP and the SP.

OIF is capable of sending a unique opaque identifier for SAML 2.0 Persistent NameID format and OpenID 2.0 which will be the SHA-256 hash of the:

  • Canonical User ID (OAM ID Store Name + User's DN + UserID)
  • SP ProviderID

This feature allows the use of SAML 2.0 Persistent NameID format and OpenID 2.0 without having to enable a Federation Data Store (see later on how to configure OIF)

SP

As an SP, the Federation Data Store is required if the incoming SSO response is not mapped via SSO Response/user attributes. In this case, the Account Linking Information needs to be present in the Federation Data Store in order for the SP to be able to successfully complete the operation. If the Account Linking Information does not exist, the SP will need to challenge and authenticate locally the user to determine its identity and create an Account Linking Information in the Federation Data Store (User + Opaque Identifier + IdP ProviderID).

The flow at the SP would then be:

  • IdP redirects user to SP with SSO response and opaque identifier
  • SP attempts to locate the Account Linking Information entry in the Federation Data Store by performing a query based on the opaque identifier and the IdP's ProviderID
  • If the query returns an Account Linking Information entry, the SP will extract the user ID from the entry and create a session for that user
  • If the query does not return an Account Linking Information entry
    • The SP will initiate a local login operation to authenticate the user
    • Once the user is locally authenticated, the SP will create an Account Linking Information entry with    
      • UserID
      • Opaque Identifier
      • IdP's ProviderID

Configuring OIF to use a Federation Data Store


Out of the box, OIF is not configured to use a persistent Federation Data Store. So an error will be thrown if

  • OpenID 2.0 SSO is used
  • SAML 2.0 Persistent NameID format not based on expressions (ie: the NameID value field in the SP Partner screen is empty) is used

Note: as mentioned earlier, OIF/IdP can be configured to populate the OpenID 2.0 and SAML 2.0 Persistent NameID with an opaque value based on the SHA-256 hash of the userID and SP's ProviderID, thus not requiring a Federation Data Store. More on this in the next section.

RDBMS

The only supported Federation Data Store is an RDBMS, where the OAM schema exists, and the RDBMS needs to be defined as a JDBC datasource in the WLS server where OAM is running

  • Either use the jdbc/oamds JDBC datasource created during installation and referencing the OAM database used to store policy and session data
  • Or
    • Install a new DB, create the OAM schema via RCU
    • Define a new JDBC datasource in WLS for the WLS managed servers where OAM is running

The ORAFEDPROVIDERFED database table will contain the Account Linking Information entries:

  • idpProvidedNameIDValue is the identifier value
  • providerID is the ProviderID of the remote partner
  • userID is the canonical User ID (OAM ID Store Name + User's DN + UserID)
  • federationType is the type of Federation
    • 1: OIF acts as an IdP and the remote partner is an SP
    • 3: OIF acts as an SP  and the remote partner is an IdP
  • idpProvidedNameIDVersionString is the protocol version (SAML2.0 or OpenID2.0)
  • userDescription is the userID
  • fedID is a unique identifier for this Account Linking Information entry

Note: only OpenID 2.0 and SAML 2.0 Persistent NameID values will be stored in the Federation Data Store

Configuration

To configure OIF to use a Federation Data Store, perform the following steps:

  • Enter the WLST environment by executing:
    $IAM_ORACLE_HOME/common/bin/wlst.sh
  • Connect to the WLS Admin server:
    connect()
  • Navigate to the Domain Runtime branch:
    domainRuntime()
  • Execute the setFederationStore WLST command:
    setFederationStore(enable, jndiname="jdbc/oamds")
    • To enable the Federation Data Store
      • Set enable to true
      • Set the optional jndiname parameter referencing the JDBC Datasource to use. If missing, the OAM JDBC Datasource will be used
      • An example would be:
        setFederationStore("true")
    • To disable the Federation Data Store:
      • Set enable to true
      • An example would be:
        setFederationStore("false")
  • Exit the WLST environment:
    exit()

Testing with OIF as an IdP

In this test, OIF will act as an IdP with a SAML 2.0 SP partner.

To configure OIF/IdP to generate random persistent identifiers that will be stored in the Federation Data Store instead of using LDAP user attributes to populate the NameID value, perform the following steps:

  • Enter the WLST environment by executing:
    $IAM_ORACLE_HOME/common/bin/wlst.sh
  • Connect to the WLS Admin server:
    connect()
  • Navigate to the Domain Runtime branch:
    domainRuntime()
  • Execute the setSPSAMLPartnerNameID WLST command:
    setSPSAMLPartnerNameID(partnerName, nameIDFormat, nameIDValue="", customFormat="", nameIDValueComputed="false")
    • partnerName will be the SP Partner Name
    • nameIDFormat will be set to orafed-persistent
    • nameIDValue will be left empty. If not empty, then OIF/IdP will use the expression to populate the NameID value instead of generating a random persistent identifier
    • An example would be:
      setSPSAMLPartnerNameID("acmeSP", "orafed-persistent")
  • Exit the WLST environment:
    exit()

Executing the following SQL query in an empty ORAFEDPROVIDERFED table would not return any data:

SQL> select idpProvidedNameIDValue, providerID, userID, federationType, idpProvidedNameIDVersionString, userDescription, fedID from ORAFEDPROVIDERFED;

IDPPROVIDE PROVIDERID    USERID        FEDERATIONTYPE IDPPROVID USERDESC FEDID
---------- ------------- ------------- -------------- --------- -------- ----------

After performing Federation SSO with the remote partner SP, executing the query once again would show the new entry:

SQL> select idpProvidedNameIDValue, providerID, userID, federationType, idpProvidedNameIDVersionString, userDescription, fedID from ORAFEDPROVIDERFED;

IDPPROVIDE PROVIDERID    USERID        FEDERATIONTYPE IDPPROVID USERDESC FEDID
---------- ------------- ------------- -------------- --------- -------- ----------
id-s-l3991 http://acme.c oud-e2e:USER:              1 SAML2.0   alice    id-KKqR2Cl
Ut7JEyggvf om/sp         cn=alice,ou=u                                   GnffAGhRLA
IoPavO7Huj               sers,dc=us,dc                                   MzXZMx3UGj
6H0UvFvEec               =oracle,dc=co                                   cMSQge9Nhh
Wwq                      m:alice                                         Nme

Testing with OIF as an SP

In this test, OIF will act as an SP with a SAML 2.0 IdP partner.

To configure OIF/SP to use the Federation Data Store when mapping the incoming SAML 2.0/OpenID 2.0 SSO Response, perform the following steps:

  • Enter the WLST environment by executing:
    $IAM_ORACLE_HOME/common/bin/wlst.sh
  • Connect to the WLS Admin server:
    connect()
  • Navigate to the Domain Runtime branch:
    domainRuntime()
  • Execute the setPartnerIDStoreAndBaseDN WLST command:
    setPartnerIDStoreAndBaseDN(partnerName, partnerType, storeName="", searchBaseDN="", delete="false")
    • partnerName will be the IdP Partner Name
    • partnerType will be set to idp
    • storeName will be set to FederationStore
    • searchBaseDN and delete will not be set
    • An example would be:
      setPartnerIDStoreAndBaseDN("acmeIdP", "idp", "FederationStore")
  • Exit the WLST environment:
    exit()

Important: when OIF/SP performs a Federation SSO with an IdP partner using the SAML 2.0 Persistent NameID or OpenID 2.0 with the Federation Data Store, if the account linking information for the user and that IdP does not exist yet, OIF/SP will need to challenge and authenticate locally the user to be able to create that account linking information entry. The subsequent times, that user won't be challenged anymore since the account linking information entry will already exists.

Executing the following SQL query in an empty ORAFEDPROVIDERFED table would not return any data:

SQL> select idpProvidedNameIDValue, providerID, userID, federationType, idpProvidedNameIDVersionString, userDescription, fedID from ORAFEDPROVIDERFED;

IDPPROVIDE PROVIDERID    USERID        FEDERATIONTYPE IDPPROVID USERDESC FEDID
---------- ------------- ------------- -------------- --------- -------- ----------

After performing Federation SSO with the remote partner IdP and after the user authenticates locally in order to be able to create the account linking information entry, executing the query once again would show the new entry:

SQL> select idpProvidedNameIDValue, providerID, userID, federationType, idpProvidedNameIDVersionString, userDescription, fedID from ORAFEDPROVIDERFED;

IDPPROVIDE PROVIDERID    USERID        FEDERATIONTYPE IDPPROVID USERDESC FEDID
---------- ------------- ------------- -------------- --------- -------- ----------
id-2eCUlO4 http://acme.c oud-e2e:USER:              3 SAML2.0   alice    id-VVSIks6
gekO2rgZfe om/idp        cn=alice,ou=u                                   hzG2szNPyI
YoZkof8YUM               sers,dc=us,dc                                   T5ccRf8dzy
-                        =oracle,dc=co                                   NL0DZjDbGg
                         m:alice                                         c-0

Configuring OIF/IdP to use a Hash as NameID


In case OIF acts as an IdP using SAML 2.0 Persistent NameID and/or OpenID 2.0 based on opaque identifiers and not LDAP user attributes, the server can be configured to populate the NameID based on the SHA-256 hash of the following data:

  • Canonical User ID (OAM ID Store Name + User's DN + UserID)
  • SP ProviderID
  • Protocol version used

To configure OIF/IdP to use SHA-256 hash of the above data to populate the NameID, perform the following steps:

  • Enter the WLST environment by executing:
    $IAM_ORACLE_HOME/common/bin/wlst.sh
  • Connect to the WLS Admin server:
    connect()
  • Navigate to the Domain Runtime branch:
    domainRuntime()
  • Execute the setSPSAMLPartnerNameID WLST command:
    setSPSAMLPartnerNameID(partnerName, nameIDFormat, nameIDValue="", customFormat="", nameIDValueComputed="false")
    • partnerName will be the SP Partner Name
    • nameIDFormat will be set to orafed-persistent
    • nameIDValue will be left empty. If not empty, then OIF/IdP will use the expression to populate the NameID value instead of generating a random persistent identifier
    • nameIDValueComputed will be set to true
    • An example would be:
      setSPSAMLPartnerNameID("acmeSP", "orafed-persistent", nameIDValueComputed="true")
  • Exit the WLST environment:
    exit()

That way, OIF/IdP is not required to be configured to use a Federation Data Store (no need to execute setFederationStore("true") to enable DB as the Federation Data Store), in order to perform Federation SSO with:

  • SAML 2.0 with opaque Persistent NameID
  • OpenID 2.0


In my next article, I discuss about transient federations, that is SAML 2.0 SSO operations with the transient NameID format.
Cheers,
Damien Carru

Join the discussion

Comments ( 2 )
  • guest Tuesday, June 7, 2016

    Hello Damien

    As alwas, thanks for your brilliant articles.

    I'm having a question for the opposite use case - I would like, if possible, to not persist any federation information in the database (as the work load for the database has proven to be pretty challenging during peak load periods).

    My customer (using OAM/OIF 11.1.2.2) is acting as an SP in a federation with an external IdP partner.

    The datastore has been theoretically disabled with WLST command setFederationStore("false", "none").

    However, large amounts of OIF data is still being written to the OAM repository database, for example to the table ORAFEDBLOBSTORE.

    Can this be prevented, also in a clustered environment? Customer is currently using Transient NameID format, but would be willing to try other alternatives if necessary.

    I'm not sure if the persisted information in your article is the same as my customer is unable to un-persist, or something else?

    Best regards,

    /Jon Fleck


  • Damien Wednesday, November 30, 2016

    Hi,

    The data created in the ORAFED* tables are related to Federation session data, including the Federated session, the temporary Federation data that needs to be maintained for subsequent SSO in the same session or for logout.

    So even though that data will be purged after some time, it will still be persisted temporarily.

    Damien


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.