Welcome to ID.me for developers! If you are interested in integrating ID.me, you are in the right place. Here we will cover how to get started implementing ID.me.

OpenID Connect Integration

ID.me uses OAuth to provide authorized access to its API. We currently use OAuth 2 draft-22 This section describes how you can use the OAuth 2 protocol to to gain access to a user's group affiliation data. Requests to retrieve user data require an access_token that is used to query ID.me's REST API. These tokens are unique to a user and should be stored securely. An access_token expire 5 minutes after being issued.


ID.me supports both a full page redirect to the authorization endpoint as well as a popup window. Once you have registered an application, sample code and documentation will be available on the application details page. The ability to upload your company logo and customize the colors of the buttons on the ID.me screen are also available.

Step 1: Direct Users To Authorization Endpoint

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

Authorization Endpoint

<div id="idme-verification">
  <a href="https://api.id.me/oauth/authorize?client_id=[YOUR_CLIENT_ID]&redirect_uri=[YOUR_REDIRECT_URI]&response_type=code&scope=openid pbr&state=488e864b&nonce=123456">
    <img src="https://s3.amazonaws.com/idme/developer/idme-buttons/assets/img/signin.svg" height="50"/>
  </a>
  <p>
    ID.me is our trusted technology partner in helping to keep your personal information safe. They specialize in digital identity protection and help
    us make sure you're you—and not someone pretending to be you—before we give you access to your information.
    <a href="https://www.id.me/about">Learn more about ID.me</a>.
  </p>
</div>

Authorization Endpoint

The api.id.me/oauth/authorize endpoint is used begin an authorization to allow a user to authenticate and allow an organization get access to a user's verification credential.

Parameters

