npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@maiguard-hq/verify

v0.2.0

Published

MaiGuard Verify Web SDK — facial verification, liveness detection, and identity capture

Readme

@maiguard-hq/verify

MaiGuard Verify Web SDK — facial verification, liveness detection, and identity capture for browser applications.

Installation

npm install @maiguard-hq/verify

Or via CDN:

<script src="https://cdn.maiguard.com/sdk/verify/v1/maiguard-verify.min.js"></script>

Quick Start

import { MaiGuardVerify } from '@maiguard-hq/verify';

const verify = new MaiGuardVerify({
  apiKey: 'pk_live_your_key',
  containerId: '#verify-container',
  // MaiGuard's web adapter runs the official provider capture UI and returns the opaque
  // server-created liveness session id. No browser boolean can attest liveness.
  providerLivenessHandler: runMaiGuardProviderLiveness,
});

// Listen to events
verify.on('liveness:challenge', (state) => {
  console.log(`Challenge ${state.index + 1}/${state.total}: ${state.challenge}`);
});

verify.on('verification:complete', (result) => {
  console.log('Verification:', result.status, result.confidenceScore);
});

// Run verification
const result = await verify.start({
  customerId: 'user_123',
  verificationPurpose: 'onboarding',
  referenceSource: 'nin',
  referenceImage: {
    type: 'data_url',
    dataUrl: trustedNinPortrait,
  },
  checks: ['liveness', 'face_match'],
  consent: { granted: true, basis: 'explicit_consent' },
});

if (result.status === 'verified') {
  // Identity confirmed
}

// Cleanup
verify.destroy();

For a non-Nigerian journey, pass the subject's ISO-2 country to verify.start (for example, country: 'GH'). Explicit codes are normalized to uppercase and malformed or empty values are rejected before capture. Omitting country preserves the existing NG fallback for legacy integrations; it does not assert that a check is available in Nigeria or any other country. The MaiGuard API remains authoritative for tenant policy and provider coverage. A providerLivenessHandler receives the resolved country in its context. Headless API calls can also derive it from a declared subject jurisdiction.

Framework Integration

React

import { MaiGuardVerify } from '@maiguard-hq/verify';
import { useEffect, useRef } from 'react';

function VerifyComponent({ onComplete }) {
  const containerRef = useRef(null);

  useEffect(() => {
    const verify = new MaiGuardVerify({
      apiKey: 'pk_live_...',
      containerId: '#verify-mount',
      providerLivenessHandler: runMaiGuardProviderLiveness,
    });

    verify.start({
      customerId: 'user_123',
      verificationPurpose: 'onboarding',
      referenceSource: 'bvn',
      referenceImage: { type: 'data_url', dataUrl: trustedBvnPortrait },
      checks: ['liveness', 'face_match'],
      consent: { granted: true },
    }).then(onComplete);

    return () => verify.destroy();
  }, []);

  return <div id="verify-mount" ref={containerRef} />;
}

Vanilla JavaScript

<div id="verify-container"></div>
<script src="https://cdn.maiguard.com/sdk/verify/v1/maiguard-verify.min.js"></script>
<script>
  const verify = new MaiGuardVerify({
    apiKey: 'pk_live_...',
    containerId: '#verify-container',
    providerLivenessHandler: runMaiGuardProviderLiveness,
  });

  verify.start({
    customerId: '12345',
    verificationPurpose: 'account_recovery',
    referenceSource: 'internal_profile',
    referenceImage: { type: 'secure_url', url: trustedPortraitUrl },
    checks: ['liveness', 'face_match'],
    consent: { granted: true },
  }).then(result => {
    console.log(result.status);
  });
</script>

Events

| Event | Payload | Description | |-------|---------|-------------| | camera:ready | { devices } | Camera stream started | | face:detected | FaceDetectionResult | Face found in frame | | face:lost | — | Face no longer visible | | quality:check | FaceDetectionResult | Quality check run | | liveness:start | { challenges } | Liveness flow began | | liveness:challenge | LivenessChallengeState | Challenge state change | | liveness:complete | LivenessResult | All challenges done | | upload:progress | UploadProgress | Upload progress | | verification:complete | VerificationResult | Final result | | error | { error, code, recoverable } | Any error |

Security

  • Long-lived provider credentials are never embedded in the SDK. A capture adapter may receive short-lived, least-privilege credentials from MaiGuard for the active session only.
  • Face matching cannot run without liveness in the same SDK flow
  • Liveness requires a provider-attested session; browser gesture results are never converted into a pass
  • The trusted portrait may come from NIN, BVN, a document, or another partner-approved source
  • Secure reference URLs are fetched in the browser with credentials omitted, redirects blocked, content type checked, and a 10 MB size limit
  • The API receives image data, not an arbitrary URL to fetch server-side
  • Biometric data is kept in memory only for the active verification flow
  • HTTPS enforced
  • Device metadata sent for fraud analysis

The web SDK uses a providerLivenessHandler boundary for the official provider capture component. The handler returns an opaque session id; MaiGuard retrieves the provider result server-side and uses the provider-selected live frame for face matching. MediaPipe positioning may guide capture, but it is never authoritative liveness evidence.

Reference image model

MaiGuard Verify is reference-image agnostic. The integrating business chooses the trusted identity source, while the SDK owns consent, camera guidance, live capture, liveness, and submission to MaiGuard for face matching and decisioning.

Supported browser inputs are:

  • { type: 'data_url', dataUrl } for a trusted base64 portrait, including NIN or BVN responses
  • { type: 'blob', blob } for a browser Blob or File
  • { type: 'secure_url', url } for a short-lived HTTPS URL that allows cross-origin browser access
  • { type: 'server_reference', referenceId } for a first-party flow whose custom verificationHandler resolves an existing protected portrait without sending it to the browser

Use verification:complete or the returned promise as the in-app result handler. Configure server-to-server webhooks in MaiGuard rather than accepting a callback URL from browser code.

Verify identity graph capture

When the merchant enables identity-link face search, supply a stable applicationRef for the application. Forward the handler's applicationRef, country and metadata unchanged when creating the liveness session; submit that same application reference and returned session ID for verification. Sessions are scoped to the merchant, environment and application, expire after three minutes, and are consumed once. A new capture attempt needs a new provider session. Retries of a consumed capture return its saved result.

Request consent.scopes: ['biometric', 'biometric_search', 'biometric_index'] only after the applicant explicitly agrees to those purposes. Search and enrollment are separate permissions; ordinary biometric consent does not authorize either. MaiGuard's tenant policy must enable each operation as well.

Device attributes are reported context. MaiGuard records the connection IP and, when available, country inferred from its local IP database. This is Verify application context, separate from Sentinel telemetry. A backend relay should send metadata.transport: 'merchant_relay'; its connection IP is the backend's IP. No precise GPS is collected. Keep these fields out of merchant debug logs.

Read identityLinkAssessment independently of the verification checks. incomplete and not_checked do not mean that no related identity exists. A face candidate never automatically merges identities.