@safepassage/sdk
Version:
SafePassage SDK - Lightweight redirect-based age verification
267 lines (214 loc) • 7.33 kB
Markdown
# SafePassage SDK v3.0.0 - Redirect Implementation
A lightweight SDK for integrating SafePassage age verification using a simple redirect flow.
## Features
- **Ultra-lightweight**: Only 4.9KB minified (1.9KB gzipped)
- **Simple integration**: Just 10 lines of code
- **Two modes**: Same-tab redirect or new-tab popup
- **TypeScript support**: Full type definitions included
- **Auto-environment detection**: Works seamlessly in development
- **Secure**: Merchant-generated session IDs prevent attacks
- **Compliant**: Enforces minimum age of 25
## Installation
```bash
npm install @safepassage/sdk
```
## Quick Start
```javascript
// Initialize SDK
const safePassage = new SafePassage({
apiKey: 'sk_live_xxxxx', // Your API key
returnUrl: 'https://yoursite.com/verified',
cancelUrl: 'https://yoursite.com/cancelled'
});
// Generate a session ID (must be UUID v4)
const sessionId = crypto.randomUUID();
// Trigger verification
safePassage.verify({
sessionId: sessionId, // Required: merchant-generated UUID
challengeAge: 25, // Optional: minimum age (25 or higher)
verificationMode: 'L1' // Optional: 'L1' or 'L2'
});
```
## Configuration
| Option | Type | Required | Description |
|--------|------|----------|-------------|
| apiKey | string | Yes | Your API key (sk_live_xxx or sk_test_xxx) |
| returnUrl | string | Yes | URL to redirect after successful verification |
| cancelUrl | string | Yes | URL to redirect if user cancels |
| environment | string | No | 'production', 'staging', or 'development' (auto-detected) |
| mode | string | No | 'redirect' (default) or 'new-tab' |
| onComplete | function | No | Callback for new-tab mode completion |
| onCancel | function | No | Callback for new-tab mode cancellation |
| onError | function | No | Error handler |
## Verification Options
```javascript
safePassage.verify({
sessionId: 'uuid-v4', // Required: merchant-generated UUID
challengeAge: 30, // Optional: min 25 (overrides dashboard setting)
verificationMode: 'L2' // Optional: 'L1' or 'L2' (overrides dashboard setting)
});
```
### Configuration Override Behavior
When you pass `challengeAge` or `verificationMode` to the `verify()` method, these values take precedence over your dashboard configuration for that specific verification session:
- **No overrides**: Uses your current dashboard settings
- **With overrides**: SDK values are used instead of dashboard settings
- **Challenge age**: Must be 25 or higher (lower values will be rejected)
- **Verification mode**:
- `'L1'`: Age estimation with computer vision
- `'L2'`: Always requires ID verification
Example use cases:
```javascript
// Use dashboard defaults
safePassage.verify({ sessionId: crypto.randomUUID() });
// Override just challenge age
safePassage.verify({
sessionId: crypto.randomUUID(),
challengeAge: 30 // Require age 30+ for this session
});
// Override just verification mode
safePassage.verify({
sessionId: crypto.randomUUID(),
verificationMode: 'L2' // Force ID check for this session
});
// Override both
safePassage.verify({
sessionId: crypto.randomUUID(),
challengeAge: 30,
verificationMode: 'L2' // ID required for 30+ verification
});
```
## Modes
### Same-Tab Redirect (Default)
User is redirected to SafePassage, then back to your site:
```javascript
const safePassage = new SafePassage({
apiKey: 'sk_live_xxxxx',
returnUrl: '/age-verified',
cancelUrl: '/age-gate'
});
safePassage.verify({ sessionId: crypto.randomUUID() });
```
### New-Tab Mode
Verification opens in a popup window:
```javascript
const safePassage = new SafePassage({
apiKey: 'sk_live_xxxxx',
returnUrl: '/age-verified',
cancelUrl: '/age-gate',
mode: 'new-tab',
onComplete: (result) => {
console.log('Verified:', result.sessionId);
// Validate on your server!
},
onCancel: () => {
console.log('User cancelled');
}
});
safePassage.verify({ sessionId: crypto.randomUUID() });
```
## Server-Side Validation (Required!)
Always validate the session on your server:
```javascript
// Node.js example
const response = await fetch('https://api.safepassageapp.com/v1/sessions/validate', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk_live_xxxxx', // Secret key
'Content-Type': 'application/json'
},
body: JSON.stringify({ sessionId })
});
const result = await response.json();
if (result.verified && result.estimatedAge >= result.challengeAge) {
// Grant access
}
```
## UUID Generation
You must generate session IDs on your end. Use the built-in crypto.randomUUID() when available:
```javascript
// Modern browsers and Node.js 16+
const sessionId = crypto.randomUUID();
// Fallback for older environments
function generateUUID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
```
## Complete Example
```html
<!DOCTYPE html>
<html>
<head>
<!-- Install via NPM: npm install @safepassage/sdk -->
<script src="node_modules/@safepassage/sdk/dist/safepassage.min.js"></script>
</head>
<body>
<button onclick="verifyAge()">Verify Your Age</button>
<script>
const safePassage = new SafePassage({
apiKey: 'sk_live_xxxxx',
returnUrl: window.location.href + '?verified=true',
cancelUrl: window.location.href
});
function verifyAge() {
// Use crypto.randomUUID() if available, otherwise fallback
const sessionId = typeof crypto.randomUUID === 'function'
? crypto.randomUUID()
: 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
sessionStorage.setItem('pendingVerification', sessionId);
safePassage.verify({ sessionId });
}
// Check if returning from verification
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.get('verified') === 'true') {
const sessionId = sessionStorage.getItem('pendingVerification');
// Validate session server-side here
console.log('Validate session:', sessionId);
}
</script>
</body>
</html>
```
## TypeScript
Full TypeScript support included:
```typescript
import { SafePassage, SafePassageConfig } from '@safepassage/sdk';
const config: SafePassageConfig = {
apiKey: process.env.SAFEPASSAGE_PUBLIC_KEY!,
returnUrl: '/verified',
cancelUrl: '/cancelled'
};
const safePassage = new SafePassage(config);
```
## Migration from v2 (iframe)
Old iframe approach (1000+ lines):
```javascript
// Complex iframe setup...
```
New redirect approach (10 lines):
```javascript
const safePassage = new SafePassage({
apiKey: 'sk_live_xxxxx',
returnUrl: '/verified',
cancelUrl: '/cancelled'
});
safePassage.verify({ sessionId: crypto.randomUUID() });
```
## Browser Support
- Chrome 60+
- Firefox 60+
- Safari 12+
- Edge 79+
- Mobile browsers
## Security Notes
1. Always generate session IDs on the merchant side
2. Validate sessions server-side before granting access
3. Pre-register callback URLs in your dashboard
4. Never expose your secret key (sk_live_xxx)