OAuth 2.0
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 community 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 is 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
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='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.
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 Access Token
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 Access Token
Example Payload
{
"access_token" : "a0b1c2d3f4g5h6i7j8k9l0m1n2o3p4q5"
"token_type" : "bearer"
"expires_in" : "300"
"refresh_token" : "e7c77fe1fd5ece9aaccb129f6dd39431"
"refresh_expires_in" : "604800"
"scope" : "military"
}
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. |
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. Exchange Access Token For User Data
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.
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
{
"attributes": [
{
"handle": "fname",
"name": "First Name",
"value": "Sean"
},
{
"handle": "lname",
"name": "Last Name",
"value": "Moen"
},
{
"handle": "email",
"name": "Email",
"value": "[email protected]"
},
{
"handle": "uuid",
"name": "Unique Identifier",
"value": "d733a89e2e634f04ac2fe66c97f71612"
},
{
"handle": "zip",
"name": "Zip Code",
"value": "44058-1478"
},
{
"handle": "eid",
"name": "External Identifier",
"value": "FOO-bar-123"
}
],
"status": [
{
"group": "military",
"subgroups": [
"Service Member"
],
"verified": true
}
]
}
Step 6. 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
{
"handle": "email",
"name": "Email",
"value": "[email protected]"
}
Integer
{
"handle": "age",
"name": "Age",
"value": 21
}
Array
{
"handle": "covid_vaccine_records",
"name": "Covid Vaccine Records",
"value": [
{
"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
{
"handle": "previous_addresses",
"name": "Previous address(es) if available",
"value": [
{
"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.