SecuGen Connect Developer Guide
Browser Integration

Browser Integration Guide

A practical reference for web teams: how the loopback bridge interacts with browser security, what preflight headers you have to honor, and a graceful fallback when the bridge isn't installed.

Strategy

Use a localhost bridge API (HTTP loopback for mainstream Windows/Linux installs, HTTPS fallback where required) with a JavaScript SDK that:

Browser support notes

BrowserBehavior
Chrome / EdgeMost reliable target. Use http://127.0.0.1 with CORS allowlist and PNA/LNA handling.
FirefoxSimilar to Chrome / Edge; enterprise HTTPS fallback can still be configured when policy requires it.
Safari (macOS / iOS)HTTPS is effectively required. Mixed-content blocking and the certificate-trust UX are stricter than other browsers.

Networking pitfalls

CORS preflight (OPTIONS)

Every endpoint must respond to OPTIONS with 200 or 204 and the proper CORS headers — but only for allowed origins. The bridge enforces an explicit allowlist.

Private Network Access (PNA)

Chromium-based browsers may add Access-Control-Request-Private-Network: true on preflight when a public-origin page calls a private-network resource (loopback counts as private). When this header is present, the bridge replies with Access-Control-Allow-Private-Network: true. Without that, the request is silently blocked.

Vary: Origin

Because CORS headers vary by origin, the bridge always emits Vary: Origin to prevent intermediate caches from serving the wrong response to the wrong page.

Local transport. Mainstream Windows/Linux installs use http://127.0.0.1:4499 and do not install a Local-CA root. Keep Origin, session, nonce, rate-limit, CORS, and PNA/LNA controls enabled.

Recommended flow (web app)

  1. SGDISC /v1/discover — confirm SecuGen Connect Protocol v1 discovery while scanning 4499, then 4498-4494.
  2. GET /v1/health — verify runtime readiness; keep as legacy fallback while older bridges are in the field.
  3. POST /v1/session/start — obtain a short-lived token.
  4. POST /v1/fingerprint/capture — capture and return a template.
  5. POST /v1/auth/verify on your server — verify the template against your enrollment store and gate the user action.

Reference snippet

async function captureFingerprint(serverNonce){
  // 1. Discovery
  const discovery = await fetch('http://127.0.0.1:4499/v1/discover', {
    method:'SGDISC',
  }).then(r => r.json());
  if (discovery.protocol !== 'secugen-connect/1') throw new Error('wrong_bridge');

  // 2. Probe
  const ping = await fetch('http://127.0.0.1:4499/v1/health').then(r => r.json());
  if (!ping.ok) throw new Error('bridge_not_running');

  // 3. Session
  const ses = await fetch('http://127.0.0.1:4499/v1/session/start', {
    method:'POST',
    headers:{'Content-Type':'application/json'},
    body: JSON.stringify({ client:{ name:'app', version:'1.0.0' } }),
  }).then(r => r.json());

  // 4. Capture
  const cap = await fetch('http://127.0.0.1:4499/v1/fingerprint/capture', {
    method:'POST',
    headers:{
      'Content-Type':'application/json',
      'Authorization':`Bearer ${ses.sessionToken}`,
    },
    body: JSON.stringify({
      nonce: serverNonce,
      timeoutMs: 10000,
      minQuality: 50,
      templateFormat: 'ANSI378',
      smartCapture: true,
      blinkLed: true,
      touchGate: true,
    }),
  }).then(r => r.json());

  if (!cap.ok) throw new Error(cap.error || 'capture_failed');
  return cap.templateBase64;
}

Progressive enhancement

If the bridge isn't installed, the SDK should:

The discovery/probe pair is the trigger — a failed SGDISC /v1/discover can fall back to GET /v1/health for older bridges, while no response on the loopback range is the canonical "bridge missing" signal. Treat repeated failures as not installed; do not retry indefinitely.