OIDC Manual Configuration

Prerequisites

The following values are required for both the Onboarding and Authentication flows. You will need them from your Incode dashboard and OIDC configuration.

Shared Values

Value Description
AUTH_SERVER_URL Base URL of the OIDC authorization server (https://auth.demo.incode.com). Also used as the issuer value for ID token validation.
SERVER_URL Base URL of the Incode API server
REDIRECT_URI The redirect URI registered with your OIDC client
API_KEY Your Incode API key
ADMIN_EMAIL Admin account email for the Incode Admin API
ADMIN_PASSWORD Admin account password for the Incode Admin API

Onboarding Client Credentials

Value Description
CLIENT_ID Your registered OIDC onboarding client ID
CLIENT_SECRET Your registered OIDC onboarding client secret

Authentication Client Credentials

Value Description
AUTH_CLIENT_ID Your registered OIDC authentication client ID
AUTH_CLIENT_SECRET Your registered OIDC authentication client secret

Keep credentials secure

Never expose CLIENT_SECRET, AUTH_CLIENT_SECRET, ADMIN_EMAIL, ADMIN_PASSWORD, or API_KEY in client-side code. All requests using these values must be made from your server.

ID Token Validation

After receiving an ID token from the /oauth2/token endpoint, your application is responsible for validating it before trusting any of its claims. Use a well-maintained JWT library rather than implementing validation manually.

Recommended Libraries

Language Library
JavaScript / Node.js jose, jsonwebtoken
Python python-jose, authlib
Java nimbus-jose-jwt
Go golang-jwt/jwt
Ruby jwt

Claims to Validate

Claim Expected Value Why
iss Must exactly match https://auth.demo.incode.com Confirms the token was issued by the authorization server you trust
exp Must be in the future (compare against server time) Rejects expired tokens
nonce Must match the nonce sent during the session Confirms the token was issued in response to your specific request — protects against replay attacks
azp Must equal your CLIENT_ID when multiple audiences are present Confirms your app is the intended recipient of the token
kid Must be present in the JWKS at https://auth.demo.incode.com/oauth2/jwks Used to verify the token's cryptographic signature

Verifying the Token Signature (JWKS)

The kid value in the token header identifies which public key to use for signature verification. Fetch Incode's public keys and find the matching key:

GET https://auth.demo.incode.com/oauth2/jwks

Example (JavaScript using jose)

import { createRemoteJWKSet, jwtVerify } from 'jose';

const JWKS = createRemoteJWKSet(
  new URL('https://auth.demo.incode.com/oauth2/jwks')
);

const { payload } = await jwtVerify(idToken, JWKS, {
  issuer:   'https://auth.demo.incode.com',
  audience: CLIENT_ID, // Use AUTH_CLIENT_ID for the Authentication flow
});

// Validate nonce manually
if (payload.nonce !== storedNonce) {
  throw new Error('Nonce mismatch — possible replay attack');
}

Create Admin Token

Endpoint:POST {SERVER_URL}/executive/log-in

Before retrieving verification results, your server must authenticate with the Incode Admin API to obtain a short-lived, high-privilege admin token.

Request

POST /executive/log-in
Content-Type: application/json
api-version: 1.0
x-api-key: YOUR_API_KEY

JSON

{
  "email": "YOUR_ADMIN_EMAIL",
  "password": "YOUR_ADMIN_PASSWORD"
}

Example (JavaScript)

const response = await fetch(`${SERVER_URL}/executive/log-in`, {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'Accept':       'application/json',
    'api-version':  '1.0',
    'x-api-key':    API_KEY,
  },
  body: JSON.stringify({
    email:    ADMIN_EMAIL,
    password: ADMIN_PASSWORD,
  }),
});

const { token: adminToken } = await response.json();

Response

JSON

{
  "token": "<admin-token>"
}
Field Description
token Short-lived admin token required for score and OCR data retrieval

OIDC Onboarding Demo

Overview

