On this page
Integrate Okta with identity verification vendors
Developers and organizations can use identity verification (IDV) vendors to integrate IDV flows into their authentication processes.
This guide shows developers of IDV vendors how their IDV solutions integrate with Okta orgs.
Learning outcome
Understand the standardized process of how IDV vendors integrate with Okta.
What you need
- An IDV service that has an app and IDV flow
- Okta Integrator Free Plan org (opens new window)
- An Okta account management policy enabled
About identity verification and IDV vendors
IDV vendors typically verify the identities of users by requiring them to submit a proof of identity. The proof of identity matches a user’s digital identity against a trusted data source. IDV vendors provide IDV flows as part of their services. Okta admins and developers can work with IDV vendors to integrate their IDV flows into their orgs.
IDV flows are customizable and can be configured in different ways to verify user identities. For example, IDV vendors can provide a flow that requires a user’s given and family names to be matched against a picture of their driver’s license or passport. Or they can provide a flow that requires users to take selfies as proofs of liveliness.
Okta supported IDV vendors
Okta supports three IDV vendors that admins can configure in the Admin Console (opens new window) or by using Okta APIs (opens new window). Use this guide to integrate IDV vendors other than the ones listed here.
How IDV vendors integrate with Okta
The following diagram shows the standardized process for how IDV vendors integrate with Okta.
An Okta user does one of the following actions to trigger an Okta account management policy evaluation:
- Enrolls or unenrolls an authenticator
- Recovers their password
- Unlocks their account
Okta then sends a
POST /oauth2/par
request to the IDV vendor's authorization server.The IDV vendor processes the request and sends a response to Okta with a
request_uri
.Okta receives the
request_uri
and uses it to construct aGET /oauth2/authorize
request.Okta redirects the
request_uri
to the user's browser. The user's browser sends the GET request to the IDV vendor's authorization endpoint to start the IDV flow. The GET request contains therequest_uri
parameter.The user then completes the IDV flow, and the IDV vendor creates an
authorization_code
and returns it to Okta in a response.Okta creates and sends a
POST /token
request to the IDV vendor that contains information from the redirect response.The IDV vendor sends an
id_token
containing the results of the flow back to Okta.Okta evaluates the results and completes the policy evaluation. The policy evaluation is marked as
VERIFIED
orFAILED
.
Summary of steps
The following sections detail the steps of an IDV vendor integration.
Policy evaluation
A user triggers an Okta account management policy evaluation. There are several ways to trigger a policy evaluation:
- A user enrolls or unenrolls an authenticator
- A user recovers their password
- A user unlocks their account
POST /oauth2/par request to IDV vendor
After the user triggers a policy evaluation, Okta sends a POST /oauth2/par
request to the IDV vendor's authorization server.
The request contains standard pushed authorization request (PAR) parameters (opens new window) and a verified_claims
object. The verified_claims
object contains two identity verification objects that determine how the IDV flow interacts with Okta.
- The
claims
object passes the information about the Okta user to the IDV vendor. - The
verification
object determines the trust framework between Okta and the IDV vendor and the necessary assurance level for a successful IDV flow.IDV-DELEGATED
is the only trust framework that Okta supports for IDV vendor integration.
When Okta sends the request, a unique verification session is established.
POST /oauth2/par request example
curl -L -X POST "https://idv-vendor.com/oauth2/par" \
-H "Content-Type: application/json" \
-d '{
"response_type": "code",
"client_id": "{client_id}",
"client_secret": "{client_secret}",
"code_challenge": "{code_challenge}",
"code_challenge_method": "{code_challenge_method}",
"scope": "openid profile identity_assurance idv_flow_{idv_flow_id}",
"claims": {
"id_token": {
"verified_claims": [
{
"verification": {
"trust_framework": {
"value": "IDV-DELEGATED",
"essential": true
},
"assurance_level": {
"value": "VERIFIED",
"essential": true
}
},
"claims": {
"given_name": {
"value": "{ud_mapped_first_name}",
"fuzzy": true
},
"family_name": {
"value": "{ud_mapped_last_name}",
"fuzzy": true
},
"middle_name": {
"value": "{ud_mapped_middle_name}"
"fuzzy": true
},
"email": {
"value": "{ud_mapped_email}"
"fuzzy": true
},
"bithdate": {
"value": "{ud_mapped_birthdate}",
"fuzzy": true
},
"phone_number": {
"value": "{ud_mapped_phone_number}",
"fuzzy": true
},
"address": {
"street_address": {
"value": "{ud_mapped_street_address}",
"fuzzy": true
},
"locality": {
"value": "{ud_mapped_city}",
"fuzzy": true
},
"region": {
"value": "{ud_mapped_state}",
"fuzzy": true
},
"postal_code": {
"value": "{ud_mapped_zipcode}",
"fuzzy": true
},
"country": {
"value": "{ud_mapped_country}",
"fuzzy": true
}
}
}
}
]
}
},
"state": "{external_state_token_id}",
"login_hint": "{user_id}",
"redirect_uri": "https://{yourOktadomain}/idp/identity-verification/callback"
}'
POST /oauth2/par error response
The error response for an unsuccessful POST /oauth2/par
request uses this structure (opens new window).
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-cache, no-store
{
"error": "invalid_request",
"error_description":
"The redirect_uri is not valid for the given client"
}
Request parameters
Parameter | Description | Param Type | DataType |
---|---|---|---|
response_type | Determines the type of flow. Okta uses code to identify the request as an authorization_code flow. | String | String |
client_id | Unique identifier of the IDV vendor app. IDV vendors provide this value. | String | String |
client_secret | A confidential key associated with the IDV vendor's client_id . IDV vendors provide this value. | String | String |
code_challenge | A cryptographic string derived from a code verifier. It’s used with the Proof Key for Code Exchange (PKCE) mechanism. | String | String |
code_challenge_method | The transformation method that’s used to create the code_challenge from the code verifier. Okta uses the S256 method. | String | String |
scope | Defines the permissions or access levels that are requested. | String | String |
openid | Identifies the request as an OpenID Connect (OIDC) request. | String | String |
profile | Requests access to the end user's default profile claims. | String | String |
identity_assurance | Requests access to the verified_claims object. | String | String |
idv_flow_{idv_flow_id} | Identifies a specific IDV flow from the IDV vendor. Replace {idv_flow_id} with the identifier of the flow. You can leave it out of the request if the client_id and client_secret are configured to represent a specific flow from the IDV vendor. | String | String |
verified_claims | Contains the verification and claims objects. | Object | Object |
verification | Specifies the parameters and requirements for verifying the claims. Okta uses both the trust_framework and assurance_level properties. See the OIDC definition of the verification (opens new window) property. | Object | Object |
trust_framework | Identifies the trust framework that provides assurance about the verified attributes. Okta sets IDV_DELEGATED as the default value. This value delegates identity verification and the assurance policy to the IDV vendor. The IDV vendor is then responsible for verifying user identities and sends the results back to Okta. IDV_DELEGATED is currently the only supported trust framework. See the OIDC definition of the trust_framework (opens new window) property. | String | String |
assurance_level | Identifies the assurance level that's required for the identity claims of the user. The IDV vendor must map their verification results to the possible assurance levels, VERIFIED or FAILED . For a successful verification, the IDV vendor must pass VERIFIED as the assurance_level . For a failed verification, the IDV vendor must pass FAILED or a null value. See the OIDC definition of the assurance_level (opens new window) property. | String | String |
claims | Contains user-specific attributes. Okta supports these OIDC claims. For more information, see the OIDC definition of the claims (opens new window) property. | Object | Object |
fuzzy | An extension that adds fuzzy logic to a specified claim to assist with matching the claim value. IDV vendors can choose whether to add this extension to any claims attribute. The fuzzy extension is set as true for all claims by default. | String | String |
state | A unique string that maintains a connection between the request and the callback. | String | String |
redirect_uri | The URI where the response is sent after the user completes the IDV flow. | String | String |
login_hint | Identifier that associates an Okta user within the IDV vendor's app. | String | String |
IDV vendor responds with request_uri
A successful POST /oauth2/par
request generates a request_uri
that's sent back to Okta as a response. The request_uri
encodes the identity verification attributes of the POST /oauth2/par
request as a reference to the now established verification session.
POST /oauth2/par response example
HTTP/1.1 201 Created
Content-Type: application/json
Cache-Control: no-cache, no-store
{
"request_uri": "urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c",
"expires_in": 60
}
Okta redirects GET /oauth2/authorize request to user
Okta uses the request_uri
in the IDV vendor response and constructs a GET /oauth2/authorize
request. Okta then redirects the request_uri
, that now contains the GET /oauth2/authorize
request, to the user's browser.
User's browser sends GET /oauth2/authorize request to IDV vendor
The user's browser sends the GET request to the IDV vendor's OAuth 2.0 authorization endpoint. The IDV vendor evaluates the request_uri
so that the IDV flow can start.
Note: For IDV vendors, Okta recommends renaming the authorization endpoint so that it's clear the endpoint is used for identity verification. For example, rename the endpoint to
/oauth2/idv-authorize
.
GET /oauth2/authorize request example
curl -L -X GET "https://idv-vendor.com/oauth2/idv-authorize?request_uri=urn:ietf:params:oauth:request_uri:6esc_11ACC5bwc014ltc14eY22c"
GET /oauth2/authorize error response
The error response for an unsuccessful GET /oauth2/authorize
request uses this structure (opens new window).
HTTP/1.1 302
GET /idp/identity-verification/callback?error=invalid_request&state=30pqcSFzH7H0bIftWwYRbNNwbpOpfY-W
User completes the IDV flow
The user is then redirected to the IDV vendor app to complete the IDV flow.
IDV vendor sends authorization_code to Okta
After the user completes the IDV flow, the IDV vendor redirects them to the redirect_uri
specified in the POST /oauth2/par
request. The user is redirected to their Okta org. The redirect_uri
contains an authorization_code
that’s redeemed at the /oauth2/token
endpoint to retrieve the IDV flow results.
IDV vendor redirect to Okta example
curl -L -X GET "https://{yourOktadomain}/idp/identity-verification/callback?code=42bbe6319f0b04a43d&state=30pqcSFzH7H0bIftWwYRbNNwbpOpfY-W"
Okta sends a POST /token request to IDV vendor
Okta receives the authorization_code
from the IDV vendor. Okta then uses it to construct and send a POST /token
request to the IDV vendor. The request contains a code_verifier
value that’s compared against the code_challenge
value provided in the POST /oauth2/par
request. The values must match for the POST /token
request to succeed.
POST /token request example
curl -L -X POST "https://idv-vendor.com/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "client_id={client_id}" \
--data-urlencode "client_secret={client_secret}" \
--data-urlencode "code=42bbe6319f0b04a43d" \
--data-urlencode "code_verifier=72e0dca42dd87b345f0652899cba4f92e7b9bb2422f7c5a301ffae41" \
--data-urlencode "redirect_uri=https://{yourOktadomain}/idp/identity-verification/callback"
POST /token error response
The error response for an unsuccessful POST /token
request uses this structure (opens new window).
HTTP/1.1 400 Bad Request
Content-Type: application/json
Cache-Control: no-cache, no-store
{
"error": "invalid_request",
"error_description":
"The request is missing a required parameter"
}
IDV vendor responds with id_token
When the POST /token
request succeeds, the IDV vendor sends an id_token
in a JSON Web Token (JWT) encoded format back to Okta in response. The id_token
includes the verified_claims
object. This object contains the results of the identity verification for the user.
Note the following the ways to format the claims
object for the id_token
response:
IDV vendors must not include any
claims
attributes other than the currently supported ones. Okta fails a policy evaluation that returnsclaims
attributes other than the supported ones.IDV vendors can choose to return a
MATCHED
value for anyclaims
attributes, instead of returning identifying information about a user. Returning aMATCHED
value still indicates that the verification was successful but doesn't require IDV vendors to pass identifying information of a user.IDV vendors can choose to not pass any
claims
values. They can passclaims
as an empty object. See Minimum conformant (opens new window).
Note: If an IDV vendor passes an empty
claims
object, then theuser.identity_verification
event marks all claims as verified or failed. Whether the claims are failed or verified depends on theassurance_level
value that's passed.
IDV vendor id_token response example
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache, no-store
{
"id_token": {
"verified_claims": [
"verification": {
"trust_framework": "IDV-DELEGATED",
"assurance_level": "VERIFIED",
"time": "2024-10-07T10:00:00Z"
},
"claims": {
"given_name": {
"fuzzy": "Dan"
}
"family_name": "Jones"
}
]
}
}
Okta completes the policy evaluation
After the id_token
is returned in the response from the POST /token
request, Okta completes the policy evaluation.
Okta inspects id_token
object. The policy evaluation is successful if the trust_framework
and assurance_level
values match the values that were passed in the POST /oauth2/par
request, IDV-DELEGATED
and VERIFIED
.
If either of the trust_framework
or assurance_level
attributes aren't included in the id_token
response or if they have null
or unexpected values, then Okta marks the policy evaluation as unsuccessful.
Failed policy evaluation example
For example, a user completes an IDV flow but provides a name that doesn't match the given_name
value. The assurance_level
value is sent back as FAILED
in the id_token
response. And the given_name
value is returned as null
.
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-cache, no-store
{
"id_token": {
"verified_claims": [
"verification": {
"trust_framework": "IDV-DELEGATED",
"assurance_level": "FAILED",
"time": "2024-10-07T10:00:00Z"
},
"claims": {
"given_name": null,
"family_name": "Jones"
}
]
}
}
Identity verification events
There are two events related to identity verification: user.identity_verification
and user.identity_verification.start
. Okta admins can view these events in the System Log. See Event Types.
user.identity_verification.start
: This event is triggered when an Okta account management policy prompts a user to verify their identity with an IDV vendor.user.identity_verification
: This event is triggered after Okta completes the evaluation of an Okta account management policy.
For the user.identity_verification
event, there are two possible results for the event: ALLOW
(user is successfully verified) or DENY
(user isn't verified).
The ALLOW
result provides a CLAIMS_VERIFIED
reason that indicates the IDV vendor successfully verified the user.
There are multiple possible reasons for the DENY
result:
PARSING_ERROR
: Indicates that Okta wasn't able to parse the response from the IDV vendor because of invalid or malformed data.MISSING
: Indicates that a required parameter or value wasn't present in the request or response.RESPONSE_PROCESSING_ERROR
: Indicates that Okta encountered an error while processing the response from the IDV vendor.ERROR_RESPONSE
: Indicates that the IDV vendor returned an explicit error response to Okta.EMPTY_USER_ID
: Indicates that no user ID was provided in the request to the IDV vendor.MISSING_CODE_CHALLENGE
: Indicates that the code challenge required for PKCE was missing from the request.MISSING_APP_INSTANCE
: Indicates that the application instance required for the IDV flow wasn't found or wasn't provided.MISSING_AUTH_STATE_TOKEN
: Indicates that the authentication state token required for the flow was missing or invalid.CLAIMS_NOT_VERIFIED
: Indicates that the IDV vendor has assessed that not allclaims
attributes were verified.CLAIM_GIVEN_NAME_NOT_VERIFIED
: Indicates that thegiven_name
value wasn't verified.CLAIM_FAMILY_NAME_NOT_VERIFIED
: Indicates that thefamily_name
value wasn't verified.
Supported OIDC claims
Okta supports the following OIDC claims. IDV vendors can choose among any of these claims and use them in their IDV flow.
To use the claims that are Early Access, enable the More Universal Directory attributes available for identity verification mapping feature in your Okta org.
Note: IDV vendors must always include the
given_name
andfamily_name
claims.
Supported claim | Description | DataType |
---|---|---|
given_name | The user's first name. | String |
family_name | The user's last name or surname. | String |
middle_name Early Access | The user's middle name. | String |
email Early Access | The user's email address. | String |
birthdate Early Access | The user's date of birth. Format the date of birth in the ISO 8601 format (YYYY-MM-DD). | datetime |
phone_number Early Access | The user's phone number. Format the phone number in the E.164 format | String |
street_address Early Access | The user's street address. This claim can include new lines. | String |
locality Early Access | The user's city or locality. | String |
region Early Access | The user's state, province, prefecture, or region. | String |
postal_code Early Access | The user's postal or ZIP code. | String |
country Early Access | The user's country. Format this value with the country name. | String |
Map Okta user profile attributes to OIDC claims
Early AccessOkta admins can map any of these supported claims to user profile attributes. See Map profile attributes from Okta to the IDV vendor IdP (opens new window).
Admins can set user profile attributes as required when they map them to to the corresponding IDV vendor attribute. The given_name
and family_name
claims are required by default. When a PAR request is sent from Okta, and a required claim doesn't have a value in the user's profile, then the initial PAR request fails.
However, if a claim is mapped but not set as required, and it doesn't have a value in the user's profile, then the claim is excluded from the initial PAR request. The PAR request isn't failed.
Use the System Log to track identity verification events
Along with the IDV events (user.identity_verification.start
and user.identity_verification
), there are two properties that are attached to those events. The properties are also attached to the policy.evaluate_sign_on
event when an Okta account management policy is involved.
IdvReferenceId
: This property provides a reference ID that's attached to all the relevant events of an IDV process.IdvFlowId
: This property displays the ID of the IDV flow. Admins can use this property to more easily track information related to a specific IDV flow.