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

# Integration

> SAML 2.0 integration steps

> **Info**
>
> **Estimated task time:** \~15 minutes

## Create a developer account

Sign up for a developer account to access additional developer documentation and set the stage for a new integration.
There is no need to go through the entire setup process. Your ID.me team will assist with configuring a new SAML integration.

## Exchange and ingest IdP and SP Metadata

Once an account is created, SAML metadata (along with keys) must be exchanged to ensure proper configuration of the endpoints.

[Sandbox IdP Metadata](https://api.idmelabs.com/saml/metadata/provider)

[Production IdP Metadata](https://api.id.me/saml/metadata/provider)

> **Warning**
>
> Preserving formatting and whitespace is critical when importing any XML metadata

The metadata document describes the IdP to a SP, including the following elements:

* The endpoint addresses for communication
* The X.509 certificates being used to sign and encrypt SAML assertions
* The SAML bindings supported by the service provider

## Direct users to AuthNRequest

The client app must send the user to the authorization endpoint in order to initiate the SAML process. At the authorization endpoint, the user authenticates on the ID.me server and then grants or denies access to the app. See the examples below:

#### Sandbox

```html
https://api.idmelabs.com/saml/SingleSignOnService?EntityID=<EntityID>&Binding=<binding>&AuthnContext=<policy-handle></policy-handle>
```

#### Production

```html
https://api.id.me/saml/SingleSignOnService?EntityID=<EntityID>&Binding=<binding>&AuthnContext=<policy-handle></policy-handle>
```

**Parameters**

| Name         | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| EntityID     | An EntityID is a globally unique name for a SAML entity, either an Identity Provider (IdP) or a Service Provider (SP).                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| Binding      | The ID.me IdP SAML service supports HTTP POST and HTTP Redirect binding                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| NameIDFormat | The ID.me IdP SAML service supports the following NameID formats:  - `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:1.1:nameid-format:unspecified`  - `urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos`  - `urn:oasis:names:tc:SAML:2.0:nameid-format:entity`  - `urn:oasis:names:tc:SAML:2.0:nameid-format:persistent`  - `urn:oasis:names:tc:SAML:2.0:nameid-format:transient`  - `urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted` |
| AuthnContext | The ID.me IdP SAML service supports invoking different authentication and verification policies on a per-application or per-request basis. The policy name is required to be passed along within the element.                                                                                                                                                                                                                                                                                                                                                                                                               |
| RelayState   | RelayState is an optional parameter that identifies a specified destination URL your users will access after signing in with SSO.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |

## ID.me XML Signature

All ID.me SAML messages are digitally signed. This includes all requests, assertions and metadata. The XML signature is contained within the element.
The signature serves as proof that only the IdP could have signed the element, and also to guarantee the integrity of the assertion. ID.me signs messages using SHA256, SHA384 and SHA512 algorithms.

```xml
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_67016ed111db-4bce-b065-45bcd564cd0e"
Version="2.0"
IssueInstant="2015-02-04T22:30:48Z"
Destination="..."
Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified"
InResponseTo="_6a12a9ef28696226601602f669545e7ebb1c80d19a">
<saml:Issuer>api.id.me</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>...</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
<ds:KeyInfo>...</ds:KeyInfo>
</ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<saml:Assertion ID="_d20913189703-4b8b-97f4-c96ef7b1dccd" Version="2.0" IssueInstant="2015-02- 04T22:30:46Z">...</saml:Assertion>
</samlp:Response>
```

## ID.me XML Encryption

ID.me requires all SAML assertions to be encrypted. This helps protect any confidential data in the response.
The encrypted assertion is contained within the element. ID.me supports using AES-128, AES-192 and AES-256 as message encryption algorithms.

```xml
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
ID="_46965880a3f0-461b-bc99-5ba262e812b3"
Version="2.0"
IssueInstant="2015-02-04T22:46:25Z"
Destination="..."
Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified"
InResponseTo="_8bf72df7b4922883b1adad99926a0293c6e135b6da">
<saml:Issuer>idp.example.com</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...</ds:Signature>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
</samlp:Status>
<saml:EncryptedAssertion>
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="_43a44a93ad36-4616-
b1e6-2a96d4f3134c" Type="http://www.w3.org/2001/04/xmlenc#Element">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<xenc:EncryptedKey Id="_78c2d92d0c46-4820-b8f0-52698580d7c9">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" />
<xenc:CipherData>
  <xenc:CipherValue>...</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedKey>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>...</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</saml:EncryptedAssertion>
</samlp:Response>
```

## Receive response signed and encrypted assertion

```xml
<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"  
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" ID="_8e8dc5f69a98cc4c1ff3427e5ce34606fd672f91e6" Version="2.0" IssueInstant="2014-07-17T01:01:48Z" Destination="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685">
  <saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
  <samlp:Status>
    <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
  </samlp:Status>
  <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" ID="_d71a3a8e9fcc45c9e9d248ef7049393fc8f04e5f75" Version="2.0" IssueInstant="2014-07-17T01:01:48Z">
    <saml:Issuer>http://idp.example.com/metadata.php</saml:Issuer>
    <saml:Subject>
      <saml:NameID SPNameQualifier="http://sp.example.com/demo1/metadata.php" Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">_ce3d2948b4cf20146dee0a0b3dd6f69b6cf86f62d7</saml:NameID>
      <saml:SubjectConfirmation
Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
        <saml:SubjectConfirmationData NotOnOrAfter="2024-01-18T06:21:48Z" Recipient="http://sp.example.com/demo1/index.php?acs" InResponseTo="ONELOGIN_4fee3b046395c4e751011e97f8900b5273d56685"/>
      </saml:SubjectConfirmation>
    </saml:Subject>
    <saml:Conditions NotBefore="2014-07-17T01:01:18Z" NotOnOrAfter="2024-01-18T06:21:48Z">
      <saml:AudienceRestriction>
        <saml:Audience>http://sp.example.com/demo1/metadata.php</saml:Audience>
      </saml:AudienceRestriction>
    </saml:Conditions>
    <saml:AuthnStatement AuthnInstant="2014-07-17T01:01:48Z" SessionNotOnOrAfter="2024-07-17T09:01:48Z" SessionIndex="_be9967abd904ddcae3c0eb4189adbe3f71e327cf93">
      <saml:AuthnContext>
        <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
      </saml:AuthnContext>
    </saml:AuthnStatement>
    <saml:AttributeStatement>
      <saml:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xsi:type="xs:string">test</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="mail" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xsi:type="xs:string">test@example.com</saml:AttributeValue>
      </saml:Attribute>
      <saml:Attribute Name="eduPersonAffiliation" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic">
        <saml:AttributeValue xsi:type="xs:string">users</saml:AttributeValue>
        <saml:AttributeValue xsi:type="xs:string">examplerole1</saml:AttributeValue>
      </saml:Attribute>
    </saml:AttributeStatement>
  </saml:Assertion>
</samlp:Response>
```

## Initiate business logic

After decrypting the assertion invoke your Business logic to use the Assertion and guide the user to the next steps per the response received.

**Note:** If an attribute is missing, the system will return a `null` value

> **Best practice**
>
> It is best practice to develop code in a manner that gracefully handles variations in data. For example, a name that contains a hyphen.

**Payload specification**

| Handle           | Name              | Max Length | Null possible | Comment                                                                                   |
| ---------------- | ----------------- | ---------- | ------------- | ----------------------------------------------------------------------------------------- |
| email            | Email             | 255        | No            |                                                                                           |
| uuid             | Unique identifier | 32         | No            |                                                                                           |
| fname            | First Name        | 255        | Yes           | Individuals with only 1 legal name would have that name placed in the Last Name attribute |
| mname            | Middle Name       | 255        | Yes           |                                                                                           |
| lname            | Last Name         | 255        | No            |                                                                                           |
| birth_date       | Birth Date        | 10         | No            | Date format: YYYY-MM-DD                                                                   |
| social           | Full SSN          | 9          | Yes           |                                                                                           |
| itin             | Full ITIN         | 9          | Yes           |                                                                                           |
| ssn_itin         | Full SSN or ITIN  | 9          | Yes           | If a member has both SSN and ITIN, SSN takes precedence                                   |
| street           | Street            | 255        | Yes           | 123 Main St Apt 1a                                                                        |
| street1          | Street1           | 255        | Yes           | 123 Main St                                                                               |
| street2          | Street2           | 255        | Yes           | Apt 1a                                                                                    |
| city             | City              | 255        | Yes           |                                                                                           |
| state            | State             | 255        | Yes           | Abbreviation or full state                                                                |
| zip              | Postal Code       | 10         | Yes           | US Postal format: 00000, 00000-0000, or 000000000                                         |
| phone            | Phone             | 11         | Yes           | Phone format: 10000000000                                                                 |
| emails_confirmed | Confirmed Emails  | n/a        | No            | Array of string values                                                                    |

> **Note**
>
> International users will have a higher rate of Null values for the address attributes.
>
> Additional attributes may be available. Discuss your use case with your ID.me team.