OpenID Connect
ID.me uses OpenID Connect (OIDC) to provide authorized access to its API. We currently use OAuth 2 draft-22. OpenID Connect is an open authentication protocol that works on top of the OAuth 2 framework. This section describes how you can use OpenID Connect to gain access to a user's data. Requests to retrieve user data require an access_token along with an id_token which are used to query ID.me's REST API. These tokens are unique to a user and should be stored securely. An access_token expires 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.
Prerequisites
Create an ID.me Developer Account & Organization
To get started, you will need to create an ID.me developer account and organization to generate your client_id and client_secret. Once created, you can configure custom redirect_uri values to facilitate where ID.me returns the authorization_code
Evaluate Well-Known Endpoints
Leverage the well-known endpoint to obtain critical configuration information. These endpoints provide metadata in a standardized format (JSON) and includes details such as: - The issuer URL - Supported authentication methods - Token endpoin - Public key for verifying tokens - Other essential configuration settings
You can use this information to configure your applications for secure authentication and authorization, ensuring compatibility and compliance with the OIDC standard.
Sandbox |
https://api.idmelabs.com/oidc/.well-known/openid-configuration |
Production |
https://api.id.me/oidc/.well-known/openid-configuration |
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:
Replace CLIENT_ID, REDIRECT_URI, and SCOPE with appropriate inputs
ID.me Widget (Optional)
<span
id='idme-wallet-button'
data-scopes='openid SCOPE'
data-client-id='CLIENT_ID'
data-redirect='REDIRECT_URI'
data-response='code'>
</span>
<script src='https://s3.amazonaws.com/idme/developer/idme-buttons/assets/js/idme-wallet-button.js'></script>
Replace CLIENT_ID, REDIRECT_URI, and SCOPE with appropriate inputs
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. Must include openid in the scope, along with one of the supported values below, to initiate OpenID Connect transactions.
Supported values can be found here:Standard OAuth/OIDC Scope & SAML AuthnContext Values |
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: |
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.
Supported values include: |
eid | An optional parameter to carry through any external identifiers you would like to receive back in the payload response. |
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 (see below) 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
Replace CLIENT_ID, CLIENT_SECRET, REDIRECT_URI, and SCOPE with appropriate inputs
Endpoint
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" : "military"
"id_token" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IktBTGVzSUpVVTRuQ0FjLVJTdTJkS0xkYkgtQmFrdXRnekE1VjdoQm9RUm8ifQ.eyJpc3MiO\niJodHRwczovL2FwaS5pZG1lbGFicy5jb20vb2lkYyIsInN1YiI6ImYxNjljMzRkMDA3YjQ1MTBhNzNiYTc5OThjMDgxZWEwIiwiYXVkIjoiZTE3OWUzNT\nc3NTAzMjBlMmU2NTJjODBiNjFjNGRjMDIiLCJleHAiOjE2MjU1MTI3ODQsImlhdCI6MTYyNTQ5NDc4NCwiZW1haWwiOiJ0ZXN0aW5nQGlkLm1lIiwiZm5\nhbWUiOiJURVNUIiwibG5hbWUiOiJVU0VSIiwiemlwIjoiMjIxMDIiLCJ1dWlkIjoiZjE2OWMzNGQwMDdiNDUxMGE3M2JhNzk5OGMwODFlYTAifQ.Qwdnb\nAn6kbnzSvASa8qEMTJO-T-jzkJAfJdLViX188N2ny1DLBjn1AxgsydXmnzeyCtfv9Mn-rjLFtsEAPXMbWoA5maU0Lqt03hbSEbvevksr6xzD0j9mzQdWb\n3YXHkSS-A3dKkl4KM5TiO7BY8W5Xmhp0YivtcW2_C24xdxukYBgR1Y6lmjaKS3SGQRkjO31mj8_qxlAP4RuC9U2cmHx-w2HYVJfwpyauzmM8uo6CD3Ql3\nqCP88bcyJtF2O9cEpvW9E47CcaueGLjBF9_Qe0u1IWzcX77rCTnxMounfjmYDn7Md0JAl6-Q6E23yu-Zibg8CFytmDDm4pGbEA7g8BA"
}
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. |
id_token | A JSON Web Token(JWT) |
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 |
Step 5. Validate The ID Token
Now, we need to validate that the ID Token sent was from the correct place by validating the JWT's signature.
Example JSON Web Token (JWT)
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IktBTGVzSUpVVTRuQ0FjLVJTdTJkS0xkYkgtQmFrdXRnekE1VjdoQm9RUm8ifQ.eyJpc3MiO
iJodHRwczovL2FwaS5pZG1lbGFicy5jb20vb2lkYyIsInN1YiI6ImYxNjljMzRkMDA3YjQ1MTBhNzNiYTc5OThjMDgxZWEwIiwiYXVkIjoiZTE3OWUzNT
c3NTAzMjBlMmU2NTJjODBiNjFjNGRjMDIiLCJleHAiOjE2MjU1MTI3ODQsImlhdCI6MTYyNTQ5NDc4NCwiZW1haWwiOiJ0ZXN0aW5nQGlkLm1lIiwiZm5
hbWUiOiJURVNUIiwibG5hbWUiOiJVU0VSIiwiemlwIjoiMjIxMDIiLCJ1dWlkIjoiZjE2OWMzNGQwMDdiNDUxMGE3M2JhNzk5OGMwODFlYTAifQ.Qwdnb
An6kbnzSvASa8qEMTJO-T-jzkJAfJdLViX188N2ny1DLBjn1AxgsydXmnzeyCtfv9Mn-rjLFtsEAPXMbWoA5maU0Lqt03hbSEbvevksr6xzD0j9mzQdWb
3YXHkSS-A3dKkl4KM5TiO7BY8W5Xmhp0YivtcW2_C24xdxukYBgR1Y6lmjaKS3SGQRkjO31mj8_qxlAP4RuC9U2cmHx-w2HYVJfwpyauzmM8uo6CD3Ql3
qCP88bcyJtF2O9cEpvW9E47CcaueGLjBF9_Qe0u1IWzcX77rCTnxMounfjmYDn7Md0JAl6-Q6E23yu-Zibg8CFytmDDm4pGbEA7g8BA
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.
Step 5. Decode ID Token For User Payload
The ID token contains information about a user and their authentication status. The following steps will describe how to decode the ID token, available in JSON Web Token (JWT) format , to get the required information about the user:
Decoded Header Payload Example
{
"typ": "JWT",
"alg": "RS256",
"kid": "KALesIJUU4nCAc-RSu2dKLdbH-BakutgzA5V7hBoQRo"
}
Key Description
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. |
Decoded ID Token Payload Example
{
"iss": "https://api.idmelabs.com/oidc",
"sub": "f169c34d007b4510a73ba7998c081ea0",
"aud": "8749d197447c364b219afbd4b613ebd0",
"exp": 1616364069,
"iat": 1616346069,
"email": "[email protected]",
"fname": "Rod",
"lname": "Hamill",
"street": "72146 Okuneva Heights",
"city": "Jeffereyburgh",
"state": "Hawaii",
"zip": "94468-5006",
"birthdate": "1959-12-08",
"eid": "FOO-bar-123",
"uuid": "d733a89e2e634f04ac2fe66c97f71612"
}
Key Description
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 | Unique identifer assoicated with the member's ID.me account |
Step 6. Exchange Access Token For ID Token (Optional)
CURL Example
curl -X GET -d "access_token=488e864b" https://api.id.me/api/public/v3/userinfo
Endpoint
https://api.id.me/api/public/v3/userinfo
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
"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IktBTGVzSUpVVTRuQ0FjLVJTdTJkS0xkYkgtQmFrdXRnekE1VjdoQm9RUm8ifQ.eyJpc3MiO
iJodHRwczovL2FwaS5pZG1lbGFicy5jb20vb2lkYyIsInN1YiI6ImYxNjljMzRkMDA3YjQ1MTBhNzNiYTc5OThjMDgxZWEwIiwiYXVkIjoiZTE3OWUzNT
c3NTAzMjBlMmU2NTJjODBiNjFjNGRjMDIiLCJleHAiOjE2MjU1MTI3ODQsImlhdCI6MTYyNTQ5NDc4NCwiZW1haWwiOiJ0ZXN0aW5nQGlkLm1lIiwiZm5
hbWUiOiJURVNUIiwibG5hbWUiOiJVU0VSIiwiemlwIjoiMjIxMDIiLCJ1dWlkIjoiZjE2OWMzNGQwMDdiNDUxMGE3M2JhNzk5OGMwODFlYTAifQ.Qwdnb
An6kbnzSvASa8qEMTJO-T-jzkJAfJdLViX188N2ny1DLBjn1AxgsydXmnzeyCtfv9Mn-rjLFtsEAPXMbWoA5maU0Lqt03hbSEbvevksr6xzD0j9mzQdWb
3YXHkSS-A3dKkl4KM5TiO7BY8W5Xmhp0YivtcW2_C24xdxukYBgR1Y6lmjaKS3SGQRkjO31mj8_qxlAP4RuC9U2cmHx-w2HYVJfwpyauzmM8uo6CD3Ql3
qCP88bcyJtF2O9cEpvW9E47CcaueGLjBF9_Qe0u1IWzcX77rCTnxMounfjmYDn7Md0JAl6-Q6E23yu-Zibg8CFytmDDm4pGbEA7g8BA"
Refer to Step #5 to learn how to parse and decode the values from the JWT
Step 7. Parse the JSON Response
Parsing the JSON response correctly is key to implementing a scalable solution. How partners retrieve data from the JSON response can determine if all responses can be handled properly and a change to the payload for any reason such as adding a new attribute won’t break the integration. It is best practice to:
- Index values using the handle within the object
- Implement validation only for existing attribute values
- Store the raw JSON responses for auditing purposes
- Create table to store the verification status, uuid and authoritative data returned from ID.me REST API
- Leverage the uuid value as a foreign key on transactions to track ID.me user activity across your application ecosystem
- Pre-fill form fields to expedite the post verification user experience
Do not expect all attributes and status values to be returned in the same order within an object or array.
Example Data Types
The attribute type determines what data type will be returned from ID.me’s REST API. The following data types should be expected from ID.me’s REST API:
String
{
"email": "[email protected]"
}
Integer
{
"age": 21
}
Array
{
"covid_vaccine_records": [
{
"brand": "Pfizer",
"date": "2022-01-01T00:00:00-05:00",
"type": "primary"
},
{
"brand": "Pfizer",
"date": "2022-02-02T00:00:00-05:00",
"type": "primary"
}
]
}
Object
{
"previous_addresses": [
{
"normalized_street": "8281 Greensboro Drive",
"street1": "8281 Greensboro Drive",
"street2": "",
"city": "West McLean",
"state": "VA",
"province": "",
"zip": "22102",
"country": "US",
"normalized": "false",
"primary": "false"
},
{
"normalized_street": "6647 WILDFLOWER DR S",
"street1": "6647 WILDFLOWER DR S",
"street2": "",
"city": "COTTAGE GROVE",
"state": "MN",
"province": "",
"zip": "55016",
"country": "US",
"normalized": "false",
"primary": "false"
}
]
}
Do not expect all attribute values to be a string.