npm.io
3.5.2 • Published 2 months ago

@safepassage/sdk

Licence
MIT
Version
3.5.2
Deps
0
Size
111 kB
Vulns
0
Weekly
218

SafePassage SDK v3.5.2

A lightweight SDK for integrating SafePassage age verification into your website or application.

Features

  • Ultra-lightweight: ~18KB minified
  • Simple integration: 5 lines of code to get started
  • Two modes: Same-tab redirect or new-tab popup
  • TypeScript support: Full type definitions included
  • Auto-environment detection: Works seamlessly across environments
  • Secure: HMAC-signed state parameters, automatic session management
  • Compliant: Enforces minimum age of 25

Changelog

3.5.2
  • SafePassage version alignment release to match PrivateAV at 3.5.2
  • No SDK API changes from 3.5.0
3.5.0
  • Added language option for UI localization (en, de, es, fr, pt)
  • Per-verification language override via verify({ language: 'es' })
3.4.11
  • Fixed CDN documentation URLs (files are at package root, not /dist/)
3.4.9
  • Prevents onCancel from firing after a successful new-tab verification when the popup closes.

Installation

npm install @safepassage/sdk

Or load directly from jsDelivr CDN (no bundler required):

<script src="https://cdn.jsdelivr.net/npm/@safepassage/sdk@latest/safepassage.min.js"></script>

Quick Start

With npm/bundler
import { SafePassage } from '@safepassage/sdk';

const sp = new SafePassage({
  apiKey: 'pk_...',  // Your public key from the dashboard
  returnUrl: window.location.origin + '/verified'
});

// Start verification - redirects user to SafePassage
await sp.verify();
With CDN (no bundler)
<script src="https://cdn.jsdelivr.net/npm/@safepassage/sdk@latest/safepassage.min.js"></script>
<script>
  const sp = new SafePassage({
    apiKey: 'pk_...',
    returnUrl: window.location.origin + '/verified'
  });

  document.getElementById('verify-btn').onclick = () => sp.verify();
</script>

That's it! The SDK handles session creation automatically.

Configuration

Option Type Required Description
apiKey string Yes Your public API key (pk_...)
returnUrl string Yes URL to redirect after verification
cancelUrl string No URL to redirect to if user closes the verification window (new-tab mode)
environment string No 'production' or 'staging' (auto-detected)
mode string No 'redirect' (default) or 'new-tab'
defaultChallengeAge number No Default minimum age (25 or higher)
defaultVerificationMode string No 'L1' or 'L2'
onComplete function No Callback for new-tab mode
onCancel function No Called when user closes popup (new-tab mode). Return false to suppress automatic cancelUrl redirect.
language string No Default UI language ('en', 'de', 'es', 'fr', 'pt'). Can be overridden per verification.
onError function No Error handler

Verification Options

Override settings per-verification:

await sp.verify({
  challengeAge: 30,           // Override minimum age for this session
  verificationMode: 'L2',     // Force ID verification for this session
  externalUserId: 'user-123', // Your user ID (returned in webhooks)
  skipIntro: true,            // Skip intro screen
  autoReturn: true,           // Auto-redirect after success
  language: 'es'              // Override UI language for this session
});
Verification Modes
  • L1: Age estimation using computer vision (faster, less friction)
  • L2: Full ID document verification (more thorough)

Integration Modes

Same-Tab Redirect (Default)

User is redirected to SafePassage, then back to your returnUrl:

const sp = new SafePassage({
  apiKey: 'pk_...',
  returnUrl: '/age-verified'
});

await sp.verify();
// User is redirected to SafePassage...
// After verification, user returns to /age-verified?sessionId=xxx&status=verified
New-Tab Mode

Verification opens in a popup window:

const sp = new SafePassage({
  apiKey: 'pk_...',
  returnUrl: '/age-verified',
  cancelUrl: '/age-cancelled',
  mode: 'new-tab',
  onComplete: (result) => {
    console.log('Verification complete:', result.sessionId, result.status);
    // Validate on your server, then update UI
  },
  onCancel: () => {
    console.log('User closed the verification window');
    // Return false if you want to handle navigation manually
    // return false;
  },
  onError: (error) => {
    console.error('Verification error:', error.message);
  }
});

await sp.verify();

If cancelUrl is provided, the SDK will redirect the opener to cancelUrl with status=cancelled and sessionId when the user closes the verification window. Return false from onCancel to suppress the automatic redirect.

Server-Side Validation (Required!)

After verification completes, always validate the result on your server before granting access:

