@safepassage/sdk 3.4.8 → 3.4.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,651 +0,0 @@
1
- /**
2
- * SafePassage SDK - Redirect-based age verification
3
- *
4
- * Lightweight SDK for integrating SafePassage age verification using redirect flow.
5
- * Provides a secure, easy-to-implement solution for age verification with comprehensive
6
- * security features and flexible integration options.
7
- *
8
- * Key Features:
9
- * - Redirect and new-tab verification modes
10
- * - Automatic session management for public API keys
11
- * - HMAC-signed state parameters for security
12
- * - Rate limiting and race condition protection
13
- * - Comprehensive security validation and logging
14
- * - PostMessage communication for new-tab mode
15
- * - Automatic cleanup and resource management
16
- * - Environment-specific configuration
17
- *
18
- * Security Features:
19
- * - Origin validation for PostMessage communication
20
- * - HTTPS enforcement in production
21
- * - Rate limiting per API key and origin
22
- * - State parameter signing with timestamps and nonces
23
- * - Comprehensive security event logging
24
- * - Protection against race conditions and replay attacks
25
- *
26
- * @author SafePassage Engineering
27
- * @version 2.0.0
28
- * @since 1.0.0
29
- */
30
- import { generateState, validateConfig } from '../utils/validation';
31
- import { getEnvironmentUrl, validateEnvironmentSecurity, } from '../utils/environment';
32
- import { validatePostMessageOrigin, validateSafePassageMessage, enforceHTTPS, verificationRateLimit, logSecurityEvent, } from '../utils/security';
33
- /**
34
- * SafePassage SDK Main Class
35
- *
36
- * Primary SDK class that manages age verification sessions with comprehensive
37
- * security and error handling. Supports both redirect and new-tab modes with
38
- * automatic session management and PostMessage communication.
39
- *
40
- * The class implements multiple security layers including origin validation,
41
- * rate limiting, state signing, and comprehensive event logging to ensure
42
- * secure verification flows.
43
- */
44
- export class SafePassage {
45
- /**
46
- * Initialize SafePassage SDK
47
- *
48
- * Validates configuration, sets up security measures, and prepares the SDK
49
- * for verification operations. Performs comprehensive environment validation
50
- * and security initialization.
51
- *
52
- * @param {SafePassageConfig} config - SDK configuration object
53
- * @throws {Error} If configuration validation fails
54
- */
55
- constructor(config) {
56
- this.popupWindow = null;
57
- this.messageListener = null;
58
- this.popupMonitorInterval = null;
59
- this.unloadListener = null;
60
- this.isVerificationInProgress = false;
61
- this.currentSessionId = null;
62
- // Server-provided verify URL (includes sessionToken)
63
- this.lastVerifyUrl = null;
64
- // Server-provided session token (WS auth)
65
- this.lastSessionToken = null;
66
- // Temporary storage for QR handoff token to include in state
67
- this.temporaryHandoffToken = null;
68
- validateConfig(config);
69
- // Normalize environment: treat 'development' or any unknown value as 'production'
70
- let normalizedEnvironment = config.environment || this.detectEnvironment();
71
- if (normalizedEnvironment !== 'staging' && normalizedEnvironment !== 'production') {
72
- console.warn(`SafePassage SDK: Unknown environment '${normalizedEnvironment}', defaulting to 'production'`);
73
- normalizedEnvironment = 'production';
74
- }
75
- this.config = Object.assign(Object.assign({}, config), { environment: normalizedEnvironment, mode: config.mode || 'redirect' });
76
- // Comprehensive environment security validation
77
- validateEnvironmentSecurity(this.config.environment);
78
- // Enforce HTTPS in production (additional layer)
79
- enforceHTTPS(this.config.environment);
80
- // Log initialization for security monitoring
81
- logSecurityEvent('SDK_INITIALIZED', {
82
- environment: this.config.environment,
83
- mode: this.config.mode,
84
- origin: window.location.origin,
85
- protocol: window.location.protocol,
86
- hostname: window.location.hostname,
87
- });
88
- // Set up automatic cleanup on page unload
89
- this.setupAutoCleanup();
90
- }
91
- /**
92
- * Initiate age verification with race condition protection
93
- *
94
- * Main verification method that handles session creation, security validation,
95
- * and verification flow initiation. Includes race condition protection and
96
- * comprehensive error handling.
97
- *
98
- * For public keys (pk_*), automatically creates sessions via the portal API.
99
- * For private keys (sk_*), requires a pre-created sessionId.
100
- *
101
- * @param {VerificationOptions} [options={}] - Verification options
102
- * @param {string} [options.sessionId] - Session ID (required for private keys)
103
- * @param {number} [options.challengeAge] - Age challenge override
104
- * @param {string} [options.verificationMode] - Verification mode override
105
- * @param {string} [options.externalUserId] - External user identifier
106
- * @returns {Promise<void>} Promise that resolves when verification is initiated
107
- * @throws {Error} If verification cannot be started or is already in progress
108
- */
109
- async verify(options = {}) {
110
- var _a, _b, _c, _d, _e, _f;
111
- const isPublicKey = this.isPublicKey();
112
- // For public keys, create session via API (SafePassage generates the sessionId)
113
- let sessionId;
114
- if (isPublicKey) {
115
- sessionId = await this.createInternalSession(options);
116
- }
117
- else {
118
- // Private keys should use the direct API, not the SDK
119
- throw new Error('Private API keys (sk_) should use the direct API, not the SDK. ' +
120
- 'The SDK is designed for browser-based public key usage only.');
121
- }
122
- if (!sessionId) {
123
- throw new Error('Failed to obtain sessionId from server');
124
- }
125
- // Race condition check - prevent multiple simultaneous verifications
126
- if (this.isVerificationInProgress) {
127
- const error = new Error(`Verification already in progress for session ${(_a = this.currentSessionId) === null || _a === void 0 ? void 0 : _a.substring(0, 8)}...`);
128
- logSecurityEvent('RACE_CONDITION_PREVENTED', {
129
- currentSession: ((_b = this.currentSessionId) === null || _b === void 0 ? void 0 : _b.substring(0, 8)) + '...',
130
- attemptedSession: 'new-session-attempt',
131
- origin: window.location.origin,
132
- });
133
- (_d = (_c = this.config).onError) === null || _d === void 0 ? void 0 : _d.call(_c, error);
134
- throw error;
135
- }
136
- // Lock verification process
137
- this.isVerificationInProgress = true;
138
- this.currentSessionId = sessionId;
139
- try {
140
- // Rate limiting check
141
- const rateLimitKey = `${this.config.apiKey}:${window.location.origin}`;
142
- if (!verificationRateLimit.isAllowed(rateLimitKey)) {
143
- const error = new Error('Too many verification attempts. Please wait before trying again.');
144
- logSecurityEvent('RATE_LIMIT_EXCEEDED', {
145
- apiKey: this.config.apiKey.substring(0, 8) + '...',
146
- origin: window.location.origin,
147
- sessionId: sessionId
148
- ? sessionId.substring(0, 8) + '...'
149
- : 'undefined',
150
- });
151
- (_f = (_e = this.config).onError) === null || _f === void 0 ? void 0 : _f.call(_e, error);
152
- throw error;
153
- }
154
- const verificationUrl = await this.buildVerificationUrl(options, sessionId);
155
- // Log verification attempt
156
- logSecurityEvent('VERIFICATION_INITIATED', {
157
- environment: this.config.environment,
158
- mode: this.config.mode,
159
- sessionId: sessionId ? sessionId.substring(0, 8) + '...' : 'undefined',
160
- origin: window.location.origin,
161
- });
162
- if (this.config.mode === 'new-tab') {
163
- this.openNewTab(verificationUrl, sessionId);
164
- }
165
- else {
166
- // For redirect mode, unlock immediately since we're leaving the page
167
- this.unlockVerification();
168
- this.redirect(verificationUrl);
169
- }
170
- }
171
- catch (error) {
172
- // Always unlock on error
173
- this.unlockVerification();
174
- throw error;
175
- }
176
- }
177
- /**
178
- * Build verification URL with HMAC-signed state
179
- *
180
- * Constructs the verification URL with signed state parameter containing
181
- * all necessary configuration and security information. The state parameter
182
- * includes HMAC signature for integrity protection.
183
- *
184
- * @param {VerificationOptions} options - Verification options
185
- * @returns {Promise<string>} Complete verification URL
186
- * @private
187
- */
188
- async buildVerificationUrl(options, sessionId) {
189
- const baseUrl = getEnvironmentUrl(this.config.environment);
190
- // Determine if we have explicit overrides
191
- const hasExplicitChallengeAge = options.challengeAge !== undefined;
192
- const hasExplicitVerificationMode = options.verificationMode !== undefined;
193
- const hasOverrides = hasExplicitChallengeAge || hasExplicitVerificationMode;
194
- const state = await generateState({
195
- merchantId: this.config.apiKey,
196
- sessionId,
197
- returnUrl: this.config.returnUrl,
198
- cancelUrl: this.config.cancelUrl,
199
- challengeAge: options.challengeAge || this.config.defaultChallengeAge,
200
- verificationMode: options.verificationMode || this.config.defaultVerificationMode,
201
- hasOverrides: hasOverrides, // Flag to indicate explicit overrides
202
- externalUserId: options.externalUserId,
203
- timestamp: Date.now(),
204
- // Phase 2: Include config for self-contained verify-ui
205
- apiUrl: this.getPortalApiUrl(),
206
- engineUrl: this.getEngineUrl(),
207
- wsUrl: this.getWebSocketUrl(),
208
- environment: this.config.environment,
209
- features: {
210
- testMode: false,
211
- warmupPeriodMs: 500,
212
- qualityThreshold: 0.6,
213
- },
214
- // Include handoffToken if available (for QR code desktop flow)
215
- handoffToken: this.temporaryHandoffToken || undefined,
216
- // Include sessionToken and verifyUrl to make UI auth deterministic
217
- sessionToken: this.lastSessionToken || undefined,
218
- verifyUrl: this.lastVerifyUrl || undefined,
219
- }, this.config.environment);
220
- // Prefer server-provided verifyUrl (contains sessionToken) and append state/mode
221
- if (this.lastVerifyUrl) {
222
- try {
223
- const url = new URL(this.lastVerifyUrl);
224
- url.searchParams.set('state', state);
225
- url.searchParams.set('mode', this.config.mode);
226
- // Append skip parameters if provided
227
- if (options.skipIntro) {
228
- url.searchParams.set('skip_intro', 'true');
229
- }
230
- if (options.autoReturn) {
231
- url.searchParams.set('auto_return', 'true');
232
- }
233
- return url.toString();
234
- }
235
- catch (_a) {
236
- // Fall back to client-constructed URL if parsing fails
237
- }
238
- }
239
- // Client-constructed URL fallback (for backwards compatibility)
240
- const params = new URLSearchParams({ state, sessionId, mode: this.config.mode });
241
- // Append skip parameters if provided
242
- if (options.skipIntro) {
243
- params.set('skip_intro', 'true');
244
- }
245
- if (options.autoReturn) {
246
- params.set('auto_return', 'true');
247
- }
248
- return `${baseUrl}/?${params.toString()}`;
249
- }
250
- /**
251
- * Redirect in same tab
252
- *
253
- * Performs a full page redirect to the verification URL.
254
- * Used for redirect mode verification.
255
- *
256
- * @param {string} url - Verification URL to redirect to
257
- * @private
258
- */
259
- redirect(url) {
260
- window.location.href = url;
261
- }
262
- /**
263
- * Open in new tab with PostMessage communication and proper cleanup
264
- *
265
- * Opens verification URL in a new tab/window and sets up secure PostMessage
266
- * communication for receiving verification results. Includes comprehensive
267
- * security validation and automatic cleanup.
268
- *
269
- * @param {string} url - Verification URL to open
270
- * @param {string} sessionId - Session ID for result correlation
271
- * @private
272
- */
273
- openNewTab(url, sessionId) {
274
- var _a, _b;
275
- // Clean up any existing resources
276
- this.cleanup();
277
- // Clear any existing popup monitor interval
278
- if (this.popupMonitorInterval) {
279
- clearInterval(this.popupMonitorInterval);
280
- this.popupMonitorInterval = null;
281
- }
282
- // Open new tab
283
- this.popupWindow = window.open(url, 'safepassage-verify', 'width=600,height=700');
284
- if (!this.popupWindow) {
285
- (_b = (_a = this.config).onError) === null || _b === void 0 ? void 0 : _b.call(_a, new Error('Failed to open verification window. Please check popup blocker settings.'));
286
- return;
287
- }
288
- // Set up PostMessage listener with enhanced security
289
- this.messageListener = (event) => {
290
- var _a, _b, _c, _d, _e, _f, _g;
291
- // First: Check if this is a SafePassage message (has our message type prefix)
292
- // Silently ignore non-SafePassage messages (browser extensions, other libraries)
293
- const messageType = (_a = event.data) === null || _a === void 0 ? void 0 : _a.type;
294
- if (!messageType || typeof messageType !== 'string' || !messageType.startsWith('safepassage:')) {
295
- // Not a SafePassage message - silently ignore
296
- return;
297
- }
298
- // Enhanced origin validation with strict allowlist (only for SafePassage messages)
299
- if (!validatePostMessageOrigin(event, this.config.environment)) {
300
- logSecurityEvent('POSTMESSAGE_ORIGIN_BLOCKED', {
301
- origin: event.origin,
302
- environment: this.config.environment,
303
- expectedOrigins: `SafePassage trusted origins for ${this.config.environment}`,
304
- messageType: (_b = event.data) === null || _b === void 0 ? void 0 : _b.type,
305
- });
306
- return;
307
- }
308
- // Enhanced message validation
309
- const messageValidation = validateSafePassageMessage(event, sessionId);
310
- if (!messageValidation.isValid) {
311
- logSecurityEvent('POSTMESSAGE_VALIDATION_FAILED', {
312
- error: messageValidation.error,
313
- origin: event.origin,
314
- sessionId: sessionId.substring(0, 8) + '...',
315
- messageType: (_c = event.data) === null || _c === void 0 ? void 0 : _c.type,
316
- });
317
- return;
318
- }
319
- const result = {
320
- sessionId: event.data.sessionId,
321
- status: event.data.status,
322
- timestamp: event.data.timestamp,
323
- externalUserId: event.data.externalUserId,
324
- };
325
- // Log successful verification completion
326
- logSecurityEvent('VERIFICATION_COMPLETED', {
327
- status: result.status,
328
- sessionId: sessionId.substring(0, 8) + '...',
329
- origin: event.origin,
330
- });
331
- // Clean up resources but keep the popup open for post-verification actions
332
- this.cleanup({ closePopup: false });
333
- // Unlock verification after successful completion
334
- this.unlockVerification();
335
- // Clear monitoring interval
336
- if (this.popupMonitorInterval) {
337
- clearInterval(this.popupMonitorInterval);
338
- this.popupMonitorInterval = null;
339
- }
340
- // Trigger appropriate callback
341
- if (result.status === 'verified') {
342
- (_e = (_d = this.config).onComplete) === null || _e === void 0 ? void 0 : _e.call(_d, result);
343
- }
344
- else {
345
- // Status is 'failed' - trigger error callback
346
- (_g = (_f = this.config).onError) === null || _g === void 0 ? void 0 : _g.call(_f, new Error(`Verification failed: ${result.status}`));
347
- }
348
- };
349
- window.addEventListener('message', this.messageListener);
350
- // Monitor popup window with proper cleanup
351
- this.popupMonitorInterval = setInterval(() => {
352
- var _a, _b;
353
- if (this.popupWindow && this.popupWindow.closed) {
354
- // Log popup closed event
355
- logSecurityEvent('POPUP_CLOSED_BY_USER', {
356
- sessionId: sessionId.substring(0, 8) + '...',
357
- environment: this.config.environment,
358
- });
359
- // Clean up and trigger cancel callback
360
- this.cleanup();
361
- // Unlock verification after popup closed
362
- this.unlockVerification();
363
- (_b = (_a = this.config).onCancel) === null || _b === void 0 ? void 0 : _b.call(_a);
364
- }
365
- }, 500);
366
- }
367
- /**
368
- * Set up automatic cleanup on page unload to prevent memory leaks
369
- *
370
- * Registers event listeners for page unload events to ensure proper
371
- * cleanup of resources and verification state. Handles both traditional
372
- * page navigation and single-page application route changes.
373
- *
374
- * @private
375
- */
376
- setupAutoCleanup() {
377
- this.unloadListener = () => {
378
- // Log automatic cleanup
379
- logSecurityEvent('SDK_AUTO_CLEANUP', {
380
- environment: this.config.environment,
381
- trigger: 'page_unload',
382
- });
383
- // Clean up all resources and unlock verification
384
- this.cleanup();
385
- this.unlockVerification();
386
- };
387
- // Listen for page unload events
388
- window.addEventListener('beforeunload', this.unloadListener);
389
- window.addEventListener('pagehide', this.unloadListener);
390
- // For single-page applications, also listen for route changes
391
- if (window.history && window.history.pushState) {
392
- const originalPushState = window.history.pushState;
393
- window.history.pushState = (...args) => {
394
- this.cleanup();
395
- this.unlockVerification();
396
- return originalPushState.apply(window.history, args);
397
- };
398
- }
399
- }
400
- /**
401
- * Auto-detect environment based on current URL
402
- *
403
- * Analyzes the current hostname to determine the appropriate environment
404
- * configuration. Used when environment is not explicitly specified.
405
- * Always defaults to production unless staging is detected.
406
- *
407
- * @returns {'production' | 'staging'} Detected environment
408
- * @private
409
- */
410
- detectEnvironment() {
411
- const hostname = window.location.hostname;
412
- if (hostname.includes('staging') || hostname.includes('stage')) {
413
- return 'staging';
414
- }
415
- return 'production';
416
- }
417
- /**
418
- * Get the current environment
419
- * @returns {string} The current environment (production or staging)
420
- */
421
- getEnvironment() {
422
- return this.config.environment;
423
- }
424
- /**
425
- * Unlock verification process to allow new verifications
426
- *
427
- * Resets the verification lock state to allow new verification attempts.
428
- * Called after successful completion, errors, or cleanup.
429
- *
430
- * @private
431
- */
432
- unlockVerification() {
433
- this.isVerificationInProgress = false;
434
- this.currentSessionId = null;
435
- logSecurityEvent('VERIFICATION_UNLOCKED', {
436
- environment: this.config.environment,
437
- origin: window.location.origin,
438
- });
439
- }
440
- /**
441
- * Internal cleanup method to prevent memory leaks
442
- *
443
- * Cleans up popup windows, event listeners, and intervals.
444
- * Does not unlock verification state - that's handled by specific callers.
445
- *
446
- * @private
447
- */
448
- cleanup(options = {}) {
449
- const shouldClosePopup = options.closePopup !== false;
450
- // Close popup window unless we're intentionally keeping it open
451
- if (this.popupWindow) {
452
- if (shouldClosePopup && !this.popupWindow.closed) {
453
- this.popupWindow.close();
454
- }
455
- if (shouldClosePopup || this.popupWindow.closed) {
456
- this.popupWindow = null;
457
- }
458
- }
459
- // Remove message listener
460
- if (this.messageListener) {
461
- window.removeEventListener('message', this.messageListener);
462
- this.messageListener = null;
463
- }
464
- // Clear monitoring interval
465
- if (this.popupMonitorInterval) {
466
- clearInterval(this.popupMonitorInterval);
467
- this.popupMonitorInterval = null;
468
- }
469
- // Note: Verification unlocking is handled by specific callers
470
- }
471
- /**
472
- * Remove auto-cleanup listeners
473
- *
474
- * Removes page unload event listeners that were set up for automatic cleanup.
475
- *
476
- * @private
477
- */
478
- removeAutoCleanupListeners() {
479
- if (this.unloadListener) {
480
- window.removeEventListener('beforeunload', this.unloadListener);
481
- window.removeEventListener('pagehide', this.unloadListener);
482
- this.unloadListener = null;
483
- }
484
- }
485
- /**
486
- * Public cleanup method for manual resource management
487
- *
488
- * Completely destroys the SDK instance, cleaning up all resources and
489
- * removing all event listeners. Should be called when the SDK is no longer needed.
490
- *
491
- * @public
492
- */
493
- destroy() {
494
- // Log destruction for security monitoring
495
- logSecurityEvent('SDK_DESTROYED', {
496
- environment: this.config.environment,
497
- origin: window.location.origin,
498
- });
499
- // Clean up all resources
500
- this.cleanup();
501
- // Unlock verification
502
- this.unlockVerification();
503
- // Remove auto-cleanup listeners
504
- this.removeAutoCleanupListeners();
505
- }
506
- /**
507
- * Get Portal API URL based on environment
508
- *
509
- * Returns the appropriate portal-api URL for the current environment.
510
- *
511
- * @returns {string} Portal API URL
512
- * @private
513
- */
514
- getPortalApiUrl() {
515
- switch (this.config.environment) {
516
- case 'staging':
517
- return 'https://api.staging.safepassageapp.com';
518
- case 'production':
519
- return 'https://api.safepassageapp.com';
520
- default:
521
- return 'https://api.safepassageapp.com';
522
- }
523
- }
524
- /**
525
- * Get Engine URL based on environment
526
- *
527
- * Returns the appropriate verify-engine URL for the current environment.
528
- * In production, engine access is proxied through portal-api.
529
- *
530
- * @returns {string} Engine URL
531
- * @private
532
- */
533
- getEngineUrl() {
534
- switch (this.config.environment) {
535
- case 'staging':
536
- return 'https://engine.staging.safepassageapp.com';
537
- case 'production':
538
- // Direct access to verify-engine
539
- return 'https://engine.safepassageapp.com';
540
- default:
541
- return 'https://engine.safepassageapp.com';
542
- }
543
- }
544
- /**
545
- * Get WebSocket URL based on environment
546
- *
547
- * Returns the appropriate WebSocket URL for the current environment.
548
- * In production, WebSocket connections are proxied through portal-api.
549
- *
550
- * @returns {string} WebSocket URL
551
- * @private
552
- */
553
- getWebSocketUrl() {
554
- switch (this.config.environment) {
555
- case 'staging':
556
- return 'wss://engine.staging.safepassageapp.com/api/websocket/stream';
557
- case 'production':
558
- // Direct WebSocket connection to verify-engine
559
- return 'wss://engine.safepassageapp.com/api/websocket/stream';
560
- default:
561
- return 'wss://engine.safepassageapp.com/api/websocket/stream';
562
- }
563
- }
564
- /**
565
- * Detect if this is a public key (pk_ prefix) vs private key (sk_ prefix)
566
- *
567
- * Determines API key type based on prefix to handle different authentication flows.
568
- *
569
- * @returns {boolean} True if public key, false if private key
570
- * @private
571
- */
572
- isPublicKey() {
573
- return this.config.apiKey.startsWith('pk_');
574
- }
575
- /**
576
- * Create session internally for public keys
577
- *
578
- * Creates a verification session via the portal API for public key authentication.
579
- * Generates a UUID session ID and submits session creation request with
580
- * verification parameters.
581
- *
582
- * @param {VerificationOptions} options - Verification options
583
- * @returns {Promise<string>} Created session ID
584
- * @throws {Error} If session creation fails
585
- * @private
586
- */
587
- async createInternalSession(options) {
588
- var _a, _b;
589
- try {
590
- const portalApiUrl = this.getPortalApiUrl();
591
- const response = await fetch(`${portalApiUrl}/api/v1/sessions/create`, {
592
- method: 'POST',
593
- headers: {
594
- 'Content-Type': 'application/json',
595
- Authorization: `Bearer ${this.config.apiKey}`,
596
- },
597
- body: JSON.stringify({
598
- merchantId: this.config.apiKey, // API expects merchantId even though it uses auth header
599
- returnUrl: this.config.returnUrl,
600
- cancelUrl: this.config.cancelUrl,
601
- challengeAge: options.challengeAge,
602
- verificationMode: options.verificationMode,
603
- merchantName: document.title || window.location.hostname,
604
- externalUserId: options.externalUserId,
605
- }),
606
- });
607
- if (!response.ok) {
608
- const errorData = await response.json().catch(() => ({}));
609
- throw new Error(`Failed to create session: ${response.status} ${response.statusText}. ${errorData.message || ''}`);
610
- }
611
- const sessionData = await response.json();
612
- // SafePassage now generates the sessionId internally
613
- const sessionId = sessionData.sessionId;
614
- if (!sessionId) {
615
- throw new Error('Server did not return a sessionId');
616
- }
617
- // Capture verifyUrl from server for redirect (ensures sessionToken is present)
618
- if (sessionData.verifyUrl) {
619
- this.lastVerifyUrl = sessionData.verifyUrl;
620
- }
621
- // Capture sessionToken for state payload (ensures UI can always auth WS)
622
- if (sessionData.sessionToken) {
623
- this.lastSessionToken = sessionData.sessionToken;
624
- }
625
- // Store the handoffToken if it exists for desktop QR flow
626
- if (sessionData.handoffToken) {
627
- // Store it temporarily so it can be included in the state
628
- this.temporaryHandoffToken = sessionData.handoffToken;
629
- }
630
- // Log successful session creation
631
- logSecurityEvent('INTERNAL_SESSION_CREATED', {
632
- sessionId: sessionId.substring(0, 8) + '...',
633
- environment: this.config.environment,
634
- apiKeyType: 'public',
635
- });
636
- return sessionId;
637
- }
638
- catch (error) {
639
- const errorMessage = error instanceof Error ? error.message : String(error);
640
- logSecurityEvent('INTERNAL_SESSION_FAILED', {
641
- error: errorMessage,
642
- environment: this.config.environment,
643
- apiKeyType: 'public',
644
- });
645
- (_b = (_a = this.config).onError) === null || _b === void 0 ? void 0 : _b.call(_a, error);
646
- throw new Error(`Failed to create verification session: ${errorMessage}`);
647
- }
648
- }
649
- }
650
- // For backwards compatibility
651
- export default SafePassage;
package/dist/index.d.ts DELETED
@@ -1,21 +0,0 @@
1
- /**
2
- * SafePassage SDK - Redirect-based age verification
3
- *
4
- * @example
5
- * ```javascript
6
- * // Initialize SDK
7
- * const sp = new SafePassage({
8
- * apiKey: 'pk_xxxxx',
9
- * returnUrl: 'https://merchant.com/verified',
10
- * cancelUrl: 'https://merchant.com/cancelled'
11
- * });
12
- *
13
- * // Trigger verification
14
- * sp.verify({
15
- * sessionId: generateUUID() // Merchant-generated UUID v4
16
- * });
17
- * ```
18
- */
19
- export { SafePassage, SafePassage as default } from './core/SafePassageSDK';
20
- export type { SafePassageConfig, VerificationOptions, VerificationResult, SessionValidationResponse, } from './types';
21
- export declare const VERSION = "3.4.8";