> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.id.me/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.id.me/_mcp/server.

# Salesforce Experience Cloud

> Configure a Salesforce Experience Cloud site to use IDMe as a SAML 2.0 identity provider for federated authentication and just-in-time user provisioning.

## Overview

This guide provides steps to integrate a Salesforce Experience Cloud site with IDMe using the SAML 2.0 protocol.

**Intended audience**\
Salesforce administrators and developers responsible for configuring sign-in on an Experience Cloud site.

**What you will build**\
A federated authentication flow where an Experience Cloud site delegates user authentication to IDMe, and Salesforce creates a site user on first sign-in with an Apex just-in-time (JIT) handler.

**Result**\
A **Sign in with IDMe** button on the site login page. Users who select it authenticate at IDMe and return to the site signed in.

**Identity proofing behavior**\
Authentication behavior, identity verification settings, and returned attributes are driven by IDMe policy configurations.

> **Note**
>
> Salesforce Nonprofit Cloud and other Salesforce clouds use the same Experience Cloud sign-in configuration. The steps in this guide apply to any Experience Cloud site built on an Aura template, where site pages are served under `/s/`. Orgs that store members as Person Accounts, as many Nonprofit Cloud orgs do, need changes to the JIT handler described in this guide.

## Authentication flow

The following steps outline the SAML authentication flow between the user, the Experience Cloud site, and IDMe:

The user navigates to the site login page and selects **Sign in with IDMe**

Salesforce generates a signed SAML AuthnRequest and redirects the user to the IDMe SSO URL

The user completes authentication and identity verification at IDMe

IDMe returns a signed SAML Response to the site's ACS URL

Salesforce validates the assertion. On first sign-in, the JIT handler creates a Contact and a site user. The user lands on the site signed in.

## Prerequisites

* A Salesforce org with Experience Cloud licenses (a free Developer Edition org works for testing; sign up at `https://developer.salesforce.com/signup`)
* System Administrator access to the org
* An Experience Cloud site built on an Aura template (for example, **Customer Account Portal**)
* An IDMe sandbox account for testing your integration
* The IDMe policy handle for your integration, from your IDMe Solution Consultant
* Understanding of [SAML flows](/guides/saml/overview) and terminology

## Environments

IDMe provides two environments:

#### Sandbox

`https://api.idmelabs.com/`

#### Production

`https://api.id.me/`

> **Note**
>
> All IDMe OIDC and SAML endpoints are derived from the base URL above. For production, replace the sandbox base URL in every IDMe endpoint you configure. The SAML issuer is the exception: it is `api.idmelabs.com` in sandbox and `idp.id.me` in production.

### Examples

* SAML metadata URL (Sandbox): `https://api.idmelabs.com/saml/metadata/provider`
* SAML metadata URL (Production): `https://api.id.me/saml/metadata/provider`
* SAML issuer (Sandbox): `api.idmelabs.com`
* SAML issuer (Production): `idp.id.me`

## Configure Salesforce

The examples in this guide use the following placeholder values. Substitute your own.

| Placeholder       | Example                                           |
| ----------------- | ------------------------------------------------- |
| Site URL          | `https://<your-domain>.my.site.com/<site-prefix>` |
| Site prefix       | `members`                                         |
| Member account    | `Site Members`                                    |
| Site user profile | `Customer Community User`                         |

### Prepare the site for external users

Navigate to **Setup** > **Digital Experiences** > **Settings**

Select **Allow using standard external profiles for self-registration, user creation, and login**, then select **Save**

> **Note**
>
> Skip this step if your site users use a custom profile cloned from a standard external profile.

![Screenshot of the Digital Experiences Settings page in Salesforce Setup, showing Role and User Settings with "Allow using standard external profiles for self-registration, user creation, and login" selected.](/_fern-files/_img/4bb398d12a43f957cf7568bccf3bc631e782c2ea30ed212976c4c7c211ddfaf3.webp)

Navigate to **Setup** > **Users** and confirm the user who will own the member account has a **Role** assigned. Salesforce requires the owner of an account that holds site users to have a role.

Create or choose the Account that will hold member Contacts (for example, `Site Members`)

Open the site in **Workspaces** and navigate to **Administration** > **Members**

Add the site user profile (for example, `Customer Community User`) to **Selected Profiles**, then select **Save**

![Screenshot of the Members page in Experience Cloud Workspaces Administration, showing System Administrator and Customer Community User in the Selected Profiles list.](/_fern-files/_img/dd02491f297b4f02cab4c03f22b5353e0f64132d9840c6511277135ecefb0fdf.webp)

