---
title: Link identities for authentication
description: IdPs and SPs must be able to communicate about users. Yet, in some cases, the IdP chooses to communicate a minimum of information about an authenticated user; for example, a generated, opaque NameID that cannot directly be used to locate to an identity in the SP identity store.
component: pingoneaic
page_id: pingoneaic:am-saml2:linking-auth-tree
canonical_url: https://docs.pingidentity.com/pingoneaic/am-saml2/linking-auth-tree.html
keywords: ["SAML 2.0", "Single Sign-on (SSO)", "Federation", "Authentication", "Accounts", "Journeys", "Scripts"]
page_aliases: ["saml2-guide:linking-auth-tree.adoc"]
section_ids:
  first_authentication_to_the_sp: First authentication to the SP
  subsequent_authentications_to_the_sp: Subsequent authentications to the SP
  saml2-integrated-mode-sso-persistent-platform: Link accounts persistently
---

# Link identities for authentication

IdPs and SPs must be able to communicate about users. Yet, in some cases, the IdP chooses to communicate a minimum of information about an authenticated user; for example, a generated, opaque `NameID` that cannot directly be used to locate to an identity in the SP identity store.

Advanced Identity Cloud can use these pseudonym identifiers for establishing links between otherwise unrelated accounts, by requiring that the user authenticates to the SP using a linking authentication mechanism.

## First authentication to the SP

The following list describes the sequence of events that occurs the first time a user attempts to authenticate to the Advanced Identity Cloud SP:

1. **Accessing the SP.**

   A user attempts to access a service and is redirected to Advanced Identity Cloud which acts as the SP, specifying the SAML 2.0 service in the login URL.

   For example, a journey containing the [SAML2 Authentication node](https://docs.pingidentity.com/auth-node-ref/latest/saml2.html):

   `https://<tenant-env-sp-fqdn>/am/XUI/#login/&service=spSAMLJourney`

2. **Authentication at the IdP.**

   Advanced Identity Cloud redirects the user to the IdP. The user authenticates successfully to the IdP. The IdP returns a SAML assertion to the SP.

3. **SP attempts to access a federated identity.**

   Advanced Identity Cloud attempts to locate the identity in its user store. No link between the IdP identity and a local one is found.

4. **Authenticating the user to the SP**

   Advanced Identity Cloud goes through a path in the journey that lets the user authenticate on the SP.

5. **Identity federation.**

   After successful authentication at the SP, Advanced Identity Cloud writes the name ID from the assertion into the local user's profile, creating a permanent link between the two identities.

   For more information on creating permanent links between identities, refer to [Enable persistent federation](enable-persistent-federation.html).

   Find an example of a journey that links identities in [Create accounts dynamically during federation](saml2-integrated-mode.html#saml2-integrated-mode-sso-dynamic-platform).

## Subsequent authentications to the SP

The following list describes the sequence of events that occur during subsequent authentication attempts, after the user's identities on the IdP and SPs have been federated:

1. **Accessing the SP.**

   A returning user attempts to access their service and is redirected to Advanced Identity Cloud, which acts as the SP. Their login URL specifies the SAML 2.0 login service.

   For example, a journey containing the [SAML2 Authentication node](https://docs.pingidentity.com/auth-node-ref/latest/saml2.html) and the [Write Federation Information node](https://docs.pingidentity.com/auth-node-ref/latest/write-federation-information.html):

   `https://<tenant-env-sp-fqdn>/am/XUI/#login/&service=spSAMLJourney`.

2. **Authentication at the IdP.**

   Advanced Identity Cloud redirects the user to the IdP, and the user authenticates successfully at the IdP. The IdP returns a SAML assertion to the SP.

3. **SP attempts to access a federated identity.**

   Advanced Identity Cloud attempts to locate the name ID in its user store. The search for the name ID succeeds.

   When there is a match, the user does not need to log in to the SP and is given access to the service.

## Link accounts persistently

If you're not using auto-federation, perform the steps in this procedure to configure a journey, similar to the following, to link accounts persistently.

|   |                                                                                                                                   |
| - | --------------------------------------------------------------------------------------------------------------------------------- |
|   | This procedure relies on [integrated mode SSO](saml2-sso-slo.html#integrated-mode-sso).SLO is *not* supported for this procedure. |

![Example journey to link accounts persistently](../am-authentication/_images/trees-node-write-federation-information-example.png)

1. Add a [SAML2 Authentication node](https://docs.pingidentity.com/auth-node-ref/latest/saml2.html).

   Ensure the NameID Format specified is `persistent`.

   The node processes the assertion, makes its contents available to the journey's shared state in the `userInfo` object, and tries to map the assertion's nameID using the `uid` mapping in the SP's assertion map.

   If the node finds a match, the journey continues through the `Account Exists` output. Otherwise, the journey continues through the `No Account Exists` output.

   The attribute the node uses to map the nameID is not configurable, and this example adds nodes to process the `userInfo` object and match its contents to the managed user's schema instead.

2. Add a [Scripted Decision node](https://docs.pingidentity.com/auth-node-ref/latest/scripted-decision.html) to copy the information from the assertion to the journey's shared state.

   > **Collapse: Example script**
   >
   > * Next-generation
   >
   > * Legacy
   >
   > ```javascript
   > if (nodeState.get("userInfo")) {
   >   if (nodeState.get("objectAttributes")) {
   >     nodeState.remove("objectAttributes");
   >   }
   >   var userName=null,sn=null,mail=null;
   >
   >   try {
   >     var attribs = nodeState.get("userInfo")["attributes"];
   >
   >     userName=attribs["uid"][0];
   >     sn=attribs["sn"][0];
   >     mail=attribs["mail"][0];
   >
   >   } catch (e) {
   >     logger.error("Error getting userInfo: " + e);
   >   }
   >   nodeState.putShared("username", userName);
   >   nodeState.putShared("objectAttributes", {"userName":userName,"sn":sn,"mail":mail, "givenName": userName});
   > }
   > action.goTo("true");
   > ```
   >
   > ```javascript
   > var fr = JavaImporter(org.forgerock.openam.auth.node.api.Action);
   >
   > if (nodeState.get("userInfo")) {
   >   if (nodeState.get("objectAttributes")) {
   >     nodeState.remove("objectAttributes");
   >   }
   >   var userName=null,sn=null,mail=null;
   >
   >   try {
   >     var attribs = nodeState.get("userInfo").get("attributes");
   >
   >     userName=attribs.get("uid").get(0).asString();
   >     sn=attribs.get("sn").get(0).asString();
   >     mail=attribs.get("mail").get(0).asString();
   >
   >   } catch (e) {
   >     logger.error("Error getting userInfo: " + e);
   >   }
   >   nodeState.putShared("username", userName);
   >   nodeState.putShared("objectAttributes", {"userName":userName,"sn":sn,"mail":mail, "givenName": userName});
   > }
   > action = fr.Action.goTo("true").build();
   > ```
   >
   > You can also query the `samlApplication` binding on the SP side to get the assertion.
   >
   > Learn more in the [Scripted Decision node API](../am-scripting/scripting-api-node.html).

3. Add an [Identify Existing User node](https://docs.pingidentity.com/auth-node-ref/latest/identify-existing-user.html) to search the user with the appropriate attribute.

   For example, `userName`.

4. Authenticate the user to the SP.

5. Add the [Write Federation Information node](https://docs.pingidentity.com/auth-node-ref/latest/write-federation-information.html) to the successful outcome of the authentication process to create the link between the accounts.

   If a transient link exists, it is converted into a persistent one.