The OIDC Onboarding flow verifies a new user's identity by combining OpenID Connect (OIDC) with Incode's biometric verification pipeline. Once the user completes the onboarding session on the frontend, your server exchanges the resulting authorization code for tokens and retrieves the full verification and document data.

High-level flow:

Your Server           Auth Server (OIDC)            Incode API
  |                         |                            |
  |-- 1. POST /token ------>|                            |
  |<-- access + id token ---|                            |
  |-- 2. GET /userinfo ---->|                            |
  |<-- interview_id --------|                            |
  |-- 3. POST /executive/log-in ----------------------->|
  |<-- adminToken ----------------------------------------|
  |-- 4. GET /omni/get/score -------------------------->|
  |<-- verification score ------------------------------|
  |-- 5. GET /omni/get/ocr-data ----------------------->|
  |<-- extracted document data -------------------------|

Step 1: Exchange the Authorization Code for Tokens

Endpoint:POST {AUTH_SERVER_URL}/oauth2/token

Once the user has completed the onboarding session on the frontend, your server receives an authorization code. Exchange it for an access token and ID token using your CLIENT_SECRET.

Request

POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Parameter Value
grant_type authorization_code
client_id YOUR_CLIENT_ID
client_secret YOUR_CLIENT_SECRET
redirect_uri YOUR_REDIRECT_URI
code The authorization code received from the onboarding session

Example (JavaScript)

const response = await fetch(`${AUTH_SERVER_URL}/oauth2/token`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type:    'authorization_code',
    client_id:     CLIENT_ID,
    client_secret: CLIENT_SECRET,
    redirect_uri:  REDIRECT_URI,
    code:          authorizationCode,
  }),
});

const tokens = await response.json();

Response

JSON

{
  "access_token": "<JWT>",
  "id_token": "<JWT>",
  "token_type": "Bearer",
  "expires_in": 3600
}

Step 2: Retrieve the Interview ID

Endpoint:GET {AUTH_SERVER_URL}/userinfo

Once your application has a valid access token, call the OIDC UserInfo endpoint to retrieve the interview_id for the onboarding session.

Request

GET /userinfo
Authorization: Bearer YOUR_ACCESS_TOKEN

Example (JavaScript)

const response = await fetch(`${AUTH_SERVER_URL}/userinfo`, {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
  },
});

const userInfo = await response.json();
const interviewId = userInfo.interview_id;

Response (example)

JSON

{
  "interview_id": "667ce6cd1f9dce127eabe35e",
  "email": "user@example.com"
}

Step 3: Create an Admin Token

Follow the guide to obtain the admin token required for Steps 4 and 5.

Step 4: Retrieve the Verification Score

Endpoint:GET {SERVER_URL}/omni/get/score

Request

GET /omni/get/score?id=YOUR_INTERVIEW_ID
Content-Type: application/json
api-version: 1.0
x-api-key: YOUR_API_KEY
X-Incode-Hardware-Id: YOUR_ADMIN_TOKEN

Example (JavaScript)

const response = await fetch(
  `${SERVER_URL}/omni/get/score?id=${interviewId}`,
  {
    method: 'GET',
    headers: {
      'Content-Type':         'application/json',
      'api-version':          '1.0',
      'x-api-key':            API_KEY,
      'X-Incode-Hardware-Id': adminToken,
    },
  }
);

const score = await response.json();

Response

Section Description
overall Composite score and pass/fail status across all checks
liveness Liveness detection results
faceRecognition Selfie-to-ID face match results
deepsight Multimodal fraud intelligence signals
idOcrConfidence Confidence scores for extracted text fields
governmentValidation Government database cross-check results
watchlistScore Watchlist screening results
antifraud Aggregate fraud risk assessment
deviceRisk Device trust signals
behavioralRisk Behavioral trust signals
reasonMsg Human-readable explanation of the overall outcome

Step 5: Retrieve OCR Data

Endpoint:GET {SERVER_URL}/omni/get/ocr-data

Request

GET /omni/get/ocr-data?id=YOUR_INTERVIEW_ID
Content-Type: application/json
api-version: 1.0
x-api-key: YOUR_API_KEY
X-Incode-Hardware-Id: YOUR_ADMIN_TOKEN

