@credenceid/online-verifier
v0.1.4
Published
A framework-agnostic frontend SDK for identity verification
Readme
@credenceid/online-verifier
A framework-agnostic frontend SDK for integrating identity verification directly into your web applications. Built with native Web Components and TypeScript, it allows you to securely verify user identities using multiple protocols: DC API (ISO 18013-5 mdoc), Google Wallet (OpenID4VP), W3C OpenID4VP (cross-device / QR code), and Annex B OID4VP mdoc.
Because it utilizes native HTML Web Components, it works seamlessly out-of-the-box with Vanilla JS, React, Vue, Angular, Svelte, and more.
Features
- Framework Agnostic: Drop it into any frontend stack.
- Multiple Verification Protocols: DC API (mdoc), Google Wallet (OpenID4VP), W3C OpenID4VP (QR / cross-device), and Annex B OID4VP mdoc.
- Headless Styling: Bring your own CSS. The SDK provides the logic and a clean DOM element; you control the look and feel.
- Secure by Design: Handles token lifecycle, silent background refreshes, and domain validation automatically.
- Normalized Responses: All protocols return the same
ParsedVerificationResultshape — no per-protocol response parsing needed. - Annex B Auto-Resume: Automatically detects wallet redirect codes on page load and resumes sessions in the background.
Installation
npm install @credenceid/online-verifier
# or
yarn add @credenceid/online-verifierLocal Development & Testing
If you want to test the SDK locally before publishing (e.g., when iterating on changes), you can build and pack it into a .tgz tarball and install it directly into any local project.
1. Build the SDK
npm run buildThis compiles the TypeScript source and outputs the distributable files to the dist/ directory.
2. Pack the SDK
npm packThis creates a versioned tarball (e.g., credenceid-online-verifier-0.1.0.tgz) in the current directory. The file contains exactly what would be published to npm.
3. Install the tarball in your project
In the consuming project, install the generated .tgz file using its path:
npm install /path/to/credenceid-online-verifier-1.0.0.tgzOr using a relative path:
npm install ../Online-verifier-SDK/credenceid-online-verifier-1.0.0.tgzThe SDK will be available under the @credenceid/online-verifier package name, exactly as it would be after an npm registry install.
Environment Configuration
Before running the SDK locally or building for a target environment, create a .env file in the project root and set the backend URL:
# .env (project root)
OV_API_BASE_URL=https://credenceid.com/cloudsdk/playground/| Variable | Required | Description |
|-------------------|----------|-----------------------------------------------------------------------------|
| OV_API_BASE_URL | Yes | Base URL of the Online Verifier backend. All API calls are resolved against this URL. |
Note: The
.envfile is listed in.gitignore— never commit it. Each developer or deployment environment must supply its own copy.
Local development example
OV_API_BASE_URL=http://localhost:8080QA example
OV_API_BASE_URL=https://credenceid.com/cloudsdkdevAfter creating or updating .env, rebuild the SDK (npm run build) so the variable is picked up by the bundler.
Quick Start
1. Initialize the SDK
Before rendering any UI component, initialize the global VerifierSDK singleton with your CredenceID credentials. This authenticates your domain with the backend.
import { VerifierSDK } from '@credenceid/online-verifier';
VerifierSDK.init({
licenseKey: 'YOUR_LICENSE_KEY',
profileId: 'YOUR_PROFILE_ID'
}).then(() => {
console.log('SDK initialized successfully.');
}).catch((error) => {
console.error('SDK initialization failed:', error);
});2. Add a UI Component
Place the desired custom element anywhere in your DOM:
<!-- ISO 18013-5 mdoc via browser DC API -->
<ov-dcapi-btn text="Verify with Mobile ID" class="my-btn"></ov-dcapi-btn>
<!-- Google Wallet (OpenID4VP v1) -->
<ov-google-wallet-btn text="Verify with Google Wallet" class="my-btn"></ov-google-wallet-btn>
<!-- W3C OpenID4VP — shows a deep link for cross-device / QR flows -->
<ov-w3c-btn text="Verify via QR Code" class="my-btn"></ov-w3c-btn>
<!-- Annex B OID4VP mdoc — shows a deep link / QR code -->
<ov-annex-b-btn text="Verify with Wallet App" class="my-btn"></ov-annex-b-btn>3. Listen for Results
All components emit the same DOM events:
const btn = document.querySelector('ov-dcapi-btn');
btn.addEventListener('ov-success', (event) => {
const result = event.detail; // ParsedVerificationResult
console.log('Name:', result.claims.given_name);
if (result.portrait) {
document.querySelector('img').src = result.portrait;
}
});
btn.addEventListener('ov-error', (event) => {
console.error('Verification failed:', event.detail.message);
});Verification Protocols
1. DC API — <ov-dcapi-btn> (ISO 18013-5 mdoc)
Uses the browser's native navigator.credentials.get Digital Credentials API. Requires a compatible browser and a wallet app installed on the same device.
<ov-dcapi-btn text="Verify with Mobile ID" class="my-btn"></ov-dcapi-btn>2. Google Wallet — <ov-google-wallet-btn> (OpenID4VP v1 Unsigned)
Uses navigator.credentials.get with the openid4vp-v1-unsigned protocol, targeting Google Wallet on Android.
<ov-google-wallet-btn text="Verify with Google Wallet" class="my-btn"></ov-google-wallet-btn>3. W3C OpenID4VP — <ov-w3c-btn> (Cross-Device / QR Code)
Initiates a cross-device flow. The component:
- Calls the backend to get a session ID and an
openid4vp://authorization URI. - Emits
ov-uri-readyso you can render a QR code. - Shows a "Tap to Open Wallet App" deep link for mobile users.
- Polls the backend every second (up to 300 attempts = 5mins) until the wallet responds.
<ov-w3c-btn text="Scan QR to Verify" class="my-btn"></ov-w3c-btn>const btn = document.querySelector('ov-w3c-btn');
// Use this event to render a QR code with a library of your choice
btn.addEventListener('ov-uri-ready', (event) => {
const { uri } = event.detail;
renderQRCode(uri); // e.g. using qrcode.js
});
btn.addEventListener('ov-success', (event) => {
console.log('Verified:', event.detail.claims);
});Or via the callback property:
btn.onUriReady = (uri) => renderQRCode(uri);4. Annex B OID4VP mdoc — <ov-annex-b-btn>
Similar to the W3C flow but uses the Annex B mdoc protocol. The component initiates a session and shows a wallet deep link. It also supports a redirect-based return flow — when the wallet redirects back to your page with a ?response_code= parameter, the SDK automatically resumes the session on init().
<ov-annex-b-btn text="Verify with Wallet" class="my-btn"></ov-annex-b-btn>const btn = document.querySelector('ov-annex-b-btn');
btn.addEventListener('ov-uri-ready', (event) => {
renderQRCode(event.detail.uri);
});
btn.addEventListener('ov-success', (event) => {
console.log('Verified:', event.detail.claims);
});Annex B Redirect Resume
If the wallet redirects back to your page instead of posting a response, the SDK detects the ?response_code= query parameter automatically during VerifierSDK.init(), cleans the URL, and dispatches one of these global window events:
window.addEventListener('ov-resume-success', (event) => {
const result = event.detail; // ParsedVerificationResult
console.log('Resumed verification:', result.claims);
});
window.addEventListener('ov-resume-error', (event) => {
console.error('Resume failed:', event.detail);
});No additional setup is required — just listen for these events before calling VerifierSDK.init().
Response Format — ParsedVerificationResult
Every ov-success event and every VerifierClient method returns the same normalized object, regardless of protocol:
interface ParsedVerificationResult {
success: boolean;
portrait?: string; // Ready-to-use base64 data URI: `data:image/jpeg;base64,...`
claims: IdentityClaims; // Identity attributes (given_name, family_name, birth_date, etc.)
authStatus: AuthVerificationDetails; // Cryptographic / authentication metadata
raw: any; // Original backend response, unmodified
}Portrait images (portrait, photo, image, picture, face_portrait) are automatically extracted from claims and promoted to the top-level portrait field as a formatted data:image/jpeg;base64,... URI:
btn.addEventListener('ov-success', (event) => {
const { claims, portrait, authStatus } = event.detail;
document.querySelector('#name').textContent = claims.given_name;
if (portrait) {
document.querySelector('#photo').src = portrait;
}
});ResponseFormatter Utility
ResponseFormatter is exported and can be used standalone to parse raw backend responses or format label keys for display.
import { ResponseFormatter } from '@credenceid/online-verifier';
// Parse a raw backend response into a normalized object
const result = ResponseFormatter.parseVerificationResponse(rawData);
// Convert a claim key to a human-readable label
ResponseFormatter.formatLabel('given_name'); // → "Given Name"
ResponseFormatter.formatLabel('birthDate'); // → "Birth Date"Styling
All components render in the Light DOM, so your global CSS cascades directly into them.
During a verification the component adds an .ov-loading class to the button and disables it. The button text also changes to reflect the current step (Initiating... → Waiting for Wallet...).
/* Style to match your brand */
.my-btn {
background-color: #0f172a;
color: white;
padding: 12px 24px;
border-radius: 6px;
border: none;
font-weight: 600;
cursor: pointer;
}
/* Loading / in-progress state */
.my-btn.ov-loading {
opacity: 0.7;
cursor: wait;
}React Integration
React uses a synthetic event system, so use a useRef to attach the callback properties directly on the element.
TypeScript Setup
Augment the React JSX namespace in your types.d.ts or vite-env.d.ts:
import React from 'react';
declare module 'react' {
namespace JSX {
interface IntrinsicElements {
'ov-dcapi-btn': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & { text?: string; class?: string; };
'ov-google-wallet-btn': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & { text?: string; class?: string; };
'ov-w3c-btn': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & { text?: string; class?: string; };
'ov-annex-b-btn': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & { text?: string; class?: string; };
}
}
}Component Example
import React, { useEffect, useRef, useState } from 'react';
import { VerifierSDK, ParsedVerificationResult } from '@credenceid/online-verifier';
export const VerifyButton = () => {
const btnRef = useRef<any>(null);
const [isReady, setIsReady] = useState(false);
useEffect(() => {
VerifierSDK.init({
licenseKey: 'YOUR_LICENSE_KEY',
profileId: 'YOUR_PROFILE_ID',
}).then(() => setIsReady(true))
.catch(err => console.error('Setup failed:', err));
}, []);
useEffect(() => {
if (!btnRef.current) return;
btnRef.current.onVerificationSuccess = (result: ParsedVerificationResult) => {
console.log('Verified:', result.claims);
};
btnRef.current.onVerificationError = (error: Error) => {
console.error('Error:', error.message);
};
// For W3C / Annex B buttons, also handle the URI ready callback:
// btnRef.current.onUriReady = (uri: string) => renderQRCode(uri);
}, [isReady]);
return (
<ov-dcapi-btn ref={btnRef} text="Verify with Mobile ID" class="my-btn" />
);
};API Reference
VerifierSDK.init(config)
Authenticates the SDK and validates your domain. Automatically handles Annex B redirect resumes via ?response_code= URL parameters.
| Parameter | Type | Description |
|--------------|----------|--------------------------------------|
| licenseKey | string | Your assigned license key. |
| profileId | string | The verification profile to execute. |
Returns: Promise<void> — throws if domain validation fails.
Web Components
| Tag | Default Text | Protocol |
|------------------------|--------------------------|--------------------------------|
| <ov-dcapi-btn> | "Verify with Mobile ID"| DC API — ISO 18013-5 mdoc |
| <ov-google-wallet-btn> | "Verify with Google Wallet" | OpenID4VP v1 Unsigned (Google Wallet) |
| <ov-w3c-btn> | "W3C OpenID4VP" | W3C OpenID4VP (cross-device) |
| <ov-annex-b-btn> | "Annex B mdoc" | Annex B OID4VP mdoc |
Shared Attributes
| Attribute | Type | Description |
|-----------|----------|------------------------------------|
| text | string | Overrides the default button label.|
| class | string | Standard CSS class(es). |
Shared Events & Callbacks
| DOM Event | JS Callback | Payload | Description |
|--------------|---------------------------|--------------------------|-----------------------------------------------------|
| ov-success | onVerificationSuccess | ParsedVerificationResult | Verification completed and backend-validated. |
| ov-error | onVerificationError | Error | User cancelled, or backend validation failed. |
W3C & Annex B Only
| DOM Event | JS Callback | Payload | Description |
|----------------|--------------|-----------------|----------------------------------------------------------|
| ov-uri-ready | onUriReady | { uri: string } | The openid4vp:// URI is ready. Use it to render a QR code. |
Global Window Events (Annex B redirect resume)
| Event | Payload | Description |
|--------------------|----------------------------|----------------------------------------------|
| ov-resume-success| ParsedVerificationResult | Annex B redirect session resumed successfully.|
| ov-resume-error | Error | Annex B redirect resume failed. |
VerifierClient Methods
These are accessible via window.VerifierSDK.client or by importing VerifierClient directly. All methods return Promise<ParsedVerificationResult>.
| Method | Description |
|----------------------------------------------|----------------------------------------------------------|
| verifyDCApi() | DC API flow (same-device, ISO 18013-5 mdoc). |
| verifyGoogleWallet() | Google Wallet flow (OpenID4VP v1 Unsigned). |
| initiateW3cOpenId() | Starts a W3C session. Returns { sessionId, authUri }. |
| pollW3cResult(sessionId, maxAttempts?) | Polls until wallet responds or times out (default 120s). |
| initiateAnnexB() | Starts an Annex B session. Returns { sessionId, walletUri }. |
| pollAnnexBResult(sessionId, maxAttempts?) | Polls until wallet responds or times out (default 120s). |
| resumeAnnexB(responseCode) | Resumes an Annex B session from a redirect response code.|
ResponseFormatter
| Method | Description |
|--------------------------------------------|--------------------------------------------------------------|
| parseVerificationResponse(rawResponse) | Normalizes DC API, W3C, and Annex B responses into ParsedVerificationResult. |
| formatLabel(key) | Converts snake_case or camelCase keys to Title Case for UI display. |
