Interpreting Results — Gateway
What Is the ID Token?
At the end of a successful Gateway flow, your application receives an ID Token — a JSON Web Token (JWT) in the industry-standard RFC 7519 format. The token is signed by ID Dataweb using RS256 (asymmetric cryptography), and contains the full results of the user's verification session.
A JWT consists of three parts separated by dots:
eyJhbGciOiJSUzI1NiJ9.eyJwb2xpY3lEZWNpc2lvbiI6ImFwcHJvdmUiLCAuLi59.signature
header payload signature
| Part | Description |
|---|---|
| Header | Token type (JWT) and signing algorithm (RS256). Base64Url encoded. |
| Payload | Verification results and session data. Base64Url encoded. |
| Signature | RS256 signature from ID Dataweb. Verify using the JWKS public key. |
Verifying the Signature
Before trusting any data in the ID Token, verify the RS256 signature. Public signing keys are available in JWK format at:
https://preprod.iddataweb.com/axn/oauth2/jwks.json
Use a standard JWT library — do not write your own cryptographic code. Resources: jwt.io libraries | JWK libraries
The policyDecision Field
policyDecision FieldThe policyDecision field is the primary output you will act on. It summarizes whether the user met your configured verification policy.
| Value | Meaning |
|---|---|
approve | User verified to the level specified in your policy |
deny | User did not meet the verification policy |
obligation | Additional step required — handled within the workflow |
no_decision | Policy not configured or transaction error |
Note: When using the Gateway, the final
policyDecisionreturned to your application will always be eitherapproveordeny. Obligations are handled automatically mid-flow — the user is stepped up to additional checks within the Gateway before a final decision is returned.
Decoding the Payload
To read the ID Token payload, split the JWT on . and Base64Url decode the second segment:
app.get("/callback", async (req, res) => {
const authCode = req.query.code
const jwt = await getToken(auth, authCode)
const payload = jwt.id_token.split('.')[1]
const jsonString = Buffer.from(payload, 'base64').toString()
const data = JSON.parse(jsonString)
// act on data.policyDecision
})Full ID Token Example
{
"at_hash": "udfkrvnPivU4uE0BYeUcXA",
"sub": "[email protected]",
"aud": "18976aa43dca4b4e",
"endpoint": {
"status": "success",
"errorCode": "",
"errorDescription": "",
"credential": "[email protected]",
"credentialCreationDate": "02/08/2022 21:09:35 UTC",
"mbun": "f3f2a548-6c67-4155-8e30-bb1a28c84647",
"maxToken": "EnMbLwzgyefV3dndx9d5r1C-iEyZ8PpRhuIeIFlGpIE",
"endpointInstanceList": [
{
"apikey": "55555",
"userAttributes": [
{
"attributeType": "FullName",
"values": { "fname": "Jane", "lname": "Smith" },
"dateCreated": "02/08/2022 21:09:55 UTC"
},
{
"attributeType": "InternationalAddress",
"values": {
"country": "US",
"locality": "Arlington",
"route": "Main Ave",
"administrative_area_level_1": "VA",
"street_number": "123",
"postal_code": "22201"
},
"dateCreated": "02/08/2022 21:09:55 UTC"
}
],
"acquiredAttributes": [
{
"attributeType": "AssertionScore",
"values": { "assertionScore": "88" },
"dateCreated": "02/08/2022 21:09:57 UTC"
}
],
"userAssertionList": [
{
"provider": "Experian",
"serviceOffering": "Experian Precise ID",
"dateAsserted": "02/08/2022 21:09:55 UTC",
"assertions": {
"link.fullName_address": "pass",
"test.address90DaysOld": "pass",
"test.addressIsResidential": "pass",
"link.lastName_phone": "pass"
}
}
],
"policyDecision": {
"conclusion": "approve",
"status": "success",
"selectedPolicyID": 12391,
"decisionDetail": "{}"
}
}
]
},
"policyDecision": "approve",
"idwRiskScore": "100",
"iss": "https://preprod.iddataweb.com/axn",
"idwTrustScore": "100",
"exp": 1644355218,
"iat": 1644354618,
"jti": "008ab766-a58d-4489-b4cd-85188d2562d0"
}Key Fields Reference
| Field | Description |
|---|---|
sub | The user's credential (e.g. email address). Same value as credential. Used per OIDC standard. |
aud | The primary client_id (API key) of the workflow. |
iss | Issuer — the ID Dataweb Gateway URL. |
policyDecision | Top-level verdict: approve or deny. This is your primary action field. |
idwRiskScore | Composite risk score (0–100). Higher is lower risk. |
idwTrustScore | Composite trust score (0–100). Higher indicates greater confidence in the identity. |
jti | JWT ID — same value as asi and transaction_id used elsewhere. Per OIDC standard. |
exp / iat | Token expiry and issue time (Unix timestamp). |
endpoint.endpointInstanceList | Array of per-step results. See below. |
The endpointInstanceList
endpointInstanceListThe endpointInstanceList is an array of objects — one per step in your verification workflow. Each object corresponds to one API key (step) and contains:
apikey— the step's API keyuserAttributes— attributes collected from the user during this stepacquiredAttributes— attributes acquired from Checkers (e.g. device type, assertion scores)userAssertionList— individual assertion results from each CheckerpolicyDecision— the decision for this step, includingconclusionandobligationApiKey(if stepped up)
Example endpointInstanceList entry (obligation mid-flow)
endpointInstanceList entry (obligation mid-flow){
"apikey": "12345",
"userAttributes": [],
"acquiredAttributes": [
{
"attributeType": "DeviceType",
"values": { "deviceType": "desktop" },
"dateCreated": "02/08/2022 21:09:40 UTC"
}
],
"userAssertionList": [],
"policyDecision": {
"conclusion": "obligation",
"obligationApiKey": "55555",
"status": "success",
"selectedPolicyID": 20124,
"decisionDetail": "{}"
}
}In this example, step 12345 obligated the user to proceed to step 55555 — this happened transparently within the Gateway flow before a final decision was returned to your application.
Updated 2 months ago
