---
title: SP account mapper
description: Use the SP account mapper to customize how SAML 2.0 assertions are mapped to user profiles.
component: pingoneaic
page_id: pingoneaic:am-saml2:custom-sp-account-mapper
canonical_url: https://docs.pingidentity.com/pingoneaic/am-saml2/custom-sp-account-mapper.html
keywords: ["SAML 2.0", "Single Sign-on (SSO)", "Federation", "Customization", "Scripts"]
page_aliases: ["release-notes:rapid-channel/sp-account-mapper.adoc"]
section_ids:
  example-sp-account-mapper: Customize auto-federation using an SP account mapper
  prepare-profile-data: Prepare the user profiles
  configure-auto-fed: Configure auto-federation
  use-sp-account-mapper-script: Update the SP account mapper script
  test-sp-account-mapper-script: Try the script
  handle-missing-nameid: Handle a missing NameID in a script
---

# SP account mapper

Use the SP account mapper to customize how SAML 2.0 assertions are mapped to user profiles.

* Next-generation example script

  [SAML2 SP Account Mapper Script](../am-scripting/sample-scripts.html#saml2-sp-account-mapper-js)

* Script bindings

  [SP account mapper scripting API](../am-scripting/saml2-sp-account-mapper-api.html)

## Customize auto-federation using an SP account mapper

This section describes how to implement an example SP account mapper that uses a script to customize auto-federation of user accounts. It assumes that you have configured your environment for SSO using SAML 2.0, where Advanced Identity Cloud is the hosted SP. These example steps use a separate Advanced Identity Cloud tenant as the remote IdP.

* [Prepare the user profiles](#prepare-profile-data)

* [Configure auto-federation](#configure-auto-fed)

* [Update the SP account mapper script](#use-sp-account-mapper-script)

* [Try the script](#test-sp-account-mapper-script)

### Prepare the user profiles

1. Create a test user on the hosted SP, for example `bjensen`, with an email address set to `bjensen@example.com`.

2. Create a test user on the hosted IdP, for example `babsjensen`, with an email address also set to `bjensen@example.com`.

### Configure auto-federation

Under Native Consoles > Access Management, go to Applications > Federation > Entity Providers and click on the name of the hosted provider.

1. On the tenant configured as the **hosted SP**:

   1. Under Assertion Processing > Auto Federation:

      * Switch on Enabled.

      * Set Attribute to `mail`.

   2. Save your changes.

2. On the tenant configured as the **hosted IdP**:

   1. Under Assertion Processing > Attribute Mapper, add the following Attribute Map:

      * Name Format Uri

        `urn:oasis:names:tc:SAML:2.0:attrname-format:basic`

      * SAML Attribute

        `mail`

      * Local Attribute

        `mail`

   2. Save your changes.

### Update the SP account mapper script

1. Under Native Consoles > Access Management, go to Scripts, and click SAML2 SP Account Mapper Script.

2. Update the script to implement any custom behavior for auto-federation. This example adds a logging statement to record the assertion map.

   |   |                                                                                                                                                                                                           |
   | - | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   |   | To handle a missing NameID in the assertion, update the script to check for a `null` NameID and fall back to auto-federation.Learn more in [Handle a missing NameID in a script](#handle-missing-nameid). |

   ```javascript
   ...
   userID = accountMapperHelper.getAutoFedUser(nameID["value"]);
       if (userID != null && userID.length > 0) {
           //
           // insert custom code here
           //
           // update logging to output assertion and userID
           logger.error("Assertion: " + assertion);
           logger.error(debugMethod + " use AutoFedUser as userID: " + userID);
           return userID;
       } else {
           ...
       }
   ```

   |   |                                                                                                                                                                                                                                                   |
   | - | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   |   | The SP account mapper script type is a [next-generation script](../am-scripting/next-generation-scripts.html) only.Learn about the available bindings in the [SP account mapper scripting API](../am-scripting/saml2-sp-account-mapper-api.html). |

3. Still in the native console, go to Applications > Federation > Entity Providers > *Hosted SP Name* > Assertion Processing.

4. Under Account Mapper, select `SAML2 SP Account Mapper Script` from the Account Mapper Script list.

5. Save your changes.

### Try the script

1. To verify the script works as expected, test your changes using an SP-initiated flow.

   For example:

   ```none
   https://<tenant-env-sp-fqdn>/am/saml2/jsp/spSSOInit.jsp?realm=/alpha&idpEntityID=idp1&metaAlias=/alpha/sp1&binding=urn%3Aoasis%3Anames%3Atc%3ASAML%3A2.0%3Abindings%3AHTTP-POST
   ```

2. Log into the IdP as `babsjensen`.

   After you've logged into the IdP successfully, you shouldn't need to log into the SP because the script auto-federates the `babsjensen` and `bjensen` accounts.

3. Verify that `bjensen` is logged into the SP.

   You can also check that the SP [debug logs](../tenants/audit-debug-logs.html) contain the customized logging output, for example:

   ```none
   Assertion:
   {
       "version": "2.0",
       "issueInstant": 1758805815000,
       "subject": {
           "subjectConfirmation": [
               {
       …​
   }
   ScriptedSPAccountMapper.getIdentity::  use AutoFedUser as userID: id=bjensen,ou=user,o=alpha,ou=services,ou=am-config
   ```

## Handle a missing NameID in a script

If your IdP doesn't always include a NameID in the assertion, update your SP account mapper script to check for a `null` NameID and fall back to auto-federation.

When `accountMapperHelper.getNameID()` returns `null`, call `accountMapperHelper.getAutoFedUser()` to resolve the user using the configured auto-federation attribute.

|   |                                                                                                                                                                |
| - | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | If there's no NameID and the auto-federation lookup fails to find a user, the script should return `null`. Advanced Identity Cloud then rejects the assertion. |

The following example shows a `getIdentity()` function with the NameID `null` check:

```javascript
function getIdentity() {
    const debugMethod = "ScriptedSPAccountMapper.getIdentity:: ";
    var nameID = accountMapperHelper.getNameID();
    var userID = null;

    if (!nameID) {
        // No NameID in assertion — fall back to auto-federation attribute
        return accountMapperHelper.getAutoFedUser();
    }

    var isTransient = accountMapperHelper.isTransientNameId(nameID["format"]);
    if (isTransient) {
        userID = accountMapperHelper.getTransientUserForSP();
        accountMapperHelper.validateUserId(userID);
        if (userID != null && userID.length > 0) {
            logger.debug(debugMethod + " use Transient user as userID:" + userID);
            return userID;
        }
    }

    userID = accountMapperHelper.getAutoFedUser(nameID["value"]);
    if (userID != null && userID.length > 0) {
        logger.debug(debugMethod + " use AutoFedUser as userID:" + userID);
        return userID;
    } else {
        if (accountMapperHelper.useNameIDAsSPUserID() && !accountMapperHelper.isAutoFedEnabled()) {
            logger.debug(debugMethod + " use NameID value as userID:" + nameID["value"]);
            accountMapperHelper.validateUserId(nameID["value"]);
            return nameID["value"];
        } else {
            return null;
        }
    }
}

getIdentity();
```

|   |                                                                                                                                                                                    |
| - | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|   | SLO isn't supported when the NameID is missing from the assertion. Learn more in [Auto-federation when no NameID is present](auto-federation.html#auto-federation-missing-nameid). |