Name Description
client_id The client identifier received during app registration. It is automatically generated and located in your application dashboard.
scope A parameter that defines the policy you are requesting permission to access.
Supported values include:
  • openid
  • redirect_uri Where the user gets redirected after an authorizing an app. Set by the developer within the application dashboard.
    response_type Determines the authorization type.
    Supported values include:
  • code
  • token
  • id_token
  • code id_token
  • code token
  • id_token token
  • code id_token token
  • state An optional parameter to carry through any server-specific state you need to, for example, protect against CSRF issues. This param will be passed back to your redirect URI untouched.
    op An optional parameter that triggers sign in or sign up once redirected to ID.me.
    Supported values include:
  • signin
  • signup
  • nouce An optional parameter value needs to include per-session state and be unguessable to attackers. One method to achieve this for Web Server Clients is to store a cryptographically random value as an HttpOnly session cookie and use a cryptographic hash of the value as the nonce parameter. In that case, once in the returned ID Token is compared to the hash of the session cookie to detect ID Token replay by third parties. A related method applicable to JavaScript Clients is to store the cryptographically random value in HTML5 local storage and use a cryptographic hash of this value.

    Step 2: Receive The Authorization Code

    When the user completes the authorization process on ID.me, we will redirect the user to your redirect_uri with the authorization code parameter appended.

    Redirect URI with code example

    https://example.com/callback? code=488e864b

    Step 3: Exchange Authorization Code For Token Payload

    Using the authorization code from the previous step, send a request to ID.me's Token Endpoint to retrieve the payload containing your access_token and refresh token each token's expiration can be found in the payload.

    CURL Example

    curl -X POST -d "code=488e864b&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&redirect_uri=REDIRECT_URI&grant_type=authorization_code" https://api.id.me/oauth/token
    Endpoint
    https://api.id.me/oauth/token
    HTTP Request Method
    POST
    Response Content Type
    application/json

    Parameters

    Name Description
    code The authorization code that you received in the previous step.
    client_id The client identifier received during app registration. It is automatically generated and located in your application dashboard.
    client_secret A secret identifier received during app registration. It is automatically generated and located in your application dashboard.
    redirect_uri Where the user gets redirected after an authorizing an app. Set by the developer within the application dashboard.
    grant_type The only supported value is currently authorization_code

    Step 4: Obtain ID Token

    Example Payload

    {
      "access_token": "a0b1c2d3f4g5h6i7j8k9l0m1n2o3p4q5",
      "token_type": "bearer",
      "expires_in": "300",
      "refresh_token": "e7c77fe1fd5ece9aaccb129f6dd39431",
      "refresh_expires_in": "604800",
      "scope": "http://idmanagement.gov/ns/assurance/ial/2/aal/2/epcs",
      "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IktBTGVzSUpVVTRuQ0FjLVJTdTJkS0xkYkgtQmFrdXRnekE1VjdoQm9RUm8ifQ.eyJpc3MiOiJodHRwczovL2FwaS5p\nZG1lbGFicy5jb20vb2lkYyIsInN1YiI6ImYxNjljMzRkMDA3YjQ1MTBhNzNiYTc5OThjMDgxZWEwIiwiYXVkIjoiZTE3OWUzNTc3NTAzMjBlMmU2NTJjODBiNjFjNGRjMDIiLCJleHAiOj\nE2MjU1MTI3ODQsImlhdCI6MTYyNTQ5NDc4NCwiZW1haWwiOiJ0ZXN0aW5nQGlkLm1lIiwiZm5hbWUiOiJWRVJPTklDQSIsImxuYW1lIjoiUEVSU0lOR0VSIiwiemlwIjoiMjIxMDIiLCJ1\ndWlkIjoiZjE2OWMzNGQwMDdiNDUxMGE3M2JhNzk5OGMwODFlYTAifQ.QwdnbAn6kbnzSvASa8qEMTJO-T-jzkJAfJdLViX188N2ny1DLBjn1AxgsydXmnzeyCtfv9Mn-rjLFtsEAPXMbWo\nA5maU0Lqt03hbSEbvevksr6xzD0j9mzQdWb3YXHkSS-A3dKkl4KM5TiO7BY8W5Xmhp0YivtcW2_C24xdxukYBgR1Y6lmjaKS3SGQRkjO31mj8_qxlAP4RuC9U2cmHx-w2HYVJfwpyauzmM\n8uo6CD3Ql3qCP88bcyJtF2O9cEpvW9E47CcaueGLjBF9_Qe0u1IWzcX77rCTnxMounfjmYDn7Md0JAl6-Q6E23yu-Zibg8CFytmDDm4pGbEA7g8BA"
    }

    Parameters

    Name Description
    id_token A JSON Web Token(JWT)
    access_token A credential that is used with every API call, so ID.me recognizes that you have authorization to make that request.
    token_type Represents how an access_token will be generated and presented for resource access calls.
    expires_in Describes the lifetime of the access_token in seconds.
    refresh_token Refresh tokens contain the information required to obtain a new access_token.
    refresh_expires_in Describes the lifetime of the refresh_token in seconds.
    scope Defines the policy you are requesting permission to access

    Example Encoded ID Token

    eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IktBTGVzSUpVVTRuQ0FjLVJTdTJkS0xkYkgtQmFrdXRnekE1VjdoQm9RUm8ifQ.eyJpc3MiOiJodHRwczovL2FwaS5p
    ZG1lbGFicy5jb20vb2lkYyIsInN1YiI6ImYxNjljMzRkMDA3YjQ1MTBhNzNiYTc5OThjMDgxZWEwIiwiYXVkIjoiZTE3OWUzNTc3NTAzMjBlMmU2NTJjODBiNjFjNGRjMDIiLCJleHAiOj
    E2MjU1MTI3ODQsImlhdCI6MTYyNTQ5NDc4NCwiZW1haWwiOiJ0ZXN0aW5nQGlkLm1lIiwiZm5hbWUiOiJWRVJPTklDQSIsImxuYW1lIjoiUEVSU0lOR0VSIiwiemlwIjoiMjIxMDIiLCJ1
    dWlkIjoiZjE2OWMzNGQwMDdiNDUxMGE3M2JhNzk5OGMwODFlYTAifQ.QwdnbAn6kbnzSvASa8qEMTJO-T-jzkJAfJdLViX188N2ny1DLBjn1AxgsydXmnzeyCtfv9Mn-rjLFtsEAPXMbWo
    A5maU0Lqt03hbSEbvevksr6xzD0j9mzQdWb3YXHkSS-A3dKkl4KM5TiO7BY8W5Xmhp0YivtcW2_C24xdxukYBgR1Y6lmjaKS3SGQRkjO31mj8_qxlAP4RuC9U2cmHx-w2HYVJfwpyauzmM
    8uo6CD3Ql3qCP88bcyJtF2O9cEpvW9E47CcaueGLjBF9_Qe0u1IWzcX77rCTnxMounfjmYDn7Md0JAl6-Q6E23yu-Zibg8CFytmDDm4pGbEA7g8BA

    Step 5: Verify User Token

    Now, we need to verify that the ID Token sent was from the correct place by validating the JWT's signature. headers.payload.signature


    This token is cryptographically signed with the RS256 algorithim. We'll use the public key of the OpenID Connect server to validate it. In order to do that, we'll fetch the public key from https://api.idmelabs.com/oidc/.well-known/jwks, which is found in the discovery document or configuration menu options.

    Ruby Example

    require "base64"
    
    encoded_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IktBTGVzSUpVVTRuQ0FjLVJTdTJkS0xkYkgtQmFrdXRnekE1VjdoQm9RUm8ifQ.eyJpc3MiOiJodHRwczovL2FwaS5p
    ZG1lbGFicy5jb20vb2lkYyIsInN1YiI6ImYxNjljMzRkMDA3YjQ1MTBhNzNiYTc5OThjMDgxZWEwIiwiYXVkIjoiZTE3OWUzNTc3NTAzMjBlMmU2NTJjODBiNjFjNGRjMDIiLCJleHAiOj
    E2MjU1MTI3ODQsImlhdCI6MTYyNTQ5NDc4NCwiZW1haWwiOiJ0ZXN0aW5nQGlkLm1lIiwiZm5hbWUiOiJWRVJPTklDQSIsImxuYW1lIjoiUEVSU0lOR0VSIiwiemlwIjoiMjIxMDIiLCJ1
    dWlkIjoiZjE2OWMzNGQwMDdiNDUxMGE3M2JhNzk5OGMwODFlYTAifQ.QwdnbAn6kbnzSvASa8qEMTJO-T-jzkJAfJdLViX188N2ny1DLBjn1AxgsydXmnzeyCtfv9Mn-rjLFtsEAPXMbWo
    A5maU0Lqt03hbSEbvevksr6xzD0j9mzQdWb3YXHkSS-A3dKkl4KM5TiO7BY8W5Xmhp0YivtcW2_C24xdxukYBgR1Y6lmjaKS3SGQRkjO31mj8_qxlAP4RuC9U2cmHx-w2HYVJfwpyauzmM
    8uo6CD3Ql3qCP88bcyJtF2O9cEpvW9E47CcaueGLjBF9_Qe0u1IWzcX77rCTnxMounfjmYDn7Md0JAl6-Q6E23yu-Zibg8CFytmDDm4pGbEA7g8BA"
    
    encoded_headers = encoded_token.split[0]
    
    plain_headers = Base64.decode64(encoded_headers)
    

    Decoded Header Payload Example

    {
      "typ": "JWT",
      "alg": "RS256",
      "kid": "KALesIJUU4nCAc-RSu2dKLdbH-BakutgzA5V7hBoQRo"
    }

    Parameters

    Name Description
    typ The Type Header Parameter is used by JWT applications to declare the media type of this complete JWT.
    alg The Algorithm Header Parameter is used by JWT applications to declare the algorithm type of this complete JWT.
    kid An optional header claim which holds a key identifier, particularly useful when you have multiple keys to sign the tokens and you need to look up the right one to verify the signature.

    Step 6: Decode ID Token For User Payload

    Protected REST endpoints can be access by making HTTP requests with the access token for a given user. The ID.me server will validate the access token to ensure it has not expired and that its scope covers the requested resource.

    Ruby Example

    require "base64"
    
    encoded_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IktBTGVzSUpVVTRuQ0FjLVJTdTJkS0xkYkgtQmFrdXRnekE1VjdoQm9RUm8ifQ.eyJpc3MiOiJodHRwczovL2FwaS5p
    ZG1lbGFicy5jb20vb2lkYyIsInN1YiI6ImYxNjljMzRkMDA3YjQ1MTBhNzNiYTc5OThjMDgxZWEwIiwiYXVkIjoiZTE3OWUzNTc3NTAzMjBlMmU2NTJjODBiNjFjNGRjMDIiLCJleHAiOj
    E2MjU1MTI3ODQsImlhdCI6MTYyNTQ5NDc4NCwiZW1haWwiOiJ0ZXN0aW5nQGlkLm1lIiwiZm5hbWUiOiJWRVJPTklDQSIsImxuYW1lIjoiUEVSU0lOR0VSIiwiemlwIjoiMjIxMDIiLCJ1
    dWlkIjoiZjE2OWMzNGQwMDdiNDUxMGE3M2JhNzk5OGMwODFlYTAifQ.QwdnbAn6kbnzSvASa8qEMTJO-T-jzkJAfJdLViX188N2ny1DLBjn1AxgsydXmnzeyCtfv9Mn-rjLFtsEAPXMbWo
    A5maU0Lqt03hbSEbvevksr6xzD0j9mzQdWb3YXHkSS-A3dKkl4KM5TiO7BY8W5Xmhp0YivtcW2_C24xdxukYBgR1Y6lmjaKS3SGQRkjO31mj8_qxlAP4RuC9U2cmHx-w2HYVJfwpyauzmM
    8uo6CD3Ql3qCP88bcyJtF2O9cEpvW9E47CcaueGLjBF9_Qe0u1IWzcX77rCTnxMounfjmYDn7Md0JAl6-Q6E23yu-Zibg8CFytmDDm4pGbEA7g8BA"
    
    encoded_payload = encoded_token.split[1]
    
    plain_payload = Base64.decode64(encoded_payload)
    

    Payload Example

    {
      "iss": "https://api.idmelabs.com/oidc",
      "sub": "f169c34d007b4510a73ba7998c081ea0",
      "aud": "8749d197447c364b219afbd4b613ebd0",
      "exp": 1616364069,
      "iat": 1616346069,
      "email": "kristi.mcclure@id.me",
      "fname": "Kristi",
      "lname": "McClure",
      "street": "83637 Frami Bridge",
      "city": "Sharikafort",
      "state": "Delaware",
      "zip": "69426",
      "birthdate": "1971-01-13",
      "uuid": "d733a89e2e634f04ac2fe66c97f71612"
    }

    Parameters

    Name Description
    iss The Type Header Parameter is used by JWT applications to declare the media type of this complete JWT.
    sub The Algorithm Header Parameter is used by JWT applications to declare the algorithm type of this complete JWT.
    aud An optional header claim which holds a key identifier, particularly useful when you have multiple keys to sign the tokens and you need to look up the right one to verify the signature.
    exp An optional header claim which holds a key identifier, particularly useful when you have multiple keys to sign the tokens and you need to look up the right one to verify the signature.
    iat An optional header claim which holds a key identifier, particularly useful when you have multiple keys to sign the tokens and you need to look up the right one to verify the signature.
    uuid An optional header claim which holds a key identifier, particularly useful when you have multiple keys to sign the tokens and you need to look up the right one to verify the signature.

    Step 7: Exchange Access Token For User Payload

    Protected REST endpoints can be access by making HTTP requests with the access token for a given user. The ID.me server will validate the access token to ensure it has not expired and that its scope covers the requested resource.

    CURL Example

    curl -X GET -d "access_token=488e864b" https://api.id.me/api/public/v3/attributes.json
    Endpoint
    https://api.id.me/api/public/v3/attributes.json
    HTTP Request Method
    GET
    Response Content Type
    application/json

    Parameters

    Name Description
    access_token A credential that is used with every API call, so ID.me recognizes that you have authorization to make that request.
    callback If you're writing an AJAX application, require a JSONP response, and would like to wrap our response with a callback, all you have to do is specify a callback parameter with the API call.

    Example Payload

    {
      "iss": "https://api.idmelabs.com/oidc",
      "sub": "f169c34d007b4510a73ba7998c081ea0",
      "aud": "8749d197447c364b219afbd4b613ebd0",
      "exp": 1616364069,
      "iat": 1616346069,
      "email": "aracelis.weimann@id.me",
      "fname": "Aracelis",
      "lname": "Weimann",
      "street": "41891 O'Connell Bypass",
      "city": "Lindport",
      "state": "Connecticut",
      "zip": "26387",
      "birthdate": "1983-06-20",
      "uuid": "d733a89e2e634f04ac2fe66c97f71612"
    }
    Requirements

    Please follow the two steps outlined below. Note that you are responsible for ensuring that all implementations of the ID.me brand assets comply with accessibility requirements (example: Section 508 minimum color contrast requirements & WCAG guidelines). Visit https://webaim.org for more information.

    Step 1

    Verify your integration meets ID.me brand requirements and guidelines. For reference, please visit https://developers.id.me/brand-assets.

    Step 2

    Verify your integration makes an API request upon retrieving the access_token from ID.me.

    Step 3

    Verify all test credentials provided are generating the expected results based on configuration.

    Step 4

    Verify your platform digests and maps the verification data to the appropriate user and presents success messaging.

    Step 5

    Verify your ID.me application is in production mode and does not display "Sandbox Mode" to users.

    Errors

    If the user denies the access request or if the request is invalid, the client will be informed using the following parameters appended to the redirect uri:

    Parameters

    Name Description
    error A single error code as described below.
    error_description A human-readable text providing additional information, used to assist in the understanding and resolution of the error occurred.
    error_uri A URI identifying a human-readable web page with information about the error, used to provide the end-user with additional information about the error.

    Codes

    Code Description
    invalid_request The request is missing a required parameter, includes an unsupported parameter or parameter value, or is otherwise malformed.
    invalid_client The client identifier provided is invalid.
    invalid_redirect_uri The redirection URI provided does not match a pre-registered value.
    access_denied The end-user or authorization server denied the request.
    unsupported_response_type The requested response type is not supported by the authorization server.
    invalid_scope The requested scope is invalid, unknown, or malformed.