OIDC Manual Configuration

Configure the required credentials and server values before integrating the OIDC Onboarding or Authentication flows. All values are available from your Incode dashboard.

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

ValueDescription
AUTH_SERVER_URLBase URL of the OIDC authorization server (https://auth.demo.incode.com). Also used as the issuer value for ID token validation.
SERVER_URLBase URL of the Incode API server
REDIRECT_URIThe redirect URI registered with your OIDC client
API_KEYYour Incode API key
ADMIN_EMAILAdmin account email for the Incode Admin API
ADMIN_PASSWORDAdmin account password for the Incode Admin API

Onboarding Client Credentials

ValueDescription
CLIENT_IDYour registered OIDC onboarding client ID
CLIENT_SECRETYour registered OIDC onboarding client secret

Authentication Client Credentials

ValueDescription
AUTH_CLIENT_IDYour registered OIDC authentication client ID
AUTH_CLIENT_SECRETYour 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

LanguageLibrary
JavaScript / Node.jsjose, jsonwebtoken
Pythonpython-jose, authlib
Javanimbus-jose-jwt
Gogolang-jwt/jwt
Rubyjwt

Claims to Validate

ClaimExpected ValueWhy
issMust exactly match https://auth.demo.incode.comConfirms the token was issued by the authorization server you trust
expMust be in the future (compare against server time)Rejects expired tokens
nonceMust match the nonce sent during the sessionConfirms the token was issued in response to your specific request — protects against replay attacks
azpMust equal your CLIENT_ID when multiple audiences are presentConfirms your app is the intended recipient of the token
kidMust be present in the JWKS at https://auth.demo.incode.com/oauth2/jwksUsed 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.

📘

Full endpoint reference

For the complete request schema, authentication options, and error responses, see the official Admin Login API reference.

🚧

Server-side only

This request must be made from your server. Never expose ADMIN_EMAIL, ADMIN_PASSWORD, or API_KEY in client-side code.

Request

POST /executive/log-in
Content-Type: application/json
api-version: 1.0
x-api-key: YOUR_API_KEY
{
  "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

{
  "token": "<admin-token>"
}
FieldDescription
tokenShort-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 -------------------------|
📘

Prerequisites

Before starting, make sure you have all required values from the Prerequisites page, including your CLIENT_ID and CLIENT_SECRET.


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
ParameterValue
grant_typeauthorization_code
client_idYOUR_CLIENT_ID
client_secretYOUR_CLIENT_SECRET
redirect_uriYOUR_REDIRECT_URI
codeThe 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

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

Validate the ID token

Before trusting any claims in the ID token, validate it using the steps in the ID Token Validation guide. Use CLIENT_ID as the audience.

Codes are single-use

Authorization codes expire quickly (typically 60 seconds) and can only be exchanged once. If the token exchange fails, the user will need to restart the onboarding session.


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)

{
  "interview_id": "667ce6cd1f9dce127eabe35e",
  "email": "[email protected]"
}
FieldDescription
interview_idThe Incode session identifier — store this for Steps 3–5
emailThe authenticated user's email address
📘

Store the interview_id

The interview_id is required to retrieve the verification score and OCR data. Store it securely on your server before proceeding.


Step 3: Create an Admin Token

Follow the Create Admin Token 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

📘

Full endpoint reference

For the complete request schema, response fields, and status definitions, see the official Get Scores API reference.

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
Query ParameterRequiredDescription
idNoThe interview_id from Step 2. If omitted, extracted from the authentication 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

SectionDescription
overallComposite score and pass/fail status across all checks
idValidationDocument authenticity and quality checks
livenessLiveness detection results
faceRecognitionSelfie-to-ID face match results
deepsightMultimodal fraud intelligence signals
idOcrConfidenceConfidence scores for extracted text fields
governmentValidationGovernment database cross-check results
watchlistScoreWatchlist screening results
antifraudAggregate fraud risk assessment
deviceRiskDevice trust signals
behavioralRiskBehavioral trust signals
reasonMsgHuman-readable explanation of the overall outcome

Error Responses

Status CodeDescription
400Bad request — check that your interview_id, api-version, and auth headers are correct

Step 5: Retrieve OCR Data

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

📘

Full endpoint reference

For the complete response schema and field definitions, see the official Get OCR Data API reference.

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
Query ParameterRequiredDescription
idNoThe interview_id from Step 2. If omitted, extracted from the authentication 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();

Response

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.

For the full field definitions and response schema, refer to the official Get OCR Data API reference.

Error Responses

Status CodeDescription
400Bad request — check that your interview_id, api-version, and auth headers are correct

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 ------------------------------|
📘

New user?

If the user has not yet been onboarded, they must complete the Onboarding flow first before they can authenticate.

📘

Prerequisites

Before starting, make sure you have all required values from the Prerequisites page, including your AUTH_CLIENT_ID and AUTH_CLIENT_SECRET.


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
ParameterValue
grant_typeauthorization_code
client_idYOUR_AUTH_CLIENT_ID
client_secretYOUR_AUTH_CLIENT_SECRET
redirect_uriYOUR_REDIRECT_URI
codeThe 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

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

Validate the ID token

Before trusting any claims in the ID token, validate it using the steps in the ID Token Validation guide. Use AUTH_CLIENT_ID as the audience.

Codes are single-use

Authorization codes expire quickly (typically 60 seconds) and can only be exchanged once. If the token exchange fails, the user will need to restart the authentication session.


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)

{
  "interview_id": "667ce6cd1f9dce127eabe35e",
  "email": "[email protected]"
}
FieldDescription
interview_idThe Incode session identifier — store this for Steps 3 and 4
emailThe authenticated user's email address
📘

Store the interview_id

The interview_id is required to retrieve the verification score. Store it securely on your server before proceeding.


Step 3: Create an Admin Token

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


Step 4: Retrieve the Verification Score

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

📘

Full endpoint reference

For the complete request schema, response fields, and status definitions, see the official Get Scores API reference.

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
Query ParameterRequiredDescription
idNoThe interview_id from Step 2. If omitted, extracted from the authentication 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

SectionDescription
overallComposite score and pass/fail status across all checks
livenessLiveness detection results
faceRecognitionFace match results against the enrolled user
deepsightMultimodal fraud intelligence signals
antifraudAggregate fraud risk assessment
deviceRiskDevice trust signals
behavioralRiskBehavioral trust signals
reasonMsgHuman-readable explanation of the overall outcome

Error Responses

Status CodeDescription
400Bad request — check that your interview_id, api-version, and auth headers are correct