Navigate to **Administration** > **Preferences** and choose whether to select **Show nicknames**. When it is selected, the site displays each member's nickname instead of their full name.

### Create a request signing certificate

Salesforce signs every SAML AuthnRequest. It does not allow the default org certificate to be used for this, so create a dedicated certificate.

Navigate to **Setup** > **Certificate and Key Management**

Select **Create Self-Signed Certificate**

Enter a **Label** and **Unique Name** (for example, `IDMe_SAML_Signing`) and select **Save**

Select **Download Certificate**. Send this file to your IDMe Solution Consultant (see [Configure IDMe](#configure-idme)).

![Screenshot of the Certificates and Keys Detail page in Salesforce Setup for a self-signed certificate labeled "IDMe SAML Signing," with 2048-bit key size, Active selected, and the Download Certificate button.](/_fern-files/_img/811eddbf8added2e14a0c78dffd918aac90a0f182ed5e37e0ec73044d0a0d90a.webp)

### Plan user provisioning

When a user signs in with IDMe for the first time, Salesforce needs a site user to sign them in to. Salesforce creates that user with just-in-time (JIT) provisioning, using the attributes in the IDMe SAML assertion. In this guide, a JIT handler generated by Salesforce does this, with one addition described in [Adapt the JIT handler template](#adapt-the-jit-handler-template).

However you set up provisioning, at a minimum:

* Store the IDMe `uuid` in the user's **Federation ID** field. Salesforce uses this value to find the user on later sign-ins. Use `uuid`, not email, as the stable identifier: email addresses can change, and `uuid` does not.
* Create each new site user with the site user profile and a Contact under the Account that holds site members.
* Set first name, last name, and email from the IDMe attributes, and update them on later sign-ins.
* Give each user a unique **Nickname** that does not contain the IDMe `uuid`. Salesforce requires a unique nickname for every user, and sites can display it to other members.

### Configure IDMe as a SAML identity provider

Navigate to **Setup** > **Single Sign-On Settings** and select **Edit**

Select **SAML Enabled**, then select **Save**

> **Note**
>
> If **SAML Enabled** is not selected, the IDMe option does not appear in the site's login settings.

Under **SAML Single Sign-On Settings**, select **New**

Configure the SAML settings:

> **Note**
>
> To obtain the IDMe Signing Certificate, download the metadata from `https://api.idmelabs.com/saml/metadata/provider` (production: `https://api.id.me/saml/metadata/provider`). Copy the X.509 certificate marked `active="true"` from between the `ds:X509Certificate` tags, and save it as a PEM file with standard headers.

| Field                                      | Value                                                                                                                                                                                        |
| ------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Name                                       | `Sign in with IDMe`                                                                                                                                                                          |
| API Name                                   | `IDMe_SAML`                                                                                                                                                                                  |
| Issuer                                     | `api.idmelabs.com` (Production: `idp.id.me`)                                                                                                                                                 |
| Identity Provider Certificate              | Upload the formatted IDMe X.509 certificate                                                                                                                                                  |
| Request Signing Certificate                | The certificate you created (for example, `IDMe_SAML_Signing`)                                                                                                                               |
| Request Signature Method                   | `RSA-SHA256`                                                                                                                                                                                 |
| Assertion Decryption Certificate           | `Assertion not encrypted`                                                                                                                                                                    |
| SAML Identity Type                         | `Assertion contains the Federation ID from the User object`                                                                                                                                  |
| SAML Identity Location                     | `Identity is in an Attribute element`                                                                                                                                                        |
| Attribute Name                             | `uuid`                                                                                                                                                                                       |
| Entity ID                                  | Your site URL (for example, `https://<your-domain>.my.site.com/<site-prefix>`)                                                                                                               |
| Service Provider Initiated Request Binding | `HTTP Redirect`                                                                                                                                                                              |
| Identity Provider Login URL                | `https://api.idmelabs.com/saml/SingleSignOnService?AuthnContext=<your IDMe policy handle>` (production: `https://api.id.me/saml/SingleSignOnService?AuthnContext=<your IDMe policy handle>`) |
| User Provisioning Enabled                  | Enabled (Checked)                                                                                                                                                                            |
| User Provisioning Type                     | `Custom SAML JIT with Apex handler`                                                                                                                                                          |
| SAML JIT Handler                           | Leave blank and select **Automatically create a SAML JIT handler template**                                                                                                                  |
| Execute Handler As                         | A System Administrator user                                                                                                                                                                  |

> **Note**
>
> The **Name** field is the label shown on the site login button. Salesforce has no field for a requested authentication context, so the IDMe policy handle is passed as the `AuthnContext` query parameter on the **Identity Provider Login URL**.

![Screenshot of the Just-in-time User Provisioning section of the SAML Single Sign-On Settings page in Salesforce, with User Provisioning Enabled selected, User Provisioning Type set to Custom SAML JIT with Apex handler, an empty SAML JIT Handler field, and the "Automatically create a SAML JIT handler template" link.](/_fern-files/_img/e7611dcea070e750bf6ef935793fa7007abdb68155562b75c033053d4613a3cf.webp)

![Screenshot of the SAML Single Sign-On Settings edit page in Salesforce, with Name "Sign in with IDMe," Issuer api.idmelabs.com, the IDMe signing certificate loaded, Request Signing Certificate "IDMe SAML Signing" with RSA-SHA256, SAML Identity Type set to Federation ID in the uuid attribute, HTTP Redirect binding, the IDMe Single Sign-On URL with an AuthnContext parameter, and Just-in-time User Provisioning set to Custom SAML JIT with an Apex handler.](/_fern-files/_img/35666844de68e0ff43181968a82d3195c57072bbf8247a53922c5d803626deba.webp)

Select **Save**. Salesforce creates an Apex class named `AutocreatedRegHandler` followed by a number, and sets it as the **SAML JIT Handler**.

> **Note**
>
> Salesforce does not allow Apex classes to be created or edited directly in a production org. Generate and adapt the template in a sandbox, then deploy it to production. The generated template does not include a test class, so your developer also writes test classes that meet Salesforce's code coverage requirement.

![Screenshot of the Single Sign-On Settings page in Salesforce Setup, showing SAML Enabled selected, the SAML Assertion Validator button, and the "Sign in with IDMe" configuration listed with Issuer api.idmelabs.com and the site URL as Entity ID.](/_fern-files/_img/83280fd0f784727a374b03b37a2851de0f298ab1b7f4beef55610a7dfb1ddb33.webp)

### Adapt the JIT handler template

The generated class already creates or updates the Account, Contact, and site user on each sign-in. It reads attributes by their Salesforce names, such as `User.Email` and `Contact.LastName`. IDMe sends attributes under IDMe names, such as `email` and `lname`, so the template needs one addition before it can use them. Your Salesforce developer or implementation partner makes this change. The rest of the template stays as Salesforce generated it.

At the start of the template's `handleJit` method, add a step that:

1. Copies the attributes map. Salesforce passes the map as read-only, so the step adds values to a copy.
2. Copies each IDMe attribute into the Salesforce names the template reads, using the table below.
3. Adds the values that come from your org rather than from IDMe, using the second table below.

| IDMe attribute | Template attribute names                                                                                     |
| -------------- | ------------------------------------------------------------------------------------------------------------ |
| `email`        | `User.Email`, `Contact.Email`                                                                                |
| `fname`        | `User.FirstName`, `Contact.FirstName`                                                                        |
| `lname`        | `User.LastName`, `Contact.LastName`                                                                          |
| `phone`        | `Contact.MobilePhone`                                                                                        |
| `street`       | `Contact.MailingStreet`                                                                                      |
| `city`         | `Contact.MailingCity`                                                                                        |
| `state`        | `Contact.MailingState`                                                                                       |
| `zip`          | `Contact.MailingPostalCode`                                                                                  |
| `birth_date`   | `Contact.Birthdate`                                                                                          |
| `uuid`         | None. Salesforce passes it to the template as the Federation ID from the **SAML Identity Location** setting. |

| Template attribute name  | Value                                                                                                    | When               |
| ------------------------ | -------------------------------------------------------------------------------------------------------- | ------------------ |
| `User.Account`           | The ID of the Account that holds site members                                                            | Every sign-in      |
| `User.ProfileId`         | The ID of the site user profile (not its name)                                                           | First sign-in only |
| `User.Username`          | A unique username in email format, for example the IDMe `uuid` at a domain your org owns                 | First sign-in only |
| `User.CommunityNickname` | A unique nickname that does not contain the `uuid`, for example the first name followed by random digits | First sign-in only |

The attributes returned depend on your IDMe policy. Confirm the list with your IDMe Solution Consultant.

#### Custom and sensitive attributes

Some IDMe attributes have no matching field in the template, such as the Social Security number (`social`) returned by policies that include identity verification. To store one of these attributes:

1. Decide whether you need the value itself. If your site only needs to know that a member is verified, the IDMe policy already establishes that, and a field such as a verified flag or the last four digits is often enough.
2. Create a custom field for the value. Navigate to **Setup** > **Object Manager**, select **Contact** (or **User**), then **Fields & Relationships** > **New**. For a sensitive value such as a Social Security number, use the **Text (Encrypted)** field type, which masks the value, and restrict access with field-level security. Orgs with Salesforce Shield can use Platform Encryption instead.
3. Have your developer set the field from the IDMe attribute in the template. For a User field, add it where the template's `handleUser` method is marked "Handle custom fields here". For a Contact field, add it in the `handleContact` method, alongside the Contact fields the template already sets.

> **Warning**
>
> Store a sensitive attribute only if your use case requires it. Keep sensitive values out of debug logs and error messages.

#### Example: military verification

A policy that verifies military status returns the sign-in attributes (`email`, `fname`, `lname`, `uuid`) plus attributes that describe the member's verified affiliation. For example, a sandbox sign-in through a military policy returned:

| IDMe attribute | Example value | Notes                                                                                                                                                                                                                                       |
| -------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `subgroups`    | `Veteran`     | The member's verified military affiliations. A member can hold more than one, and IDMe sends each as a separate value. Values include `Service Member`, `Veteran`, `Retiree`, `Military Spouse`, `Military Family`, and `Surviving Spouse`. |
| `zip`          | `22150`       | Postal code. Maps to `Contact.MailingPostalCode` in the template.                                                                                                                                                                           |
| `group`        | No value      | Present in some policies with no value. Do not rely on it.                                                                                                                                                                                  |

Attribute names depend on how your policy is configured. For example, the affiliations attribute can arrive as `subgroups` or `military_subgroups`, and policies can also return attributes such as `military_branch`. Confirm the list with your IDMe Solution Consultant.

To store the affiliation:

1. Create a custom field on the Contact (or the User, if your site's visibility rules read User fields). Because a member can hold more than one affiliation, use a **Picklist (Multi-Select)** field with the values above, or a text field.
2. Have your developer set the field from the affiliations attribute in the template, in `handleContact` for a Contact field or at the "Handle custom fields here" marker in `handleUser` for a User field. Test with a sandbox member who holds more than one affiliation to confirm how the handler receives multiple values.
3. Set the field on every sign-in, not only the first. The template runs on each sign-in, so a member whose status changes, for example from `Service Member` to `Veteran`, is updated the next time they sign in.

By default, IDMe sends a successful SAML response only after verification succeeds, so the handler does not need a separate path for unverified members. A member who declines to share their attributes returns to Salesforce with an error response instead, and sees the site's single sign-on error page. To show your own page, set **Custom Error URL** in the SAML settings.

For more advanced use cases, such as reusing existing Contacts or a custom member data model (for example, Nonprofit Cloud), your developer can extend the template further or build a handler that implements the Salesforce [`Auth.SamlJitHandler`](https://developer.salesforce.com/docs/platform/apex-ref/references/apex-ref/apex-interface-auth-samljithandler.html) interface.

### Add IDMe to the site login page

Open the site in **Workspaces** and navigate to **Administration** > **Login & Registration**

Under **Login Page Setup**, select **Sign in with IDMe**

![Screenshot of the Login & Registration page in Experience Cloud Workspaces Administration, showing Login Page Setup with both the username and password option and "Sign in with IDMe" selected.](/_fern-files/_img/47c5295e543c41397236bbb5aa4dc76a14952b592cd6597a4913f05e45ed6787.webp)

Select **Save**

### Display the IDMe button

Salesforce renders the SAML option as a standard button labeled with the **Name** of the SAML configuration. To display the official **Sign in with IDMe** button, your site developer applies the button SVG from the [IDMe brand guidelines](/brand-assets/brand-guidelines#sign-in-with-idme-button) to that button, either with custom CSS in Experience Builder that targets the single sign-on button or with a custom login component, then publishes the site. Salesforce can change the login page markup between releases, so recheck custom CSS after each Salesforce release.

![Screenshot of the Experience Cloud site login page showing username and password fields, the Log in button, and the official green "Sign in with IDMe" button below them.](/_fern-files/_img/457f26d73da73ac8af696b3dca042631816bedaf05984179dafd720cda68141a.webp)

## Configure IDMe

This portion of the configuration is completed by an IDMe Solution Consultant. You will need to provide the following information to complete the setup:

**SP Entity ID**

The **Entity ID** from your SAML configuration. In this guide, the site URL: \
`https://<your-domain>.my.site.com/<site-prefix>`

**Assertion Consumer Service (ACS) URL**

The site ACS URL follows this pattern: \
`https://<your-domain>.my.site.com/<site-prefix>/login`

> **Warning**
>
> Provide the ACS URL exactly as shown, without the `?so=<org ID>` parameter that Salesforce displays on the SAML configuration page. Salesforce sends the URL without it, and IDMe rejects a request whose ACS URL does not match.

**Salesforce signing certificate**

The certificate you downloaded in [Create a request signing certificate](#create-a-request-signing-certificate), in PEM format. IDMe rejects signed AuthnRequests until this certificate is on file.

**Policy handle name**

Confirm the IDMe policy handle with your Solution Consultant. This value determines the identity verification level and attributes returned in the SAML assertion, and is configured in Salesforce as the `AuthnContext` parameter on the **Identity Provider Login URL**.

IDMe returns the following attributes for a sign-in policy. Policies that include verification return additional attributes.

| Attribute | Description                                                    |
| --------- | -------------------------------------------------------------- |
| `uuid`    | IDMe unique identifier, stored as the Salesforce Federation ID |
| `email`   | Email address (also sent as the NameID)                        |
| `fname`   | First name                                                     |
| `lname`   | Last name                                                      |

## Test the integration

Open an incognito window and navigate to your site login page (for example, `https://<your-domain>.my.site.com/<site-prefix>/s/login/`)

Select **Sign in with IDMe** and verify you are redirected to IDMe

![Screenshot of the IDMe sandbox "Sign in to IDMe" page with the Sandbox Mode banner, an email field, and a Continue button.](/_fern-files/_img/572384811d5f2c05de2a10781b36ec56beabb46843da103aa3182e3ca6a0fed1.webp)

Sign in or create a new IDMe account and consent to share attributes

Verify you are redirected back to the site and signed in successfully

Navigate to **Setup** > **Users** to confirm the user was created with the expected profile, Contact, and **Federation ID** (the IDMe `uuid`)

![Screenshot of a user detail page in Salesforce Setup for a user created by the JIT handler, showing the username built from the IDMe UUID, Active and Customer Portal User selected, the linked Contact, and the Federation ID set to the IDMe UUID.](/_fern-files/_img/e6b9beab0f4c0d87b205b20703d875a7205bf27fa2f4247209cbb8a07e58be9d.webp)

## Troubleshooting

**IDMe displays "Something went wrong" after selecting Sign in with IDMe**

IDMe rejected the AuthnRequest. The two most common causes are an ACS URL mismatch (the registered ACS URL includes `?so=<org ID>`) and a missing Salesforce signing certificate. Confirm both with your Solution Consultant.

**The IDMe option does not appear under Login Page Setup**

SAML is not enabled for the org. Navigate to **Setup** > **Single Sign-On Settings**, select **Edit**, and select **SAML Enabled**.

**Salesforce displays "Single Sign-On Error" after returning from IDMe**

Navigate to **Setup** > **Single Sign-On Settings** and select **SAML Assertion Validator**. The validator shows the last failed assertion and the reason. "Unable to map the subject to a Salesforce user" means the JIT handler did not create the user; check the Apex debug log for the **Execute Handler As** user.

**JIT handler fails with FIELD_INTEGRITY_EXCEPTION**

The site user profile is a standard external profile and the org does not allow it. Navigate to **Setup** > **Digital Experiences** > **Settings** and select **Allow using standard external profiles for self-registration, user creation, and login**, or use a cloned custom profile.

**JIT handler fails with DUPLICATES_DETECTED**

A duplicate rule matched the new Contact to an existing one. Update the JIT handler to allow the save when a duplicate rule alerts, or to look up and reuse an existing Contact by email before creating a new one.

**Site displays "down for maintenance" after signing in with IDMe**

The JIT handler stopped with an unhandled error. Check the Apex debug log for the **Execute Handler As** user. A `Collection is read-only` error means the handler adds values to the attributes map Salesforce passes in, instead of to a copy.

**Returning users fail with "Could not find account"**

Set `User.Account` on every sign-in. If it is missing on the first sign-in, the template creates a separate Account for each user. If it is missing on later sign-ins, sign-in fails.

**Request Signing Certificate cannot be saved**

Salesforce does not allow the default certificate to sign requests. Create a self-signed certificate as described in [Create a request signing certificate](#create-a-request-signing-certificate).

**Assertion signature fails after an IDMe certificate rotation**

IDMe rotates signing certificates with an `active="true"` element in its metadata. When IDMe announces a rotation, upload the new active certificate to the **Identity Provider Certificate** field. The `uuid`, and the users keyed on it, do not change.