// Node.js / Express example
app.get('/age-verified', async (req, res) => {
  const { sessionId } = req.query;

  // Validate with your SECRET key (sk_...)
  const response = await fetch(
    `https://api.safepassageapp.com/api/v1/sessions/${sessionId}`,
    {
      headers: {
        'Authorization': `Bearer ${process.env.SAFEPASSAGE_SECRET_KEY}`
      }
    }
  );

  const session = await response.json();

  if (session.status === 'VERIFIED') {
    // Grant access
    req.session.ageVerified = true;
    res.redirect('/content');
  } else {
    res.redirect('/age-verification-failed');
  }
});

Security Note: Never trust client-side verification status alone. Always validate server-side using your secret key.

For reliable verification tracking, configure webhooks in your dashboard:

// Webhook payload example
{
  "event": "verification.completed",
  "sessionId": "abc-123",
  "verified": true,
  "externalUserId": "your-user-id",  // If provided during verify()
  "timestamp": "2025-01-15T10:30:00Z"
}

Complete Example

HTML + CDN
<!DOCTYPE html>
<html>
<head>
  <title>Age Verification</title>
  <script src="https://cdn.jsdelivr.net/npm/@safepassage/sdk@latest/safepassage.min.js"></script>
</head>
<body>
  <button id="verify-btn">Verify Your Age</button>

  <script>
    const sp = new SafePassage({
      apiKey: 'pk_...',
      returnUrl: window.location.origin + '/verified'
    });

    document.getElementById('verify-btn').onclick = () => sp.verify();
  </script>
</body>
</html>
React Component
import { useState } from 'react';
import { SafePassage } from '@safepassage/sdk';

function AgeGate() {
  const [verifying, setVerifying] = useState(false);

  const sp = new SafePassage({
    apiKey: process.env.NEXT_PUBLIC_SAFEPASSAGE_KEY,
    returnUrl: window.location.origin + '/verified'
  });

  const handleVerify = async () => {
    setVerifying(true);
    try {
      await sp.verify();
    } catch (error) {
      console.error('Failed to start verification:', error);
      setVerifying(false);
    }
  };

  return (
    <button onClick={handleVerify} disabled={verifying}>
      {verifying ? 'Redirecting...' : 'Verify Your Age'}
    </button>
  );
}

TypeScript

Full TypeScript support included:

import { SafePassage, SafePassageConfig, VerificationResult } from '@safepassage/sdk';

const config: SafePassageConfig = {
  apiKey: process.env.NEXT_PUBLIC_SAFEPASSAGE_KEY!,
  returnUrl: '/verified',
  mode: 'new-tab',
  onComplete: (result: VerificationResult) => {
    console.log(`Session ${result.sessionId}: ${result.status}`);
  }
};

const sp = new SafePassage(config);

Skip Parameters

For streamlined embedded flows:

// Skip intro screen (go directly to camera)
await sp.verify({ skipIntro: true });

// Auto-redirect after success (no success screen)
await sp.verify({ autoReturn: true });

// Both - minimal user interaction
await sp.verify({ skipIntro: true, autoReturn: true });

Error Handling

const sp = new SafePassage({
  apiKey: 'pk_...',
  returnUrl: '/verified',
  onError: (error) => {
    if (error.message.includes('popup')) {
      alert('Please allow popups for age verification');
    } else if (error.message.includes('rate limit')) {
      alert('Too many attempts. Please wait a moment.');
    } else {
      console.error('Verification error:', error);
    }
  }
});

API Keys

SafePassage uses two types of API keys:

Key Type Prefix Use Case
Public Key pk_ Client-side SDK (this package)
Secret Key sk_ Server-side validation only

Important: This SDK only works with public keys (pk_). For server-side integrations using secret keys, use the Direct API instead.

Browser Support

  • Chrome 60+
  • Firefox 60+
  • Safari 12+
  • Edge 79+
  • Mobile browsers (iOS Safari, Chrome for Android)

Security Best Practices

  1. Use public keys client-side - Never expose secret keys in browser code
  2. Validate server-side - Always verify results using your secret key
  3. Configure webhooks - For reliable, tamper-proof verification notifications
  4. Register callback URLs - Pre-register your returnUrl in the dashboard
  5. Use HTTPS - SDK enforces HTTPS in production

Cleanup

When done with the SDK (e.g., in SPA route changes):

sp.destroy();

Migration from v3.0.x

If you were using merchant-generated session IDs:

// Old (v3.0.x)
sp.verify({ sessionId: crypto.randomUUID() });

// New (v3.4+) - sessionId is auto-generated
await sp.verify();

The SDK now creates sessions automatically via the API when using public keys.

Support

Keywords