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 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.
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 hospital_employee&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>
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
|
nonce
|
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
|
Example Payload
{
"access_token": "a0b1c2d3f4g5h6i7j8k9l0m1n2o3p4q5",
"token_type": "bearer",
"expires_in": "300",
"refresh_token": "e7c77fe1fd5ece9aaccb129f6dd39431",
"refresh_expires_in": "604800",
"scope": "http://idmanagement.gov/ns/assurance/loa/3/erx",
"id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IktBTGVzSUpVVTRuQ0FjLVJTdTJkS0xkYkgtQmFrdXRnekE1VjdoQm9RUm8ifQ.eyJpc3MiO\niJodHRwczovL2FwaS5pZG1lbGFicy5jb20vb2lkYyIsInN1YiI6ImYxNjljMzRkMDA3YjQ1MTBhNzNiYTc5OThjMDgxZWEwIiwiYXVkIjoiZTE3OWUzNT\nc3NTAzMjBlMmU2NTJjODBiNjFjNGRjMDIiLCJleHAiOjE2MjU1MTI3ODQsImlhdCI6MTYyNTQ5NDc4NCwiZW1haWwiOiJ0ZXN0aW5nQGlkLm1lIiwiZm5\nhbWUiOiJURVNUIiwibG5hbWUiOiJVU0VSIiwiemlwIjoiMjIxMDIiLCJ1dWlkIjoiZjE2OWMzNGQwMDdiNDUxMGE3M2JhNzk5OGMwODFlYTAifQ.Qwdnb\nAn6kbnzSvASa8qEMTJO-T-jzkJAfJdLViX188N2ny1DLBjn1AxgsydXmnzeyCtfv9Mn-rjLFtsEAPXMbWoA5maU0Lqt03hbSEbvevksr6xzD0j9mzQdWb\n3YXHkSS-A3dKkl4KM5TiO7BY8W5Xmhp0YivtcW2_C24xdxukYBgR1Y6lmjaKS3SGQRkjO31mj8_qxlAP4RuC9U2cmHx-w2HYVJfwpyauzmM8uo6CD3Ql3\nqCP88bcyJtF2O9cEpvW9E47CcaueGLjBF9_Qe0u1IWzcX77rCTnxMounfjmYDn7Md0JAl6-Q6E23yu-Zibg8CFytmDDm4pGbEA7g8BA"
}
Key Descriptions
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 |
Step 4: 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:
Python Example
import base64
encoded_token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IktBTGVzSUpVVTRuQ0FjLVJTdTJkS0xkYkgtQmFrdXRnekE1VjdoQm9RUm
8ifQ.eyJpc3MiOiJodHRwczovL2FwaS5pZG1lbGFicy5jb20vb2lkYyIsInN1YiI6ImYxNjljMzRkMDA3YjQ1MTBhNzNiYTc5OThjMD
gxZWEwIiwiYXVkIjoiZTE3OWUzNTc3NTAzMjBlMmU2NTJjODBiNjFjNGRjMDIiLCJleHAiOjE2MjU1MTI3ODQsImlhdCI6MTYyNTQ5N
Dc4NCwiZW1haWwiOiJ0ZXN0aW5nQGlkLm1lIiwiZm5hbWUiOiJWRVJPTklDQSIsImxuYW1lIjoiUEVSU0lOR0VSIiwiemlwIjoiMjIx
MDIiLCJ1dWlkIjoiZjE2OWMzNGQwMDdiNDUxMGE3M2JhNzk5OGMwODFlYTAifQ.QwdnbAn6kbnzSvASa8qEMTJO-T-jzkJAfJdLViX1
88N2ny1DLBjn1AxgsydXmnzeyCtfv9Mn-rjLFtsEAPXMbWoA5maU0Lqt03hbSEbvevksr6xzD0j9mzQdWb3YXHkSS-A3dKkl4KM5TiO
7BY8W5Xmhp0YivtcW2_C24xdxukYBgR1Y6lmjaKS3SGQRkjO31mj8_qxlAP4RuC9U2cmHx-w2HYVJfwpyauzmM8uo6CD3Ql3qCP88bc
yJtF2O9cEpvW9E47CcaueGLjBF9_Qe0u1IWzcX77rCTnxMounfjmYDn7Md0JAl6-Q6E23yu-Zibg8CFytmDDm4pGbEA7g8BA=="
split_token = encoded_token.split(".")
encoded_header = split_token[0]
encoded_payload = split_token[1]
decoded_payload = base64.b64decode(encoded_payload)
print(decoded_payload)
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. |
Decode ID Token Payload Example
{
"iss": "https://api.idmelabs.com/oidc",
"sub": "f169c34d007b4510a73ba7998c081ea0",
"aud": "8749d197447c364b219afbd4b613ebd0",
"exp": 1616364069,
"iat": 1616346069,
"email": "stephan.goldner@id.me",
"fname": "Stephan",
"lname": "Goldner",
"street": "517 Sharee Well",
"city": "East Wilfredomouth",
"state": "California",
"zip": "82474-1158",
"birthdate": "1966-12-09",
"uuid": "d733a89e2e634f04ac2fe66c97f71612"
}
Key Descriptions
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 6: Exchange Access Token For ID Token (OPTIONAL)
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/userinfo
Endpoint
https://api.id.me/api/public/v3/userinfo
HTTP Request Method
GET
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. |
Production Requirements
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. |