Example (JavaScript)

const response = await fetch(
  `${SERVER_URL}/omni/get/ocr-data?id=${interviewId}`,
  {
    method: 'GET',
    headers: {
      'Content-Type':         'application/json',
      'api-version':          '1.0',
      'x-api-key':            API_KEY,
      'X-Incode-Hardware-Id': adminToken,
    },
  }
);

const ocrData = await response.json();

A successful response returns a 200 OK containing data extracted from the user's identity document and address statement, including fields such as name, date of birth, address, document number, and expiration date.

Authentication

Overview

The OIDC Authentication flow allows a previously onboarded user to authenticate using face recognition. This is a 1:N flow — the authorization server matches the user's face against the full enrolled population without requiring a known user identifier upfront.

High-level flow:

Your Server           Auth Server (OIDC)            Incode API
  |                         |                            |
  |-- 1. POST /token ------>|                            |
  |<-- access + id token ---|                            |
  |-- 2. GET /userinfo ---->|                            |
  |<-- interview_id --------|                            |
  |-- 3. POST /executive/log-in ----------------------->|
  |<-- adminToken ----------------------------------------|
  |-- 4. GET /omni/get/score -------------------------->|
  |<-- verification score ------------------------------|

Step 1: Exchange the Authorization Code for Tokens

Endpoint:POST {AUTH_SERVER_URL}/oauth2/token

Once the user has completed the face authentication session on the frontend, your server receives an authorization code. Exchange it for an access token and ID token using your AUTH_CLIENT_SECRET.

Request

POST /oauth2/token
Content-Type: application/x-www-form-urlencoded
Accept: application/json
Parameter Value
grant_type authorization_code
client_id YOUR_AUTH_CLIENT_ID
client_secret YOUR_AUTH_CLIENT_SECRET
redirect_uri YOUR_REDIRECT_URI
code The authorization code received from the authentication session

Example (JavaScript)

const response = await fetch(`${AUTH_SERVER_URL}/oauth2/token`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
  body: new URLSearchParams({
    grant_type:    'authorization_code',
    client_id:     AUTH_CLIENT_ID,
    client_secret: AUTH_CLIENT_SECRET,
    redirect_uri:  REDIRECT_URI,
    code:          authorizationCode,
  }),
});

const tokens = await response.json();

Response

JSON

{
  "access_token": "<JWT>",
  "id_token": "<JWT>",
  "token_type": "Bearer",
  "expires_in": 3600
}

Step 2: Retrieve the Interview ID

Endpoint:GET {AUTH_SERVER_URL}/userinfo

Once your application has a valid access token, call the OIDC UserInfo endpoint to retrieve the interview_id for the authentication session.

Request

GET /userinfo
Authorization: Bearer YOUR_ACCESS_TOKEN

Example (JavaScript)

const response = await fetch(`${AUTH_SERVER_URL}/userinfo`, {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
  },
});

const userInfo = await response.json();
const interviewId = userInfo.interview_id;

Response (example)

JSON

{
  "interview_id": "667ce6cd1f9dce127eabe35e",
  "email": "user@example.com"
}

Step 3: Create an Admin Token

Follow the guide to obtain the admin token required for Step 4.

Step 4: Retrieve the Verification Score

Endpoint:GET {SERVER_URL}/omni/get/score

Request

Example (JavaScript)

const score = await response.json();


**Response**

| Section              | Description                                               |
|----------------------|-----------------------------------------------------------|
| `overall`            | Composite score and pass/fail status across all checks   |
| `liveness`           | Liveness detection results                                 |
| `faceRecognition`    | Face match results against the enrolled user              |
| `deepsight`          | Multimodal fraud intelligence signals                      |
| `antifraud`          | Aggregate fraud risk assessment                           |
| `deviceRisk`         | Device trust signals                                     |
| `behavioralRisk`     | Behavioral trust signals                                   |
| `reasonMsg`          | Human-readable explanation of the overall outcome         |