> 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.

# PingFederate OIDC integration guide

> Configure PingFederate to use IDMe as an OpenID Connect identity provider for federated authentication.

## Overview

This guide provides steps to integrate PingFederate with IDMe using the OpenID Connect (OIDC) protocol.

**Intended audience** \
Developers and IAM administrators responsible for configuring federation between PingFederate and IDMe.

**What you will build** \
A federated authentication flow where PingFederate delegates user authentication to IDMe and issues its own ID token to a target application.

**Result** \
Users sign in through a target application, are redirected through PingFederate to IDMe to authenticate and complete identity verification, and return to the target application with a PingFederate-issued ID token containing the mapped IDMe attributes.

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

## Authentication flow

The following steps outline the OIDC authentication flow between the user, the target application, PingFederate, and IDMe:

The user navigates to the application and is redirected to PingFederate

PingFederate redirects the user to IDMe

The user completes authentication and identity verification at IDMe

IDMe redirects the user back to PingFederate with an authorization code

PingFederate exchanges the code for tokens

PingFederate completes its own authorization response and redirects the user back to the application with an authorization code.

The application exchanges that code at PingFederate's token endpoint and receives the PingFederate-issued ID token

![Diagram showing OIDC Flow between PingFederate, IDMe, and an application](https://files.buildwithfern.com/visual-editor-images/docs.id.me/2026-10-20T20:02:14.360Z/guides/iam-platforms/ping-identity/pingfederate/PingFederate_IDme_Integration_OIDC_Flow_Diagram.png "PingFederate_IDme_Integration_OIDC_Flow_Diagram")

## Prerequisites

* Active PingFederate instance
* Access to PingFederate (and optional user directory) with administrator access
* An IDMe sandbox account for testing your integration
* Understanding of [OIDC flows](/guides/oidc/overview) and terminology
* An application to test the sign-in flow
* A directory such as PingDirectory, Active Directory, or OpenLDAP, and administrator credentials to configure it, if you plan to enable JIT provisioning (optional)

## 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.

### Examples

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

## Configure PingFederate

PingFederate plays two roles in this integration: an OIDC relying party to IDMe, and an OpenID provider to your target application.

> **Note**
>
> As configured in this guide, this is a **pass-through integration.** PingFederate reads the attributes from IDMe's ID token, maps them, and puts them in its own ID token for the application without saving them. No user directory is needed, and the steps through registering your OAuth client are the complete integration. A directory is needed only if you want PingFederate to create, and keep updated, a user account for each IDMe user, which is covered as an optional final step.

> **Note**
>
> These steps were validated against PingFederate 13.1.2. Admin console menu paths may differ in other versions; check the PingFederate documentation for the latest information.

### Create an authentication policy contract

An Authentication Policy Contract is the common language in PingFederate between an authentication source (the IDMe IdP connection) and what consumes it (OAuth/OIDC token issuance). Without one, the attributes IDMe returns have nowhere to land.

Navigate to **Authentication > Policies > Policy Contracts**

Select **Create New Contract**

On the **Contract Info** tab, enter a name (for example, `IDme-Contract`), then select **Next**

On the **Contract Attributes** tab, `subject` is included by default. Under **Extend the Contract**, add each IDMe attribute you plan to pass to the application. This example uses `fname`, `lname`, `email`, `street`, `city`, `state`, `zip`, and `phone`

> **Note**
>
> It's recommended to keep the attribute names the same across this integration - from PingFederate to IDMe to the target application. Every layer in PingFederate declares its own attribute list, and matching names at every layer makes mapping mistakes easier to spot.

Select **Next**, then select **Save**

![Screenshot of sample PingFederate Authentication Policy Contract](https://files.buildwithfern.com/visual-editor-images/docs.id.me/2026-10-20T20:13:35.196Z/guides/iam-platforms/ping-identity/pingfederate/PingFederate-AuthN-_Policy-Contract.png "PingFederate-AuthN- Policy-Contract")

### Add IDMe as an OpenID Connect IdP connection

Navigate to **Authentication > Integration > IdP Connections** and select **Create Connection**

> **Note**
>
> Before you start, check the PingFederate base URL at **System > Server > Protocol Settings > Federation Info**. PingFederate builds the redirect URI that IDMe needs from this value.

On the **Connection Type** tab, check **Browser SSO Profiles**, select **OpenID Connect** in the **Protocol** list, and select **Next**

On the **Connection Options** tab, leave **Browser SSO** checked, leave **JIT Provisioning** unchecked for a pass-through integration (check it only if you are also configuring the optional directory setup), leave **OAuth Attribute Mapping** unchecked since this guide maps attributes through the Authentication Policy Contract instead, and select **Next**

On the **General Info** tab, set **Issuer** to the IDMe sandbox issuer (`https://api.idmelabs.com/oidc`), select **Load Metadata** so PingFederate retrieves the endpoints from the IDMe well-known endpoint, enter a **Connection Name** (for example, `ID.me Sandbox`), and enter the **Client ID** and **Client Secret** from your IDMe Application, then select **Next**

On the **Browser SSO** tab, select **Configure Browser SSO**

On the **User-Session Creation** tab, select **Configure User-Session Creation**, then select **No Mapping** for **Identity Mapping**

> **Note**
>
> The authentication policy you configure later maps IDMe's attributes into the contract, so the connection does not need its own mapping. Account Mapping and Account Linking are for connections that map straight to a target session; Account Linking also ties each IDMe identity to an account the user already has in your existing user store, confirmed once by signing in with those existing credentials.

After you select No Mapping, the Target Session Mapping tab disappears; this is expected. Select **Next**. On the **Attribute Contract** tab, `sub` is the core attribute; under **Extend the Contract**, add each IDMe claim you need, spelled exactly as IDMe returns it (e.g., `fname`, `lname`, `email`, `street`, `city`, `state`, `zip`, `phone`), then select **Next**. On the **Summary** tab, review the settings and select **Done**, then select **Next** to go to **Protocol Settings**

On the **Protocol Settings** tab, select **Configure Protocol Settings**, then on the **OpenID Provider Info** tab confirm or set the following values:

| Field                                 | Value                                                                              |
| ------------------------------------- | ---------------------------------------------------------------------------------- |
| Scopes                                | `openid <IDMe Policy Handle>` (for example, `openid nist_ial2_aal2`)               |
| Authorization Endpoint                | `https://api.idmelabs.com/oauth/authorize`                                         |
| OpenID Connect Login Type             | `Code`                                                                             |
| Authentication Scheme                 | `Basic`                                                                            |
| Enable PKCE                           | Checked or unchecked; must match your IDMe Application settings                    |
| Token Endpoint                        | `https://api.idmelabs.com/oauth/token`                                             |
| JWKS URL                              | `https://api.idmelabs.com/oidc/.well-known/jwks`                                   |
| UserInfo Endpoint                     | Leave blank unless needed; PingFederate reads every attribute from IDMe's ID token |
| Pushed Authorization Request Endpoint | Leave blank                                                                        |

> **Note**
>
> The scope that IDMe receives is set here, in the Scopes field. This value decides what IDMe verifies and which attributes it returns, and PingFederate forwards it to IDMe unchanged on every sign-in. This is separate from the scope your target application later requests from PingFederate, which only controls which claims PingFederate includes in its own ID token.

Select **Next**. On the **Overrides** tab, leave the defaults and select **Next**. On the **Summary** tab (still under the Protocol Settings parent tab) select **Done**

You now return to the **Browser SSO** window's **Protocol Settings** tab. Select **Next** to get to the **Summary** tab and check that the settings are correct. Select **Done**.

You now return to the **IdP Connections** tab. Click **Next** to go to **Activation & Summary**. In the **Activation & Summary** tab, check the toggle at the top right to make the connection **Active**, copy the **Redirect URI** shown at the top of the tab and save it for later, review the summary, and select **Save**

![Screenshot of sample Activation & Summary tab for the IDMe IdP connection in PingFederate](https://files.buildwithfern.com/visual-editor-images/docs.id.me/2026-10-20T20:55:16.033Z/guides/iam-platforms/ping-identity/pingfederate/PingFederate-Activation-Summary-Tab-IDme-Connection.png "PingFederate-Activation-Summary-Tab-IDme-Connection")

### Create an authentication policy

An Authentication Policy tells PingFederate which authentication source to use when an application sends a user to its authorization endpoint. Without one, PingFederate does not know to send users to IDMe.

> **Note**
>
> An authentication policy decides how a user signs in, while a policy contract defines what data comes out when they succeed. Keeping them separate makes the contract a stable handoff point: you can add a second identity provider, place IDMe behind a selector, or add MFA after IDMe by changing only the policy, as long as each successful path still fills the same contract.

Navigate to **Authentication > Policies > Policies**

Check the **IdP Authentication Policies** box to turn on policies for browser-based sign-in, including the OAuth authorization code flow

Select **Add Policy**, enter a **Name** (for example, `IDme-Sign-In`), and for the first action select **IdP Connections**, then select your IdP connection name (for example, `ID.me Sandbox`)

For **Fail**, select **Done**. For **Success**, select your Authentication Policy Contract (for example, `IDme-Contract`)

Under the contract you selected, select **Contract Mapping**. On the **Attribute Sources & User Lookup** tab, leave it empty and select **Next**, since this tab is only for looking up extra attributes in a data store that do not come from IDMe

On the **Contract Fulfillment** tab, set **Source** to the IDMe IdP connection for every row, map `subject` to `sub`, and map every other attribute to the IDMe attribute with the same name, then select **Next**

> **Note**
>
> You can also map `subject` to `uuid`, because the values are the same from IDMe and always included in payloads, but PingFederate defaults to the `sub` attribute, which may require fewer changes elsewhere in PingFederate.

On the **Issuance Criteria** tab, select **Next**. On the **Summary** tab, select **Done** to close the contract mapping, then select **Done** to close the policy

Make sure the policy is enabled in the top right of the screen, then select **Save**

> **Note**
>
> If you already have policies, add the IDMe policy where it belongs in the existing order. PingFederate evaluates policies from the top down. To offer IDMe alongside another sign-in option, or to send some applications to IDMe and others elsewhere, put a selector (for example, Requested AuthN Context or OAuth Client Set) in front of the IDMe action.

> **Note**
>
> For a single-IdP demo, you can skip the policy. Leave IdP Authentication Policies unchecked and add the IDMe connection on the Default Authentication Sources tab instead. In that case, the connection must map the contract itself: on the IdP connection's User-Session Creation tab, select Account Mapping, and on Target Session Mapping select Map New Authentication Policy, select your contract, and map each attribute from Provider Claims. This is simpler but cannot grow to more than one sign-in option.

### Configure OAuth and OIDC issuance

These OAuth objects turn the attributes in the Authentication Policy Contract into the ID token that PingFederate issues to the target application. The attributes flow as follows:

```text
IDMe claims → IdP connection → Authentication Policy Contract
              → Access Token Mapping → Access Token Manager
              → OIDC Policy → ID token

```

> **Important**
>
> Each arrow above is a separate mapping screen in PingFederate. An attribute missing from any one of them is silently dropped from the ID token.

PingFederate also requires a persistent grant mapping, which identifies the user to the OAuth server; the attributes do not need to pass through it. Keep it to the user key and `sub`/`uuid` only, and never add personal data such as name, email, or address, because PingFederate stores the grant when it issues refresh tokens.

#### Define the scope and persistent grant attribute

Navigate to **System > OAuth Settings > Scope Management**

On the **Common Scopes** tab, select **+ Add Common Scope**

Enter a **Name** matching your IDMe Policy handle (for example, `nist_ial2_aal2`) and a short, generic **Description** (for example, `Access to ID.me-verified identity attributes`)

Leave **Dynamic Scope** unchecked, since this guide uses one fixed scope name, and select **Save**

> **Note**
>
> The scope description is static text that appears only on PingFederate's own consent page, which this guide bypasses (see Bypass Approval Page when registering the OAuth client). It is not the IDMe consent screen: IDMe shows its own consent screen, built from the IDMe Policy, before it releases anything to PingFederate. Keep the description short and generic so it does not need updating when attributes change.

Navigate to **System > OAuth Settings > Authorization Server Settings**

Under **Persistent Grant Extended Attributes**, add `sub` only, and select **Save**

> **Note**
>
> This is PingFederate's own name for the attribute, not IDMe's claim. Its value comes from the contract's subject, which can be filled from either IDMe's `sub` or `uuid`, since they hold the same value. Keeping the name `sub` is recommended, since it carries through to the `sub` claim in PingFederate's ID token, and OpenID Connect requires that claim to be called `sub`.

#### Create an access token manager

Navigate to **Applications > OAuth > Access Token Management** and select **Create New Instance**

On the **Type** tab, enter an **Instance Name** and **Instance ID** (for example, `idmeAtm`), select **Internally Managed Reference Tokens** as the type, and select **Next**

On the **Instance Configuration** tab, this example uses a **Token Lifetime** of 120 minutes; keep the other defaults and select **Next**

On the **Session Validation** tab, keep the defaults and select **Next**

On the **Access Token Attribute Contract** tab, leave **Subject Attribute Name** as `USER_KEY`. Under **Extend the Contract**, add `sub` and every attribute from your Authentication Policy Contract, selecting **Add** after each one, then select **Next**

> **Important**
>
> Add `sub` to the access token manager's attribute contract explicitly. If it is missing, the OpenID Connect Policy fails validation with "not an applicable token attribute" the next time anyone saves it.

Select **Next** through **Token Endpoint Attribute Contract**, **Resource URIs**, and **Access Control**, keeping the defaults. On the **Summary** tab, select **Save**

On the **Access Token Management** list, make this access token manager the default if it is your only one. A client can use a non-default access token manager, as long as that access token manager has its own Access Token Mapping

#### Map the policy contract to the persistent grant

Navigate to **Authentication > OAuth > Policy Contract Grant Mapping**

In the list, select your Authentication Policy Contract (for example, `IDme-Contract`) and select **Add Mapping**. If a mapping for that contract already exists, select it under **Mappings** instead

On the **Attribute Sources & User Lookup** tab, leave it empty and select **Next**

On the **Contract Fulfillment** tab, for each row set **Source** to **Authentication Policy Contract** and **Value** as follows: `USER_KEY` from `subject`, `USER_NAME` from `subject`, and `sub` from `subject`. Select **Next**. On the **Issuance Criteria** tab, select **Next**

On the **Summary** tab, select **Save**

#### Create the access token mapping

Navigate to **Applications > OAuth > Access Token Mappings**

In the **Context** list, select your Authentication Policy Contract (for example, `IDme-Contract`), not **Default**. In the **Access Token Manager** list, select your access token manager (for example, `idmeAtm`). Select **Add Mapping**. If a mapping for that context and access token manager already exists, select it under **Mappings** instead

On the **Attribute Sources & User Lookup** tab, leave it empty and select **Next**

On the **Contract Fulfillment** tab, map every access token manager attribute: set **Source** to **Authentication Policy Contract**, map `sub` from `subject`, and map each other attribute to the contract attribute with the same name, then select **Next**

On the **Issuance Criteria** tab, select **Next**. On the **Summary** tab, select **Save**

> **Error**
>
> Every access token manager a client can use needs its own Access Token Mapping for this contract. If an OAuth client points at an access token manager that has no mapping, PingFederate fails at the first hit of `/as/authorization.oauth2` with "There are no authentication methods available for OAuth," before the user ever reaches IDMe. The access token manager does not have to be the tenant default.

#### Create the OpenID Connect policy

Navigate to **Applications > OAuth > OpenID Connect Policy Management** and select **Add Policy**

On the **Manage Policy** tab, enter a **Policy ID** and **Name** (for example, `idmeOidcPolicy`), select your access token manager under **Access Token Manager**, set **ID Token Lifetime** (this example uses 5 minutes), and check **Include User Info in ID Token**

> **Note**
>
> Without Include User Info in ID Token checked, the ID token contains only `sub`, and the other attributes are available only from PingFederate's UserInfo endpoint.

Select **Next**

On the **Attribute Contract** tab, extend it with the attributes you want in the ID token, then select **Next**

On the **Attribute Scopes** tab, map your scope (for example, `nist_ial2_aal2`) to the attributes it releases, then select **Next**

> **Note**
>
> Each scope maps to the attributes it releases. For example, mapping `nist_ial2_aal2` to release all eight IDMe attributes means that if the application requests only `openid`, the ID token contains only `sub`, even though the user still fully verified at IDMe.

On the **Attribute Sources & User Lookup** tab, leave it empty and select **Next**

On the **Contract Fulfillment** tab, for each attribute set **Source** to **Access Token** and **Value** to the matching access token manager attribute, then select **Next**

On the **Issuance Criteria** tab, select **Next**. On the **Summary** tab, select **Save**

On the policy list, set it as the default if it is your only OpenID Connect policy

### Register the target application as an OAuth client

Now define an OAuth client in PingFederate that represents your application. Without one, PingFederate has no place to send the final ID token after validating IDMe's response.

Navigate to **Applications > OAuth > Clients** and select **Add Client**

Configure the client: set **Client ID** (for example, `my-web-app`) and **Name** (for example, `My Web App`); set **Client Authentication** to **Client Secret**, select **Generate Secret**, and copy it for use in your target application's OIDC configuration

Set **Redirect URIs** to the application's callback (for example, `https://app.example.com/callback`), and set **Allowed Grant Types** to **Authorization Code**

Set **Default Access Token Manager** to your access token manager and check **Restrict to Default Access Token Manager**. Under **OpenID Connect**, set **Policy** to the OpenID Connect policy you created

Check **Bypass Approval Page** if you do not want PingFederate's consent screen to appear during sign-in from PingFederate to the target application, then select **Save**

Configure your target application with the **Issuer / discovery** value `https://<pf-runtime-host>:9031/.well-known/openid-configuration`, the **Client ID** and **Client Secret** from this step, and a **Scope** of `openid <your scope>` (for example, `openid nist_ial2_aal2`)

### Store IDMe users in a directory (optional)

> **Note**
>
> Skip this step unless you want PingFederate to create, and keep updated, a user account in a directory for each IDMe user who logs in. Turning on Just-in-Time (JIT) provisioning does not change what the target application receives.

You may already have a directory behind PingFederate, typically PingDirectory or Active Directory, sometimes OpenLDAP or a SQL database. With JIT provisioning, PingFederate creates the user in that directory at the first IDMe sign-in and can update the account at every later sign-in. These steps were tested with OpenLDAP over LDAPS.

> **Important**
>
> The certificate used in these example commands is for local setup purposes only. Use a trusted certificate from an official CA in production environments.

(LDAPS or StartTLS only) Set up the directory's certificate and trust it in PingFederate. To create a test certificate on macOS for a local test directory, run the following commands in Terminal, replacing `ldap.example.com` with the hostname you enter in **Hostname(s)**.

Create a test certificate authority (CA):

```text
openssl req -x509 -newkey rsa:2048 -nodes -days 825 -sha256 \
-keyout ldap-ca.key -out ldap-ca.crt -subj "/CN=Example LDAP Test CA" \
-addext "basicConstraints=critical,CA:TRUE" \
-addext "keyUsage=critical,keyCertSign,cRLSign"

```

Create the directory's private key and certificate request:

```text
openssl req -newkey rsa:2048 -nodes -sha256 \
  -keyout ldap.key -out ldap.csr -subj "/CN=ldap.example.com"

```

Sign the directory's certificate with the CA:

```text
printf "subjectAltName=DNS:ldap.example.com\nextendedKeyUsage=serverAuth\n" > ldap.ext
openssl x509 -req -in ldap.csr -CA ldap-ca.crt -CAkey ldap-ca.key \
  -CAcreateserial -days 825 -sha256 -extfile ldap.ext -out ldap.crt

```

Check the result, which should print "ldap.crt: OK":

```text
openssl verify -CAfile ldap-ca.crt ldap.crt

```

Configure the directory to use `ldap.crt` and `ldap.key` for LDAPS, then import `ldap-ca.crt` into PingFederate: navigate to **Security > Certificate & Key Management > Trusted CAs**, select **Import**, choose `ldap-ca.crt` (in PEM format), review the certificate on the **Summary** window, and select **Save**

> **Note**
>
> Only PingFederate needs to trust `ldap-ca.crt`. You do not need to add it to the macOS Keychain, since PingFederate checks the directory's certificate against its own Trusted CAs list and its Java runtime, not the operating system's trust store. Importing certificates into PingFederate requires an administrator account with the Crypto Admin role.

> **Important**
>
> Keep `ldap-ca.key` private, since anyone with it can create certificates that PingFederate will trust. For production, use a certificate from your organization's CA instead; if that CA is already trusted by PingFederate's Java runtime, you do not need to import it.

Connect PingFederate to the directory: navigate to **System > Data & Credential Stores > Data Stores** and select **Add New Data Store**. On the **Data Store Type** tab, select **Directory (LDAP)** and select **Next**

On the **LDAP Configuration** tab, configure the following: **Hostname(s)** with the directory's host and port (for example, `ldap.example.com:636` for LDAPS); **Connection Security** set to **LDAPS** or **StartTLS** (choose **None** only for a local test directory, and ensure the hostname matches the certificate); leave **Use DNS SRV Record** and **Follow LDAP Referrals** unchecked; **LDAP Type** set to **PingDirectory**, **Active Directory**, or **Generic** for OpenLDAP; **Authentication Method** set to **Simple**; and **Credential Storage** set to **Internally Managed**.

For **User DN** and **Password**, use a dedicated service account that PingFederate signs in to the directory as; do not use the directory administrator account. Give the account permission to search, read, create, and modify user entries only under the base DN where JIT creates users (for example, `ou=people,dc=example,dc=com`). For OpenLDAP, create the service account and grant it those rights before this step:

```text
dn: ou=service-accounts,dc=example,dc=com
objectClass: organizationalUnit
ou: service-accounts

dn: cn=pf-jit,ou=service-accounts,dc=example,dc=com
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: pf-jit
description: PingFederate JIT provisioning
userPassword: <password hash from slappasswd>

```

```text
dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcAccess
olcAccess: {1}to dn.subtree="ou=people,dc=example,dc=com"
  by dn.exact="cn=pf-jit,ou=service-accounts,dc=example,dc=com" write by * break

```

> **Note**
>
> Your database name (`{1}mdb`) and rule position (`{1}`) may differ; the rule must come before the directory's general access rules. Enter `cn=pf-jit,ou=service-accounts,dc=example,dc=com` as the User DN, with the account's password.

Select **Test Connection** to confirm PingFederate can reach the directory and sign in with that account, then select **Next**

On the **Summary** tab, review the settings and select **Save**. PingFederate names the data store after its hostname (for example, `openldap`)

Turn on JIT provisioning for the IDMe connection: navigate to **Authentication > Integration > IdP Connections** and select your IDMe connection (for example, `ID.me Sandbox`). On the **Connection Options** tab, check **JIT Provisioning**. Select **Next** through **General Info** and **Browser SSO**, which are already configured, to the **JIT Provisioning** tab, then select **Configure JIT Provisioning**

On the **User Repository** tab, under **Active Data Store**, select the data store you created (listed by its hostname, for example, `openldap`), then select **Next**

On the **Location** tab, enter the **Base DN** where users are created (for example, `ou=people,dc=example,dc=com`), then select **Next**

On the **Unique User ID** tab, in **Filter**, enter `uid=${sub}` without parentheses, so IDMe's `sub` is the user key, then select **Next**

On the **Attributes** tab, for each directory attribute select its **Root Object Class**, then the attribute, and select **Add Attribute**. This example uses `inetOrgPerson` for `uid`, `givenName`, and `mail`; `organizationalPerson` for `street`, `l`, `st`, `postalCode`, and `telephoneNumber`; `person` for `sn` and `cn`; and `top` for `objectClass`, which every new directory entry needs. Select **Next**

> **Note**
>
> Added attributes are listed alphabetically, not at the bottom, so look for each one in its sorted position (for example, `objectClass` appears between `mail` and `postalCode`). Use Add Attribute for each row; Save saves the whole connection, not the row you are building.

On the **Attribute Fulfillment** tab, map each directory attribute from **Provider Claims**: `uid` from `sub`, `givenName` from `fname`, `sn` from `lname`, `cn` and `mail` from `email`, `street` from `street`, `l` from `city`, `st` from `state`, `postalCode` from `zip`, `telephoneNumber` from `phone`, and `objectClass` set to `inetOrgPerson` as **Text**. Match these to your directory schema, then select **Next**

On the **Event Trigger** tab, select **All Claims**, so PingFederate creates the account at the first sign-in and updates it with the latest IDMe attributes at every sign-in, then select **Next**

> **Note**
>
> The default, Only Claims Containing a New User ID, creates the account once and never updates it. Use it only if other systems maintain those directory attributes after the account is created.

On the **Error Handling** tab, select **Send the User's Attributes to the Target Application**, so a directory failure does not block sign-in, then select **Next**. On the **Summary** tab, review the settings and select **Done**

Select **Next** through **Credentials**, keeping the defaults, to the **Activation & Summary** tab, and select **Save**

## 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:

**Redirect URIs** \
The PingFederate redirect URI, copied from the IDMe IdP connection's Activation & Summary tab, must be added to your IDMe Application's allowed redirect URIs.

> **Info**
>
> If you enable PKCE on the IDMe Application, PingFederate's Enable PKCE setting on the IdP connection's OpenID Provider Info must match.

**Policy handle name** \
Confirm the IDMe policy handle (for example, `nist_ial2_aal2`). This value must match the Scopes value on the PingFederate IdP connection, together with `openid`, and determines the identity verification level and attributes IDMe returns.

## Test the integration

There are two ways to test the integration.

### Option 1: Sign in through the target application

Start the target application and select its sign-in button. The application sends you to PingFederate's authorization endpoint

PingFederate redirects you to IDMe. Complete authentication and identity verification according to your IDMe Policy settings

IDMe redirects you back to PingFederate, which redirects you to the application's callback

The application exchanges the code at PingFederate's token endpoint and receives a PingFederate-issued ID token. Its `iss` value is your PingFederate base URL, not IDMe

> **Note**
>
> If you configured JIT provisioning, also confirm that PingFederate created the user in your directory, for example by running `ldapsearch` filtered on `uid=<the IDMe sub>`. The ID token the application receives is the same with or without JIT provisioning.

Confirm the ID token contains every attribute you mapped

### Option 2: Manually construct the authorization URL

Use this format:

```text
https://<pf-runtime-host>:9031/as/authorization.oauth2
  ?client_id=<your PingFederate OAuth client ID>
  &redirect_uri=<your URL-safe redirect URI for target app>
  &response_type=code
  &scope=openid%20<your scope>
  &state=<any random characters you choose>
  &nonce=<any random characters you choose>

```

For example:

```text
https://localhost:9031/as/authorization.oauth2
  ?client_id=my-web-app
  &redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
  &response_type=code
  &scope=openid%20nist_ial2_aal2
  &state=xyz789
  &nonce=abc123

```

> **Important**
>
> Before you sign in, export PingFederate's runtime certificate so curl can verify the connection to the token endpoint: navigate to **Security > Certificate & Key Management > SSL Server Certificates**, select **Action > Export** for the certificate PingFederate uses for its runtime (port 9031), keep **Certificate Only** selected, and select **Export**. Save the file as `pf-runtime.pem`. Do not use `curl -k` instead, since it skips certificate checks and would send your client secret to any server.

Paste the URL into a browser on one line, without line breaks. Complete IDMe sign-in; the browser lands on the redirect URI with a `code` parameter. (If the application is not running, the page fails to load, but the code is still in the address bar.) Within 60 seconds, exchange the code:

```text
curl --cacert pf-runtime.pem -u "<client_id>:<client_secret>" \
  -d grant_type=authorization_code \
  -d code=<code from the address bar> \
  -d redirect_uri=<the same redirect URI, not encoded> \
  https://<pf-runtime-host>:9031/as/token.oauth2

```

Decode the `id_token` in the response and check the claims.

## Troubleshooting

**After authenticating at IDMe, PingFederate shows an error or no attributes come through**

Check that the IDMe Policy handle matches the handle in the IdP connection's Scopes field. A mismatch is the most common cause of failures on the IDMe leg.

**error=server_error\&error_description=There are no authentication methods available for OAuth**

This error appears at the first hit