@glideidentity/web-client-sdk 4.4.8-beta.3 → 4.4.8
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.
- package/README.md +395 -714
- package/dist/browser/web-client-sdk.min.js +1 -1
- package/dist/core/phone-auth/client.js +187 -73
- package/dist/core/phone-auth/strategies/desktop.d.ts +9 -3
- package/dist/core/phone-auth/strategies/desktop.js +47 -4
- package/dist/core/phone-auth/strategies/link.d.ts +8 -2
- package/dist/core/phone-auth/strategies/link.js +46 -10
- package/dist/core/phone-auth/types.d.ts +1 -1
- package/dist/core/phone-auth/ui/modal.d.ts +4 -0
- package/dist/core/phone-auth/ui/modal.js +17 -6
- package/dist/core/version.js +1 -1
- package/dist/esm/core/phone-auth/client.js +187 -73
- package/dist/esm/core/phone-auth/strategies/desktop.d.ts +9 -3
- package/dist/esm/core/phone-auth/strategies/desktop.js +47 -4
- package/dist/esm/core/phone-auth/strategies/link.d.ts +8 -2
- package/dist/esm/core/phone-auth/strategies/link.js +46 -10
- package/dist/esm/core/phone-auth/types.d.ts +1 -1
- package/dist/esm/core/phone-auth/ui/modal.d.ts +4 -0
- package/dist/esm/core/phone-auth/ui/modal.js +17 -6
- package/dist/esm/core/version.js +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -3
- package/package.json +1 -1
|
@@ -17,7 +17,7 @@ export interface QRCodeData {
|
|
|
17
17
|
export interface DesktopAuthOptions {
|
|
18
18
|
/** Custom polling interval in milliseconds (overrides server-provided value) */
|
|
19
19
|
pollingInterval?: number;
|
|
20
|
-
/** Maximum polling attempts before timeout (default:
|
|
20
|
+
/** Maximum polling attempts before timeout (default: 30 = 1 minute with 2s interval) */
|
|
21
21
|
maxPollingAttempts?: number;
|
|
22
22
|
/** Custom polling endpoint (overrides backend-provided or uses configured endpoint) */
|
|
23
23
|
pollingEndpoint?: string;
|
|
@@ -56,6 +56,7 @@ export declare class DesktopHandler implements StrategyHandler {
|
|
|
56
56
|
private isCancelled;
|
|
57
57
|
private onCancel?;
|
|
58
58
|
private pollingReject?;
|
|
59
|
+
private isPollingInProgress;
|
|
59
60
|
/**
|
|
60
61
|
* Maps backend HTTP status codes to client status
|
|
61
62
|
* @param httpStatus HTTP status code from backend
|
|
@@ -76,6 +77,10 @@ export declare class DesktopHandler implements StrategyHandler {
|
|
|
76
77
|
* Stop polling
|
|
77
78
|
*/
|
|
78
79
|
private stopPolling;
|
|
80
|
+
/**
|
|
81
|
+
* Check if polling is currently active
|
|
82
|
+
*/
|
|
83
|
+
isPolling(): boolean;
|
|
79
84
|
/**
|
|
80
85
|
* Format response for backend processing
|
|
81
86
|
* Desktop strategy typically returns the credential from mobile authentication
|
|
@@ -98,7 +103,7 @@ export declare class DesktopHandler implements StrategyHandler {
|
|
|
98
103
|
/**
|
|
99
104
|
* Helper function to display QR code in a modal or inline
|
|
100
105
|
*/
|
|
101
|
-
export declare function createQRCodeDisplay(qrCodeData: string, options?: {
|
|
106
|
+
export declare function createQRCodeDisplay(qrCodeData: string | QRCodeData, options?: {
|
|
102
107
|
container?: HTMLElement;
|
|
103
108
|
size?: number;
|
|
104
109
|
title?: string;
|
|
@@ -106,8 +111,9 @@ export declare function createQRCodeDisplay(qrCodeData: string, options?: {
|
|
|
106
111
|
}): HTMLElement;
|
|
107
112
|
/**
|
|
108
113
|
* Helper function to create a modal for QR code display
|
|
114
|
+
* Supports both string QR codes and QRCodeData objects for dual-platform support
|
|
109
115
|
*/
|
|
110
|
-
export declare function showQRCodeModal(qrCodeData: string, options?: {
|
|
116
|
+
export declare function showQRCodeModal(qrCodeData: string | QRCodeData, options?: {
|
|
111
117
|
title?: string;
|
|
112
118
|
description?: string;
|
|
113
119
|
onClose?: () => void;
|
|
@@ -16,6 +16,7 @@ export class DesktopHandler {
|
|
|
16
16
|
constructor() {
|
|
17
17
|
this.pollingAttempts = 0;
|
|
18
18
|
this.isCancelled = false;
|
|
19
|
+
this.isPollingInProgress = false;
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
21
22
|
* Maps backend HTTP status codes to client status
|
|
@@ -58,8 +59,8 @@ export class DesktopHandler {
|
|
|
58
59
|
const innerData = desktopData.data;
|
|
59
60
|
// Try to extract from inner data
|
|
60
61
|
// Support both single QR (qr_code_image) and dual-platform QR (ios/android)
|
|
61
|
-
if (innerData.ios_qr_image
|
|
62
|
-
// Dual-platform QR format
|
|
62
|
+
if (innerData.ios_qr_image && innerData.android_qr_image) {
|
|
63
|
+
// Dual-platform QR format - both must be present
|
|
63
64
|
qrCode = {
|
|
64
65
|
iosQRCode: innerData.ios_qr_image,
|
|
65
66
|
androidQRCode: innerData.android_qr_image,
|
|
@@ -67,6 +68,10 @@ export class DesktopHandler {
|
|
|
67
68
|
androidUrl: innerData.android_url
|
|
68
69
|
};
|
|
69
70
|
}
|
|
71
|
+
else if (innerData.ios_qr_image || innerData.android_qr_image) {
|
|
72
|
+
// Only one platform QR - use as single QR format
|
|
73
|
+
qrCode = innerData.ios_qr_image || innerData.android_qr_image;
|
|
74
|
+
}
|
|
70
75
|
else {
|
|
71
76
|
// Single QR format (legacy)
|
|
72
77
|
qrCode = innerData.qr_code_image || innerData.qr_code;
|
|
@@ -117,7 +122,7 @@ export class DesktopHandler {
|
|
|
117
122
|
console.log('[Desktop QR] Selected endpoint:', finalPollingEndpoint, 'from source:', endpointSource);
|
|
118
123
|
// Start polling for authentication status
|
|
119
124
|
const finalPollingInterval = (options === null || options === void 0 ? void 0 : options.pollingInterval) || pollingInterval || 2000;
|
|
120
|
-
const maxAttempts = (options === null || options === void 0 ? void 0 : options.maxPollingAttempts) ||
|
|
125
|
+
const maxAttempts = (options === null || options === void 0 ? void 0 : options.maxPollingAttempts) || 30; // Default to 1 minute
|
|
121
126
|
console.log(`[Desktop QR] Starting polling - endpoint source: ${endpointSource}, interval: ${finalPollingInterval}ms, max attempts: ${maxAttempts}`);
|
|
122
127
|
return this.startPolling(finalPollingEndpoint || '', // Pass empty string if undefined, will use fallback
|
|
123
128
|
sessionId, finalPollingInterval, maxAttempts, expiresIn || 300, // Default 5 minutes expiry
|
|
@@ -136,7 +141,12 @@ export class DesktopHandler {
|
|
|
136
141
|
// Store the reject function so we can call it from cancel()
|
|
137
142
|
this.pollingReject = reject;
|
|
138
143
|
const poll = () => __awaiter(this, void 0, void 0, function* () {
|
|
144
|
+
// Skip if another poll is already in progress
|
|
145
|
+
if (this.isPollingInProgress) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
139
148
|
try {
|
|
149
|
+
this.isPollingInProgress = true;
|
|
140
150
|
// Check if cancelled
|
|
141
151
|
if (this.isCancelled) {
|
|
142
152
|
this.stopPolling();
|
|
@@ -360,6 +370,10 @@ export class DesktopHandler {
|
|
|
360
370
|
});
|
|
361
371
|
}
|
|
362
372
|
}
|
|
373
|
+
finally {
|
|
374
|
+
// Always clear the polling flag when done
|
|
375
|
+
this.isPollingInProgress = false;
|
|
376
|
+
}
|
|
363
377
|
});
|
|
364
378
|
// Start initial poll
|
|
365
379
|
poll();
|
|
@@ -378,8 +392,15 @@ export class DesktopHandler {
|
|
|
378
392
|
this.pollingIntervalId = undefined;
|
|
379
393
|
}
|
|
380
394
|
this.pollingAttempts = 0;
|
|
395
|
+
this.isPollingInProgress = false;
|
|
381
396
|
// Don't clear pollingReject here - it's needed by cancel()
|
|
382
397
|
}
|
|
398
|
+
/**
|
|
399
|
+
* Check if polling is currently active
|
|
400
|
+
*/
|
|
401
|
+
isPolling() {
|
|
402
|
+
return this.pollingIntervalId !== undefined;
|
|
403
|
+
}
|
|
383
404
|
/**
|
|
384
405
|
* Format response for backend processing
|
|
385
406
|
* Desktop strategy typically returns the credential from mobile authentication
|
|
@@ -437,9 +458,30 @@ export class DesktopHandler {
|
|
|
437
458
|
export function createQRCodeDisplay(qrCodeData, options) {
|
|
438
459
|
const container = (options === null || options === void 0 ? void 0 : options.container) || document.createElement('div');
|
|
439
460
|
container.className = 'phone-auth-qr-container';
|
|
461
|
+
// Determine QR code to display
|
|
462
|
+
let qrCodeSrc;
|
|
463
|
+
if (typeof qrCodeData === 'string') {
|
|
464
|
+
// Simple string QR code
|
|
465
|
+
qrCodeSrc = qrCodeData;
|
|
466
|
+
}
|
|
467
|
+
else if (qrCodeData && typeof qrCodeData === 'object') {
|
|
468
|
+
// QRCodeData object - prefer iOS QR if available
|
|
469
|
+
if (qrCodeData.iosQRCode) {
|
|
470
|
+
qrCodeSrc = qrCodeData.iosQRCode;
|
|
471
|
+
}
|
|
472
|
+
else if (qrCodeData.androidQRCode) {
|
|
473
|
+
qrCodeSrc = qrCodeData.androidQRCode;
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
throw new Error('Invalid QRCodeData: missing QR code images');
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
throw new Error('Invalid qrCodeData: must be string or QRCodeData object');
|
|
481
|
+
}
|
|
440
482
|
// Create QR code image
|
|
441
483
|
const img = document.createElement('img');
|
|
442
|
-
img.src =
|
|
484
|
+
img.src = qrCodeSrc;
|
|
443
485
|
img.alt = 'QR Code for authentication';
|
|
444
486
|
img.style.width = `${(options === null || options === void 0 ? void 0 : options.size) || 256}px`;
|
|
445
487
|
img.style.height = `${(options === null || options === void 0 ? void 0 : options.size) || 256}px`;
|
|
@@ -467,6 +509,7 @@ export function createQRCodeDisplay(qrCodeData, options) {
|
|
|
467
509
|
}
|
|
468
510
|
/**
|
|
469
511
|
* Helper function to create a modal for QR code display
|
|
512
|
+
* Supports both string QR codes and QRCodeData objects for dual-platform support
|
|
470
513
|
*/
|
|
471
514
|
export function showQRCodeModal(qrCodeData, options) {
|
|
472
515
|
// Create modal overlay
|
|
@@ -8,7 +8,7 @@ import type { PrepareResponse } from '../types';
|
|
|
8
8
|
export interface LinkAuthOptions {
|
|
9
9
|
/** Fixed polling interval in milliseconds (default: 2000) */
|
|
10
10
|
pollingInterval?: number;
|
|
11
|
-
/** Maximum polling attempts before timeout (default:
|
|
11
|
+
/** Maximum polling attempts before timeout (default: 30 = 1 minute with 2s interval) */
|
|
12
12
|
maxPollingAttempts?: number;
|
|
13
13
|
/** Custom polling endpoint (overrides backend-provided or configured endpoint) */
|
|
14
14
|
pollingEndpoint?: string;
|
|
@@ -41,9 +41,11 @@ export interface LinkAuthResult {
|
|
|
41
41
|
}
|
|
42
42
|
export declare class LinkHandler implements StrategyHandler {
|
|
43
43
|
private pollingInterval?;
|
|
44
|
-
private
|
|
44
|
+
private isPollingActive;
|
|
45
45
|
private isCancelled;
|
|
46
46
|
private onCancel?;
|
|
47
|
+
private pollingReject?;
|
|
48
|
+
private isPollingInProgress;
|
|
47
49
|
/**
|
|
48
50
|
* Invoke link-based authentication
|
|
49
51
|
* Opens authentication app while keeping user on current page
|
|
@@ -74,6 +76,10 @@ export declare class LinkHandler implements StrategyHandler {
|
|
|
74
76
|
* Clean up resources (stop polling if active)
|
|
75
77
|
*/
|
|
76
78
|
cleanup(): void;
|
|
79
|
+
/**
|
|
80
|
+
* Check if polling is currently active
|
|
81
|
+
*/
|
|
82
|
+
isPolling(): boolean;
|
|
77
83
|
/**
|
|
78
84
|
* Cancel the ongoing authentication
|
|
79
85
|
*/
|
|
@@ -14,8 +14,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
14
14
|
};
|
|
15
15
|
export class LinkHandler {
|
|
16
16
|
constructor() {
|
|
17
|
-
this.
|
|
17
|
+
this.isPollingActive = false;
|
|
18
18
|
this.isCancelled = false;
|
|
19
|
+
this.isPollingInProgress = false;
|
|
19
20
|
}
|
|
20
21
|
/**
|
|
21
22
|
* Invoke link-based authentication
|
|
@@ -23,7 +24,6 @@ export class LinkHandler {
|
|
|
23
24
|
*/
|
|
24
25
|
invoke(data, options) {
|
|
25
26
|
return __awaiter(this, void 0, void 0, function* () {
|
|
26
|
-
console.log('[Link Auth] 🔗 SDK Version: 4.4.8-beta.2 (with enhanced error logging)');
|
|
27
27
|
console.log('[Link Auth] 🔗 invoke() called with data:', JSON.stringify(data, null, 2));
|
|
28
28
|
console.log('[Link Auth] Options:', options ? JSON.stringify({
|
|
29
29
|
pollingInterval: options.pollingInterval,
|
|
@@ -67,7 +67,7 @@ export class LinkHandler {
|
|
|
67
67
|
startPolling(sessionKey, linkData, options) {
|
|
68
68
|
return __awaiter(this, void 0, void 0, function* () {
|
|
69
69
|
const interval = (options === null || options === void 0 ? void 0 : options.pollingInterval) || 2000; // Fixed 2 second interval
|
|
70
|
-
const maxAttempts = (options === null || options === void 0 ? void 0 : options.maxPollingAttempts) ||
|
|
70
|
+
const maxAttempts = (options === null || options === void 0 ? void 0 : options.maxPollingAttempts) || 30; // 1 minute with 2s interval
|
|
71
71
|
let attempts = 0;
|
|
72
72
|
console.log('[Link Auth] 🚀 Starting polling:', {
|
|
73
73
|
sessionKey,
|
|
@@ -76,27 +76,37 @@ export class LinkHandler {
|
|
|
76
76
|
linkDataAvailable: !!linkData
|
|
77
77
|
});
|
|
78
78
|
return new Promise((resolve, reject) => {
|
|
79
|
-
this.
|
|
79
|
+
this.isPollingActive = true;
|
|
80
|
+
this.pollingReject = reject; // Store reject function for cancel()
|
|
80
81
|
const poll = () => __awaiter(this, void 0, void 0, function* () {
|
|
81
|
-
if (!this.
|
|
82
|
+
if (!this.isPollingActive) {
|
|
82
83
|
return; // Polling was stopped
|
|
83
84
|
}
|
|
85
|
+
// Skip if another poll is already in progress
|
|
86
|
+
if (this.isPollingInProgress) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
84
89
|
let statusUrl = ''; // Declare at function scope for catch block access
|
|
85
90
|
try {
|
|
86
|
-
|
|
87
|
-
// Check max attempts
|
|
91
|
+
this.isPollingInProgress = true;
|
|
92
|
+
// Check max attempts before making the request
|
|
88
93
|
if (attempts >= maxAttempts) {
|
|
89
94
|
this.stopPolling();
|
|
90
95
|
if (options === null || options === void 0 ? void 0 : options.onTimeout) {
|
|
91
96
|
options.onTimeout();
|
|
92
97
|
}
|
|
98
|
+
// Calculate actual timeout duration
|
|
99
|
+
const timeoutSeconds = Math.round((maxAttempts * interval) / 1000);
|
|
100
|
+
const timeoutMessage = timeoutSeconds >= 60
|
|
101
|
+
? `${Math.floor(timeoutSeconds / 60)} minute${Math.floor(timeoutSeconds / 60) > 1 ? 's' : ''}`
|
|
102
|
+
: `${timeoutSeconds} seconds`;
|
|
93
103
|
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
94
104
|
options.onStatusUpdate({
|
|
95
105
|
status: 'expired',
|
|
96
|
-
message:
|
|
106
|
+
message: `Authentication timeout after ${timeoutMessage}`
|
|
97
107
|
});
|
|
98
108
|
}
|
|
99
|
-
reject(new Error(
|
|
109
|
+
reject(new Error(`Authentication timeout after ${timeoutMessage}`));
|
|
100
110
|
return;
|
|
101
111
|
}
|
|
102
112
|
// Build public status endpoint URL
|
|
@@ -175,6 +185,7 @@ export class LinkHandler {
|
|
|
175
185
|
});
|
|
176
186
|
}
|
|
177
187
|
// Return the authentication result
|
|
188
|
+
this.pollingReject = undefined; // Clear reject function on success
|
|
178
189
|
resolve({
|
|
179
190
|
authenticated: true,
|
|
180
191
|
credential: result.credential || sessionKey,
|
|
@@ -190,6 +201,7 @@ export class LinkHandler {
|
|
|
190
201
|
else if (result.status === 'pending') {
|
|
191
202
|
// Continue polling
|
|
192
203
|
console.log('[Link Auth] Status still pending, continuing to poll...');
|
|
204
|
+
attempts++; // Increment attempts after successful poll
|
|
193
205
|
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
194
206
|
options.onStatusUpdate({
|
|
195
207
|
status: 'pending',
|
|
@@ -200,6 +212,7 @@ export class LinkHandler {
|
|
|
200
212
|
else {
|
|
201
213
|
// Unexpected status value
|
|
202
214
|
console.log('[Link Auth] ⚠️ Unexpected status value:', result.status, 'Full result:', JSON.stringify(result, null, 2));
|
|
215
|
+
attempts++; // Increment for unexpected status too
|
|
203
216
|
}
|
|
204
217
|
}
|
|
205
218
|
else if (response.status === 410) {
|
|
@@ -260,6 +273,7 @@ export class LinkHandler {
|
|
|
260
273
|
else {
|
|
261
274
|
// Unexpected status - continue polling
|
|
262
275
|
console.log('[Link Auth] ⚠️ Unexpected HTTP status:', response.status, 'continuing to poll...');
|
|
276
|
+
attempts++; // Increment for unexpected HTTP status
|
|
263
277
|
try {
|
|
264
278
|
const body = yield response.text();
|
|
265
279
|
console.log('[Link Auth] Response body:', body);
|
|
@@ -272,6 +286,7 @@ export class LinkHandler {
|
|
|
272
286
|
catch (error) {
|
|
273
287
|
// Network or other error - continue polling
|
|
274
288
|
console.error('[Link Auth] 🔴 Polling error:', error.message || error);
|
|
289
|
+
attempts++; // Increment for error case
|
|
275
290
|
console.error('[Link Auth] Error details:', {
|
|
276
291
|
name: error.name,
|
|
277
292
|
message: error.message,
|
|
@@ -292,6 +307,10 @@ export class LinkHandler {
|
|
|
292
307
|
});
|
|
293
308
|
}
|
|
294
309
|
}
|
|
310
|
+
finally {
|
|
311
|
+
// Always clear the polling flag when done
|
|
312
|
+
this.isPollingInProgress = false;
|
|
313
|
+
}
|
|
295
314
|
});
|
|
296
315
|
// Start initial poll immediately
|
|
297
316
|
poll();
|
|
@@ -305,7 +324,8 @@ export class LinkHandler {
|
|
|
305
324
|
*/
|
|
306
325
|
stopPolling() {
|
|
307
326
|
console.log('[Link Auth] 🏁 Stopping polling');
|
|
308
|
-
this.
|
|
327
|
+
this.isPollingActive = false;
|
|
328
|
+
this.isPollingInProgress = false;
|
|
309
329
|
if (this.pollingInterval) {
|
|
310
330
|
clearInterval(this.pollingInterval);
|
|
311
331
|
this.pollingInterval = undefined;
|
|
@@ -340,14 +360,30 @@ export class LinkHandler {
|
|
|
340
360
|
this.stopPolling();
|
|
341
361
|
this.isCancelled = false;
|
|
342
362
|
this.onCancel = undefined;
|
|
363
|
+
this.pollingReject = undefined;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Check if polling is currently active
|
|
367
|
+
*/
|
|
368
|
+
isPolling() {
|
|
369
|
+
return this.pollingInterval !== undefined;
|
|
343
370
|
}
|
|
344
371
|
/**
|
|
345
372
|
* Cancel the ongoing authentication
|
|
346
373
|
*/
|
|
347
374
|
cancel() {
|
|
348
375
|
var _a;
|
|
376
|
+
console.log('[Link Auth] Cancelling authentication');
|
|
349
377
|
this.isCancelled = true;
|
|
350
378
|
this.stopPolling();
|
|
351
379
|
(_a = this.onCancel) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
380
|
+
// Immediately reject the polling promise
|
|
381
|
+
if (this.pollingReject) {
|
|
382
|
+
this.pollingReject({
|
|
383
|
+
code: 'USER_DENIED',
|
|
384
|
+
message: 'Authentication cancelled by user'
|
|
385
|
+
});
|
|
386
|
+
this.pollingReject = undefined;
|
|
387
|
+
}
|
|
352
388
|
}
|
|
353
389
|
}
|
|
@@ -72,7 +72,7 @@ export interface AuthConfig extends PhoneAuthCallbacks {
|
|
|
72
72
|
pollingInterval?: number;
|
|
73
73
|
/**
|
|
74
74
|
* Maximum polling attempts before timeout
|
|
75
|
-
* @default
|
|
75
|
+
* @default 30 (1 minute with 2s interval)
|
|
76
76
|
*/
|
|
77
77
|
maxPollingAttempts?: number;
|
|
78
78
|
/**
|
|
@@ -26,6 +26,10 @@ export declare class AuthModal {
|
|
|
26
26
|
private closeCallback?;
|
|
27
27
|
constructor(options?: InvokeOptions['modalOptions'], callbacks?: InvokeOptions['callbacks']);
|
|
28
28
|
private handleEscapeKey;
|
|
29
|
+
/**
|
|
30
|
+
* Escape HTML to prevent XSS attacks
|
|
31
|
+
*/
|
|
32
|
+
private escapeHtml;
|
|
29
33
|
/**
|
|
30
34
|
* Shows the modal with a QR code for desktop authentication
|
|
31
35
|
* Supports both single QR code (legacy) and dual-platform QR codes (iOS + Android)
|
|
@@ -44,6 +44,17 @@ export class AuthModal {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Escape HTML to prevent XSS attacks
|
|
49
|
+
*/
|
|
50
|
+
escapeHtml(unsafe) {
|
|
51
|
+
return unsafe
|
|
52
|
+
.replace(/&/g, "&")
|
|
53
|
+
.replace(/</g, "<")
|
|
54
|
+
.replace(/>/g, ">")
|
|
55
|
+
.replace(/"/g, """)
|
|
56
|
+
.replace(/'/g, "'");
|
|
57
|
+
}
|
|
47
58
|
/**
|
|
48
59
|
* Shows the modal with a QR code for desktop authentication
|
|
49
60
|
* Supports both single QR code (legacy) and dual-platform QR codes (iOS + Android)
|
|
@@ -72,7 +83,7 @@ export class AuthModal {
|
|
|
72
83
|
// Only iOS QR code available - show single QR
|
|
73
84
|
this.createModal(`
|
|
74
85
|
<div class="glide-auth-qr-container">
|
|
75
|
-
<img src="${qrCodeData.iosQRCode}" alt="QR Code" class="glide-auth-qr-code" />
|
|
86
|
+
<img src="${this.escapeHtml(qrCodeData.iosQRCode)}" alt="QR Code" class="glide-auth-qr-code" />
|
|
76
87
|
<p class="glide-auth-status">Scan with your iPhone to authenticate</p>
|
|
77
88
|
</div>
|
|
78
89
|
`);
|
|
@@ -83,8 +94,8 @@ export class AuthModal {
|
|
|
83
94
|
// Legacy single QR code
|
|
84
95
|
this.createModal(`
|
|
85
96
|
<div class="glide-auth-qr-container">
|
|
86
|
-
<img src="${qrCodeData}" alt="QR Code" class="glide-auth-qr-code" />
|
|
87
|
-
<p class="glide-auth-status">${statusMessage}</p>
|
|
97
|
+
<img src="${this.escapeHtml(qrCodeData)}" alt="QR Code" class="glide-auth-qr-code" />
|
|
98
|
+
<p class="glide-auth-status">${this.escapeHtml(statusMessage)}</p>
|
|
88
99
|
</div>
|
|
89
100
|
`);
|
|
90
101
|
}
|
|
@@ -115,11 +126,11 @@ export class AuthModal {
|
|
|
115
126
|
<!-- QR Code Image -->
|
|
116
127
|
<img
|
|
117
128
|
id="glide-qr-code-img"
|
|
118
|
-
src="${qrCodeData.iosQRCode}"
|
|
129
|
+
src="${this.escapeHtml(qrCodeData.iosQRCode)}"
|
|
119
130
|
alt="QR Code"
|
|
120
131
|
class="glide-auth-qr-code"
|
|
121
|
-
data-ios="${qrCodeData.iosQRCode}"
|
|
122
|
-
data-android="${qrCodeData.androidQRCode}"
|
|
132
|
+
data-ios="${this.escapeHtml(qrCodeData.iosQRCode)}"
|
|
133
|
+
data-android="${this.escapeHtml(qrCodeData.androidQRCode || '')}"
|
|
123
134
|
/>
|
|
124
135
|
|
|
125
136
|
<!-- Status Message -->
|
package/dist/esm/core/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// SDK version - injected at build time
|
|
2
|
-
export const SDK_VERSION = '4.4.8
|
|
2
|
+
export const SDK_VERSION = '4.4.8';
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isEr
|
|
|
4
4
|
export { isExtendedResponse, isCredential, isAuthCredential, isLinkStrategy, isTS43Strategy, isDesktopStrategy, getStrategy, hasPollingControls, hasTrigger, isHeadlessResult, requiresPolling, requiresUserAction } from './core/phone-auth';
|
|
5
5
|
export type { PhoneAuthCallbacks, PLMN, SessionInfo, InvokeOptions, ExecutionMode, AuthCredential, AnyExtendedResponse, DesktopExtendedResponse, LinkExtendedResponse, TS43ExtendedResponse, PrepareRequest, PrepareResponse, GetPhoneNumberRequest, GetPhoneNumberResponse, VerifyPhoneNumberRequest, VerifyPhoneNumberResponse, SecureCredentialRequest, SecureCredentialResponse, DigitalCredential, TS43Data, LinkData, DesktopData, ClientInfo, ConsentData, BrowserErrorType, BrowserErrorCodeType, BrowserNameType } from './core/phone-auth/types';
|
|
6
6
|
export { USE_CASE as UseCase, AUTHENTICATION_STRATEGY as AuthenticationStrategy, BrowserError, BrowserErrorCode, BrowserName } from './core/phone-auth/types';
|
|
7
|
-
export { DesktopHandler
|
|
7
|
+
export { DesktopHandler } from './core/phone-auth/strategies/desktop';
|
|
8
8
|
export type { DesktopAuthOptions, DesktopAuthResult, PollingStatus, QRCodeData } from './core/phone-auth/strategies/desktop';
|
|
9
9
|
export { useClient, usePhoneAuth } from './adapters/react';
|
|
10
10
|
export { useClient as useVueClient, usePhoneAuth as useVuePhoneAuth } from './adapters/vue';
|
package/dist/esm/index.js
CHANGED
|
@@ -9,7 +9,7 @@ isHeadlessResult, requiresPolling, requiresUserAction } from './core/phone-auth'
|
|
|
9
9
|
// Export constants for use case and strategy
|
|
10
10
|
export { USE_CASE as UseCase, AUTHENTICATION_STRATEGY as AuthenticationStrategy, BrowserError, BrowserErrorCode, BrowserName } from './core/phone-auth/types';
|
|
11
11
|
// Desktop Strategy Exports
|
|
12
|
-
export { DesktopHandler
|
|
12
|
+
export { DesktopHandler } from './core/phone-auth/strategies/desktop';
|
|
13
13
|
// Adapters
|
|
14
14
|
export { useClient, usePhoneAuth } from './adapters/react';
|
|
15
15
|
export { useClient as useVueClient, usePhoneAuth as useVuePhoneAuth } from './adapters/vue';
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ export { PhoneAuthErrorCode, isPhoneAuthError, isUserError, getUserMessage, isEr
|
|
|
4
4
|
export { isExtendedResponse, isCredential, isAuthCredential, isLinkStrategy, isTS43Strategy, isDesktopStrategy, getStrategy, hasPollingControls, hasTrigger, isHeadlessResult, requiresPolling, requiresUserAction } from './core/phone-auth';
|
|
5
5
|
export type { PhoneAuthCallbacks, PLMN, SessionInfo, InvokeOptions, ExecutionMode, AuthCredential, AnyExtendedResponse, DesktopExtendedResponse, LinkExtendedResponse, TS43ExtendedResponse, PrepareRequest, PrepareResponse, GetPhoneNumberRequest, GetPhoneNumberResponse, VerifyPhoneNumberRequest, VerifyPhoneNumberResponse, SecureCredentialRequest, SecureCredentialResponse, DigitalCredential, TS43Data, LinkData, DesktopData, ClientInfo, ConsentData, BrowserErrorType, BrowserErrorCodeType, BrowserNameType } from './core/phone-auth/types';
|
|
6
6
|
export { USE_CASE as UseCase, AUTHENTICATION_STRATEGY as AuthenticationStrategy, BrowserError, BrowserErrorCode, BrowserName } from './core/phone-auth/types';
|
|
7
|
-
export { DesktopHandler
|
|
7
|
+
export { DesktopHandler } from './core/phone-auth/strategies/desktop';
|
|
8
8
|
export type { DesktopAuthOptions, DesktopAuthResult, PollingStatus, QRCodeData } from './core/phone-auth/strategies/desktop';
|
|
9
9
|
export { useClient, usePhoneAuth } from './adapters/react';
|
|
10
10
|
export { useClient as useVueClient, usePhoneAuth as useVuePhoneAuth } from './adapters/vue';
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.PhoneAuthManager = exports.ClientManager = exports.PhoneAuthService = exports.ClientService = exports.useVuePhoneAuth = exports.useVueClient = exports.usePhoneAuth = exports.useClient = exports.
|
|
3
|
+
exports.PhoneAuthManager = exports.ClientManager = exports.PhoneAuthService = exports.ClientService = exports.useVuePhoneAuth = exports.useVueClient = exports.usePhoneAuth = exports.useClient = exports.DesktopHandler = exports.BrowserName = exports.BrowserErrorCode = exports.BrowserError = exports.AuthenticationStrategy = exports.UseCase = exports.requiresUserAction = exports.requiresPolling = exports.isHeadlessResult = exports.hasTrigger = exports.hasPollingControls = exports.getStrategy = exports.isDesktopStrategy = exports.isTS43Strategy = exports.isLinkStrategy = exports.isAuthCredential = exports.isCredential = exports.isExtendedResponse = exports.createErrorBreadcrumb = exports.serializeError = exports.isRetryableError = exports.getRetryDelay = exports.isErrorCode = exports.getUserMessage = exports.isUserError = exports.isPhoneAuthError = exports.PhoneAuthErrorCode = exports.PhoneAuthClient = void 0;
|
|
4
4
|
// Phone Authentication
|
|
5
5
|
var phone_auth_1 = require("./core/phone-auth");
|
|
6
6
|
Object.defineProperty(exports, "PhoneAuthClient", { enumerable: true, get: function () { return phone_auth_1.PhoneAuthClient; } });
|
|
@@ -40,8 +40,6 @@ Object.defineProperty(exports, "BrowserName", { enumerable: true, get: function
|
|
|
40
40
|
// Desktop Strategy Exports
|
|
41
41
|
var desktop_1 = require("./core/phone-auth/strategies/desktop");
|
|
42
42
|
Object.defineProperty(exports, "DesktopHandler", { enumerable: true, get: function () { return desktop_1.DesktopHandler; } });
|
|
43
|
-
Object.defineProperty(exports, "showQRCodeModal", { enumerable: true, get: function () { return desktop_1.showQRCodeModal; } });
|
|
44
|
-
Object.defineProperty(exports, "createQRCodeDisplay", { enumerable: true, get: function () { return desktop_1.createQRCodeDisplay; } });
|
|
45
43
|
// Adapters
|
|
46
44
|
var react_1 = require("./adapters/react");
|
|
47
45
|
Object.defineProperty(exports, "useClient", { enumerable: true, get: function () { return react_1.useClient; } });
|