@glideidentity/web-client-sdk 5.1.3 → 6.0.0-beta.2
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 +337 -526
- package/dist/browser/web-client-sdk.min.js +1 -1
- package/dist/cjs/adapters/index.js +15 -0
- package/dist/cjs/adapters/react.js +192 -0
- package/dist/cjs/adapters/vanilla.js +38 -0
- package/dist/cjs/adapters/vue.js +187 -0
- package/dist/cjs/browser.js +58 -0
- package/dist/cjs/client/http.js +159 -0
- package/dist/cjs/client/index.js +19 -0
- package/dist/cjs/client/logger.js +135 -0
- package/dist/cjs/client/phone-auth-client.js +428 -0
- package/dist/cjs/client/strategies/polling.js +177 -0
- package/dist/cjs/core/errors.js +204 -0
- package/dist/cjs/core/index.js +83 -0
- package/dist/cjs/core/type-guards.js +196 -0
- package/dist/cjs/core/types.js +25 -0
- package/dist/{core/phone-auth/validation-utils.js → cjs/core/validators.js} +70 -23
- package/dist/cjs/index.js +81 -0
- package/dist/cjs/ui/index.js +11 -0
- package/dist/{core/phone-auth → cjs}/ui/mobile-debug-console.js +149 -78
- package/dist/cjs/ui/modal.js +1122 -0
- package/dist/esm/adapters/index.js +11 -0
- package/dist/esm/adapters/react.js +182 -0
- package/dist/esm/adapters/vanilla.js +29 -0
- package/dist/esm/adapters/vue.js +177 -0
- package/dist/esm/browser.js +30 -11
- package/dist/esm/client/http.js +156 -0
- package/dist/esm/client/index.js +11 -0
- package/dist/esm/client/logger.js +131 -0
- package/dist/esm/client/phone-auth-client.js +424 -0
- package/dist/esm/client/strategies/polling.js +174 -0
- package/dist/esm/core/errors.js +193 -0
- package/dist/esm/core/index.js +60 -0
- package/dist/esm/core/type-guards.js +181 -0
- package/dist/esm/core/types.js +22 -1
- package/dist/esm/core/{phone-auth/validation-utils.js → validators.js} +66 -21
- package/dist/esm/index.js +45 -17
- package/dist/esm/ui/index.js +5 -0
- package/dist/esm/{core/phone-auth/ui → ui}/mobile-debug-console.js +149 -78
- package/dist/esm/ui/modal.js +1117 -0
- package/dist/types/adapters/index.d.ts +10 -0
- package/dist/types/adapters/index.d.ts.map +1 -0
- package/dist/types/adapters/react.d.ts +70 -0
- package/dist/types/adapters/react.d.ts.map +1 -0
- package/dist/types/adapters/vanilla.d.ts +29 -0
- package/dist/types/adapters/vanilla.d.ts.map +1 -0
- package/dist/types/adapters/vue.d.ts +71 -0
- package/dist/types/adapters/vue.d.ts.map +1 -0
- package/dist/types/browser.d.ts +27 -0
- package/dist/types/browser.d.ts.map +1 -0
- package/dist/types/client/http.d.ts +41 -0
- package/dist/types/client/http.d.ts.map +1 -0
- package/dist/types/client/index.d.ts +10 -0
- package/dist/types/client/index.d.ts.map +1 -0
- package/dist/types/client/logger.d.ts +36 -0
- package/dist/types/client/logger.d.ts.map +1 -0
- package/dist/types/client/phone-auth-client.d.ts +91 -0
- package/dist/types/client/phone-auth-client.d.ts.map +1 -0
- package/dist/types/client/strategies/polling.d.ts +36 -0
- package/dist/types/client/strategies/polling.d.ts.map +1 -0
- package/dist/types/core/errors.d.ts +71 -0
- package/dist/types/core/errors.d.ts.map +1 -0
- package/dist/types/core/index.d.ts +38 -0
- package/dist/types/core/index.d.ts.map +1 -0
- package/dist/types/core/type-guards.d.ts +118 -0
- package/dist/types/core/type-guards.d.ts.map +1 -0
- package/dist/types/core/types.d.ts +535 -0
- package/dist/types/core/types.d.ts.map +1 -0
- package/dist/types/core/validators.d.ts +63 -0
- package/dist/types/core/validators.d.ts.map +1 -0
- package/dist/types/index.d.ts +40 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/ui/index.d.ts +6 -0
- package/dist/types/ui/index.d.ts.map +1 -0
- package/dist/{esm/core/phone-auth → types}/ui/mobile-debug-console.d.ts +1 -0
- package/dist/types/ui/mobile-debug-console.d.ts.map +1 -0
- package/dist/types/ui/modal.d.ts +87 -0
- package/dist/types/ui/modal.d.ts.map +1 -0
- package/package.json +48 -34
- package/dist/adapters/angular/client.service.d.ts +0 -7
- package/dist/adapters/angular/client.service.js +0 -30
- package/dist/adapters/angular/index.d.ts +0 -3
- package/dist/adapters/angular/index.js +0 -18
- package/dist/adapters/angular/phone-auth.service.d.ts +0 -38
- package/dist/adapters/angular/phone-auth.service.js +0 -130
- package/dist/adapters/react/index.d.ts +0 -9
- package/dist/adapters/react/index.js +0 -28
- package/dist/adapters/react/useClient.d.ts +0 -26
- package/dist/adapters/react/useClient.js +0 -121
- package/dist/adapters/react/usePhoneAuth.d.ts +0 -23
- package/dist/adapters/react/usePhoneAuth.js +0 -95
- package/dist/adapters/vanilla/client.d.ts +0 -8
- package/dist/adapters/vanilla/client.js +0 -33
- package/dist/adapters/vanilla/index.d.ts +0 -3
- package/dist/adapters/vanilla/index.js +0 -18
- package/dist/adapters/vanilla/phone-auth.d.ts +0 -46
- package/dist/adapters/vanilla/phone-auth.js +0 -138
- package/dist/adapters/vue/index.d.ts +0 -10
- package/dist/adapters/vue/index.js +0 -36
- package/dist/adapters/vue/useClient.d.ts +0 -115
- package/dist/adapters/vue/useClient.js +0 -131
- package/dist/adapters/vue/usePhoneAuth.d.ts +0 -94
- package/dist/adapters/vue/usePhoneAuth.js +0 -103
- package/dist/browser.d.ts +0 -7
- package/dist/browser.js +0 -31
- package/dist/core/client.d.ts +0 -22
- package/dist/core/client.js +0 -77
- package/dist/core/logger.d.ts +0 -130
- package/dist/core/logger.js +0 -370
- package/dist/core/phone-auth/api-types.d.ts +0 -593
- package/dist/core/phone-auth/api-types.js +0 -215
- package/dist/core/phone-auth/client.d.ts +0 -189
- package/dist/core/phone-auth/client.js +0 -1441
- package/dist/core/phone-auth/error-utils.d.ts +0 -110
- package/dist/core/phone-auth/error-utils.js +0 -350
- package/dist/core/phone-auth/index.d.ts +0 -7
- package/dist/core/phone-auth/index.js +0 -50
- package/dist/core/phone-auth/status-types.d.ts +0 -107
- package/dist/core/phone-auth/status-types.js +0 -31
- package/dist/core/phone-auth/strategies/desktop.d.ts +0 -122
- package/dist/core/phone-auth/strategies/desktop.js +0 -596
- package/dist/core/phone-auth/strategies/index.d.ts +0 -11
- package/dist/core/phone-auth/strategies/index.js +0 -15
- package/dist/core/phone-auth/strategies/link.d.ts +0 -89
- package/dist/core/phone-auth/strategies/link.js +0 -384
- package/dist/core/phone-auth/strategies/ts43.d.ts +0 -32
- package/dist/core/phone-auth/strategies/ts43.js +0 -161
- package/dist/core/phone-auth/strategies/types.d.ts +0 -18
- package/dist/core/phone-auth/strategies/types.js +0 -6
- package/dist/core/phone-auth/type-guards.d.ts +0 -143
- package/dist/core/phone-auth/type-guards.js +0 -198
- package/dist/core/phone-auth/types.d.ts +0 -237
- package/dist/core/phone-auth/types.js +0 -93
- package/dist/core/phone-auth/ui/mobile-debug-console.d.ts +0 -25
- package/dist/core/phone-auth/ui/modal.d.ts +0 -88
- package/dist/core/phone-auth/ui/modal.js +0 -598
- package/dist/core/phone-auth/validation-utils.d.ts +0 -44
- package/dist/core/types.d.ts +0 -62
- package/dist/core/types.js +0 -2
- package/dist/core/version.d.ts +0 -1
- package/dist/core/version.js +0 -5
- package/dist/esm/adapters/angular/client.service.d.ts +0 -7
- package/dist/esm/adapters/angular/client.service.js +0 -27
- package/dist/esm/adapters/angular/index.d.ts +0 -3
- package/dist/esm/adapters/angular/index.js +0 -4
- package/dist/esm/adapters/angular/phone-auth.service.d.ts +0 -38
- package/dist/esm/adapters/angular/phone-auth.service.js +0 -127
- package/dist/esm/adapters/react/index.d.ts +0 -9
- package/dist/esm/adapters/react/index.js +0 -8
- package/dist/esm/adapters/react/useClient.d.ts +0 -26
- package/dist/esm/adapters/react/useClient.js +0 -116
- package/dist/esm/adapters/react/usePhoneAuth.d.ts +0 -23
- package/dist/esm/adapters/react/usePhoneAuth.js +0 -92
- package/dist/esm/adapters/vanilla/client.d.ts +0 -8
- package/dist/esm/adapters/vanilla/client.js +0 -29
- package/dist/esm/adapters/vanilla/index.d.ts +0 -3
- package/dist/esm/adapters/vanilla/index.js +0 -4
- package/dist/esm/adapters/vanilla/phone-auth.d.ts +0 -46
- package/dist/esm/adapters/vanilla/phone-auth.js +0 -134
- package/dist/esm/adapters/vue/index.d.ts +0 -10
- package/dist/esm/adapters/vue/index.js +0 -11
- package/dist/esm/adapters/vue/useClient.d.ts +0 -115
- package/dist/esm/adapters/vue/useClient.js +0 -127
- package/dist/esm/adapters/vue/usePhoneAuth.d.ts +0 -94
- package/dist/esm/adapters/vue/usePhoneAuth.js +0 -100
- package/dist/esm/browser.d.ts +0 -7
- package/dist/esm/core/client.d.ts +0 -22
- package/dist/esm/core/client.js +0 -70
- package/dist/esm/core/logger.d.ts +0 -130
- package/dist/esm/core/logger.js +0 -359
- package/dist/esm/core/phone-auth/api-types.d.ts +0 -593
- package/dist/esm/core/phone-auth/api-types.js +0 -203
- package/dist/esm/core/phone-auth/client.d.ts +0 -189
- package/dist/esm/core/phone-auth/client.js +0 -1404
- package/dist/esm/core/phone-auth/error-utils.d.ts +0 -110
- package/dist/esm/core/phone-auth/error-utils.js +0 -338
- package/dist/esm/core/phone-auth/index.d.ts +0 -7
- package/dist/esm/core/phone-auth/index.js +0 -8
- package/dist/esm/core/phone-auth/status-types.d.ts +0 -107
- package/dist/esm/core/phone-auth/status-types.js +0 -26
- package/dist/esm/core/phone-auth/strategies/desktop.d.ts +0 -122
- package/dist/esm/core/phone-auth/strategies/desktop.js +0 -590
- package/dist/esm/core/phone-auth/strategies/index.d.ts +0 -11
- package/dist/esm/core/phone-auth/strategies/index.js +0 -7
- package/dist/esm/core/phone-auth/strategies/link.d.ts +0 -89
- package/dist/esm/core/phone-auth/strategies/link.js +0 -380
- package/dist/esm/core/phone-auth/strategies/ts43.d.ts +0 -32
- package/dist/esm/core/phone-auth/strategies/ts43.js +0 -157
- package/dist/esm/core/phone-auth/strategies/types.d.ts +0 -18
- package/dist/esm/core/phone-auth/strategies/types.js +0 -5
- package/dist/esm/core/phone-auth/type-guards.d.ts +0 -143
- package/dist/esm/core/phone-auth/type-guards.js +0 -185
- package/dist/esm/core/phone-auth/types.d.ts +0 -237
- package/dist/esm/core/phone-auth/types.js +0 -76
- package/dist/esm/core/phone-auth/ui/modal.d.ts +0 -88
- package/dist/esm/core/phone-auth/ui/modal.js +0 -594
- package/dist/esm/core/phone-auth/validation-utils.d.ts +0 -44
- package/dist/esm/core/types.d.ts +0 -62
- package/dist/esm/core/version.d.ts +0 -1
- package/dist/esm/core/version.js +0 -2
- package/dist/esm/index.d.ts +0 -12
- package/dist/index.d.ts +0 -12
- package/dist/index.js +0 -55
|
@@ -1,596 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Desktop Strategy Handler
|
|
4
|
-
* Handles QR code-based authentication for desktop browsers
|
|
5
|
-
* Manages QR code display and polling for authentication status
|
|
6
|
-
*/
|
|
7
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
8
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
10
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
11
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
12
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
13
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
14
|
-
});
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.DesktopHandler = void 0;
|
|
18
|
-
exports.createQRCodeDisplay = createQRCodeDisplay;
|
|
19
|
-
exports.showQRCodeModal = showQRCodeModal;
|
|
20
|
-
class DesktopHandler {
|
|
21
|
-
constructor() {
|
|
22
|
-
this.pollingAttempts = 0;
|
|
23
|
-
this.isCancelled = false;
|
|
24
|
-
this.isPollingInProgress = false;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Maps backend HTTP status codes to client status
|
|
28
|
-
* @param httpStatus HTTP status code from backend
|
|
29
|
-
* @param bodyStatus Optional status from response body (for 200 OK responses)
|
|
30
|
-
* @returns Mapped status string for client use
|
|
31
|
-
*/
|
|
32
|
-
mapBackendStatus(httpStatus, bodyStatus) {
|
|
33
|
-
switch (httpStatus) {
|
|
34
|
-
case 200:
|
|
35
|
-
// For 200 OK, check the body status
|
|
36
|
-
return bodyStatus === 'completed' ? 'authenticated' : 'pending';
|
|
37
|
-
case 410:
|
|
38
|
-
return 'expired';
|
|
39
|
-
case 422:
|
|
40
|
-
return 'error'; // Failed or cancelled
|
|
41
|
-
case 404:
|
|
42
|
-
return 'error'; // Session not found
|
|
43
|
-
case 400:
|
|
44
|
-
return 'error'; // Invalid session key
|
|
45
|
-
default:
|
|
46
|
-
return 'error';
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Invoke desktop authentication with QR code
|
|
51
|
-
* Returns QR code data for display and starts polling if endpoint is provided
|
|
52
|
-
*/
|
|
53
|
-
invoke(data, options) {
|
|
54
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
-
const desktopData = data.data;
|
|
56
|
-
// Extract QR code from nested or flat structure, checking multiple field names
|
|
57
|
-
let qrCode;
|
|
58
|
-
let sessionId;
|
|
59
|
-
let pollingEndpoint;
|
|
60
|
-
let pollingInterval;
|
|
61
|
-
let expiresIn;
|
|
62
|
-
// Check nested structure first (data.data.qr_code_image or data.data.qr_code)
|
|
63
|
-
if (desktopData && desktopData.data && typeof desktopData.data === 'object') {
|
|
64
|
-
const innerData = desktopData.data;
|
|
65
|
-
// Try to extract from inner data
|
|
66
|
-
// Support both single QR (qr_code_image) and dual-platform QR (ios/android)
|
|
67
|
-
if (innerData.ios_qr_image && innerData.android_qr_image) {
|
|
68
|
-
// Dual-platform QR format - both must be present
|
|
69
|
-
qrCode = {
|
|
70
|
-
iosQRCode: innerData.ios_qr_image,
|
|
71
|
-
androidQRCode: innerData.android_qr_image,
|
|
72
|
-
iosUrl: innerData.ios_url,
|
|
73
|
-
androidUrl: innerData.android_url
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
else if (innerData.ios_qr_image || innerData.android_qr_image) {
|
|
77
|
-
// Only one platform QR - use as single QR format
|
|
78
|
-
qrCode = innerData.ios_qr_image || innerData.android_qr_image;
|
|
79
|
-
}
|
|
80
|
-
else {
|
|
81
|
-
// Single QR format (legacy)
|
|
82
|
-
qrCode = innerData.qr_code_image || innerData.qr_code;
|
|
83
|
-
}
|
|
84
|
-
sessionId = innerData.session_id;
|
|
85
|
-
pollingEndpoint = innerData.status_url;
|
|
86
|
-
pollingInterval = innerData.polling_interval;
|
|
87
|
-
expiresIn = innerData.expires_in;
|
|
88
|
-
}
|
|
89
|
-
// Fall back to flat structure if no QR code found
|
|
90
|
-
if (!qrCode && desktopData) {
|
|
91
|
-
qrCode = desktopData.qr_code_image || desktopData.qr_code;
|
|
92
|
-
sessionId = sessionId || desktopData.session_id;
|
|
93
|
-
pollingEndpoint = pollingEndpoint || desktopData.status_url || desktopData.polling_endpoint;
|
|
94
|
-
pollingInterval = pollingInterval || desktopData.polling_interval;
|
|
95
|
-
expiresIn = expiresIn || desktopData.expires_in;
|
|
96
|
-
}
|
|
97
|
-
// Validate QR code exists
|
|
98
|
-
if (!qrCode) {
|
|
99
|
-
throw new Error('Invalid desktop authentication data: missing QR code');
|
|
100
|
-
}
|
|
101
|
-
// Validate session ID exists
|
|
102
|
-
if (!sessionId) {
|
|
103
|
-
throw new Error('Invalid desktop authentication data: missing session ID');
|
|
104
|
-
}
|
|
105
|
-
// Notify that QR code is ready
|
|
106
|
-
if (options === null || options === void 0 ? void 0 : options.onQRCodeReady) {
|
|
107
|
-
options.onQRCodeReady(qrCode);
|
|
108
|
-
}
|
|
109
|
-
// Use polling endpoint with this priority:
|
|
110
|
-
// 1. Developer-provided endpoint from options (highest priority)
|
|
111
|
-
// 2. Backend-provided endpoint
|
|
112
|
-
// 3. Hardcoded fallback
|
|
113
|
-
console.log('[Desktop QR] Polling endpoint selection:');
|
|
114
|
-
console.log(' - options?.pollingEndpoint:', options === null || options === void 0 ? void 0 : options.pollingEndpoint);
|
|
115
|
-
console.log(' - backend pollingEndpoint:', pollingEndpoint);
|
|
116
|
-
let finalPollingEndpoint = options === null || options === void 0 ? void 0 : options.pollingEndpoint;
|
|
117
|
-
let endpointSource = 'options';
|
|
118
|
-
if (!finalPollingEndpoint) {
|
|
119
|
-
finalPollingEndpoint = pollingEndpoint; // Backend-provided status_url
|
|
120
|
-
endpointSource = 'backend';
|
|
121
|
-
}
|
|
122
|
-
if (!finalPollingEndpoint) {
|
|
123
|
-
// Use hardcoded fallback - this will be constructed in the polling function
|
|
124
|
-
console.log('[Desktop QR] No polling endpoint provided, will use hardcoded fallback');
|
|
125
|
-
endpointSource = 'fallback';
|
|
126
|
-
}
|
|
127
|
-
console.log('[Desktop QR] Selected endpoint:', finalPollingEndpoint, 'from source:', endpointSource);
|
|
128
|
-
// Start polling for authentication status
|
|
129
|
-
const finalPollingInterval = (options === null || options === void 0 ? void 0 : options.pollingInterval) || pollingInterval || 2000;
|
|
130
|
-
const maxAttempts = (options === null || options === void 0 ? void 0 : options.maxPollingAttempts) || 30; // Default to 1 minute
|
|
131
|
-
console.log(`[Desktop QR] Starting polling - endpoint source: ${endpointSource}, interval: ${finalPollingInterval}ms, max attempts: ${maxAttempts}`);
|
|
132
|
-
return this.startPolling(finalPollingEndpoint || '', // Pass empty string if undefined, will use fallback
|
|
133
|
-
sessionId, finalPollingInterval, maxAttempts, expiresIn || 300, // Default 5 minutes expiry
|
|
134
|
-
options, endpointSource // Pass the endpoint source for logging
|
|
135
|
-
);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
/**
|
|
139
|
-
* Start polling for authentication status
|
|
140
|
-
*/
|
|
141
|
-
startPolling(endpoint_1, sessionId_1, interval_1, maxAttempts_1, expiresIn_1, options_1) {
|
|
142
|
-
return __awaiter(this, arguments, void 0, function* (endpoint, sessionId, interval, maxAttempts, expiresIn, options, endpointSource = 'unknown') {
|
|
143
|
-
const startTime = Date.now();
|
|
144
|
-
const expiryTime = startTime + (expiresIn * 1000);
|
|
145
|
-
return new Promise((resolve, reject) => {
|
|
146
|
-
// Store the reject function so we can call it from cancel()
|
|
147
|
-
this.pollingReject = reject;
|
|
148
|
-
const poll = () => __awaiter(this, void 0, void 0, function* () {
|
|
149
|
-
// Skip if another poll is already in progress
|
|
150
|
-
if (this.isPollingInProgress) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
try {
|
|
154
|
-
this.isPollingInProgress = true;
|
|
155
|
-
// Check if cancelled
|
|
156
|
-
if (this.isCancelled) {
|
|
157
|
-
this.stopPolling();
|
|
158
|
-
if (options === null || options === void 0 ? void 0 : options.onCancel) {
|
|
159
|
-
options.onCancel();
|
|
160
|
-
}
|
|
161
|
-
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
162
|
-
options.onStatusUpdate({
|
|
163
|
-
status: 'cancelled',
|
|
164
|
-
message: 'Authentication cancelled'
|
|
165
|
-
});
|
|
166
|
-
}
|
|
167
|
-
// Reject the promise with a cancellation error
|
|
168
|
-
reject({
|
|
169
|
-
code: 'USER_DENIED',
|
|
170
|
-
message: 'Authentication cancelled by user'
|
|
171
|
-
});
|
|
172
|
-
return;
|
|
173
|
-
}
|
|
174
|
-
// Check if expired
|
|
175
|
-
if (Date.now() > expiryTime) {
|
|
176
|
-
this.stopPolling();
|
|
177
|
-
if (options === null || options === void 0 ? void 0 : options.onExpired) {
|
|
178
|
-
options.onExpired();
|
|
179
|
-
}
|
|
180
|
-
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
181
|
-
options.onStatusUpdate({
|
|
182
|
-
status: 'expired',
|
|
183
|
-
message: 'QR code has expired'
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
resolve({
|
|
187
|
-
authenticated: false,
|
|
188
|
-
error: 'Authentication expired'
|
|
189
|
-
});
|
|
190
|
-
return;
|
|
191
|
-
}
|
|
192
|
-
// Check max attempts
|
|
193
|
-
if (this.pollingAttempts >= maxAttempts) {
|
|
194
|
-
this.stopPolling();
|
|
195
|
-
if (options === null || options === void 0 ? void 0 : options.onTimeout) {
|
|
196
|
-
options.onTimeout();
|
|
197
|
-
}
|
|
198
|
-
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
199
|
-
options.onStatusUpdate({
|
|
200
|
-
status: 'error',
|
|
201
|
-
message: 'Polling timeout reached'
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
resolve({
|
|
205
|
-
authenticated: false,
|
|
206
|
-
error: 'Polling timeout'
|
|
207
|
-
});
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
// Build public status endpoint URL - use relative path for proxied requests
|
|
211
|
-
let statusUrl;
|
|
212
|
-
// Extract base URL and construct public endpoint
|
|
213
|
-
if (endpoint && (endpoint.startsWith('http://') || endpoint.startsWith('https://'))) {
|
|
214
|
-
// Full URL provided - use as is
|
|
215
|
-
statusUrl = endpoint;
|
|
216
|
-
}
|
|
217
|
-
else if (endpoint && endpoint !== '') {
|
|
218
|
-
// Relative path provided (e.g. '/api/phone-auth/status')
|
|
219
|
-
// Append session ID to the provided endpoint
|
|
220
|
-
statusUrl = `${endpoint}/${sessionId}`;
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
// No endpoint provided - use hardcoded fallback
|
|
224
|
-
// This ensures it goes through the same domain and uses the app's API configuration
|
|
225
|
-
statusUrl = `/api/phone-auth/status/${sessionId}`;
|
|
226
|
-
}
|
|
227
|
-
// Poll the public endpoint - no authentication required
|
|
228
|
-
console.log(`[Desktop QR] Polling status (attempt ${this.pollingAttempts}/${maxAttempts})`);
|
|
229
|
-
console.log(`[Desktop QR] Using ${endpointSource} endpoint: ${statusUrl}`);
|
|
230
|
-
// Build headers
|
|
231
|
-
const headers = {
|
|
232
|
-
'Accept': 'application/json'
|
|
233
|
-
};
|
|
234
|
-
// Add developer header if devEnv is set
|
|
235
|
-
if (options === null || options === void 0 ? void 0 : options.devEnv) {
|
|
236
|
-
headers['developer'] = options.devEnv;
|
|
237
|
-
console.log(`[Desktop QR] Adding developer header: ${options.devEnv}`);
|
|
238
|
-
}
|
|
239
|
-
const response = yield fetch(statusUrl, {
|
|
240
|
-
method: 'GET',
|
|
241
|
-
headers
|
|
242
|
-
});
|
|
243
|
-
console.log(`[Desktop QR] Status response: ${response.status} ${response.statusText}`);
|
|
244
|
-
// Backend Status Code Mapping:
|
|
245
|
-
// - 200 OK: Session exists (body has 'pending' or 'completed' status)
|
|
246
|
-
// - 410 Gone: Session expired after timeout
|
|
247
|
-
// - 422 Unprocessable Entity: Authentication failed or cancelled
|
|
248
|
-
// - 404 Not Found: Session doesn't exist
|
|
249
|
-
// - 400 Bad Request: Invalid session key format
|
|
250
|
-
// Handle response based on HTTP status code
|
|
251
|
-
if (response.status === 200) {
|
|
252
|
-
const result = yield response.json();
|
|
253
|
-
if (result.status === 'completed') {
|
|
254
|
-
// Authentication completed successfully
|
|
255
|
-
this.stopPolling();
|
|
256
|
-
// Close the modal if it exists
|
|
257
|
-
const modal = document.querySelector('[style*="position: fixed"]');
|
|
258
|
-
if (modal && modal.querySelector('#desktop-auth-status')) {
|
|
259
|
-
setTimeout(() => {
|
|
260
|
-
modal.remove();
|
|
261
|
-
}, 500); // Brief delay to show success message
|
|
262
|
-
}
|
|
263
|
-
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
264
|
-
options.onStatusUpdate({
|
|
265
|
-
status: 'authenticated',
|
|
266
|
-
message: 'Authentication successful',
|
|
267
|
-
data: result
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
// Return the session data for next steps
|
|
271
|
-
this.pollingReject = undefined; // Clear the reject function on success
|
|
272
|
-
resolve({
|
|
273
|
-
authenticated: true,
|
|
274
|
-
credential: result.credential || result.session_key || sessionId,
|
|
275
|
-
session: result.session || {
|
|
276
|
-
session_key: result.session_key || sessionId,
|
|
277
|
-
status: result.status,
|
|
278
|
-
protocol: result.protocol,
|
|
279
|
-
created_at: result.created_at,
|
|
280
|
-
last_updated: result.last_updated
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
}
|
|
284
|
-
else if (result.status === 'pending') {
|
|
285
|
-
// Continue polling
|
|
286
|
-
this.pollingAttempts++;
|
|
287
|
-
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
288
|
-
options.onStatusUpdate({
|
|
289
|
-
status: 'pending',
|
|
290
|
-
message: `Waiting for authentication (attempt ${this.pollingAttempts}/${maxAttempts})`
|
|
291
|
-
});
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
else if (response.status === 410) {
|
|
296
|
-
// Session expired
|
|
297
|
-
this.stopPolling();
|
|
298
|
-
const errorData = yield response.json().catch(() => ({ message: 'Session expired' }));
|
|
299
|
-
// Close the modal on error
|
|
300
|
-
const modal = document.querySelector('[style*="position: fixed"]');
|
|
301
|
-
if (modal && modal.querySelector('#desktop-auth-status')) {
|
|
302
|
-
setTimeout(() => {
|
|
303
|
-
modal.remove();
|
|
304
|
-
}, 500);
|
|
305
|
-
}
|
|
306
|
-
if (options === null || options === void 0 ? void 0 : options.onExpired) {
|
|
307
|
-
options.onExpired();
|
|
308
|
-
}
|
|
309
|
-
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
310
|
-
options.onStatusUpdate({
|
|
311
|
-
status: 'expired',
|
|
312
|
-
message: errorData.message || 'Session has expired'
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
resolve({
|
|
316
|
-
authenticated: false,
|
|
317
|
-
error: errorData.message || 'Session expired'
|
|
318
|
-
});
|
|
319
|
-
}
|
|
320
|
-
else if (response.status === 422) {
|
|
321
|
-
// Authentication failed
|
|
322
|
-
this.stopPolling();
|
|
323
|
-
const errorData = yield response.json().catch(() => ({ message: 'Authentication failed' }));
|
|
324
|
-
// Close the modal on error
|
|
325
|
-
const modal = document.querySelector('[style*="position: fixed"]');
|
|
326
|
-
if (modal && modal.querySelector('#desktop-auth-status')) {
|
|
327
|
-
setTimeout(() => {
|
|
328
|
-
modal.remove();
|
|
329
|
-
}, 500);
|
|
330
|
-
}
|
|
331
|
-
const isUserCancelled = errorData.code === 'USER_CANCELLED';
|
|
332
|
-
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
333
|
-
options.onStatusUpdate({
|
|
334
|
-
status: 'error',
|
|
335
|
-
message: errorData.message || 'Authentication failed'
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
resolve({
|
|
339
|
-
authenticated: false,
|
|
340
|
-
error: isUserCancelled
|
|
341
|
-
? 'User cancelled authentication'
|
|
342
|
-
: (errorData.message || 'Authentication failed')
|
|
343
|
-
});
|
|
344
|
-
}
|
|
345
|
-
else if (response.status === 404) {
|
|
346
|
-
// Session not found
|
|
347
|
-
this.stopPolling();
|
|
348
|
-
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
349
|
-
options.onStatusUpdate({
|
|
350
|
-
status: 'error',
|
|
351
|
-
message: 'Session not found'
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
resolve({
|
|
355
|
-
authenticated: false,
|
|
356
|
-
error: 'Session not found'
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
else if (response.status === 400) {
|
|
360
|
-
// Invalid session key
|
|
361
|
-
this.stopPolling();
|
|
362
|
-
const errorData = yield response.json().catch(() => ({ message: 'Invalid session key' }));
|
|
363
|
-
resolve({
|
|
364
|
-
authenticated: false,
|
|
365
|
-
error: errorData.message || 'Invalid session key'
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
else {
|
|
369
|
-
// Unexpected status - continue polling
|
|
370
|
-
this.pollingAttempts++;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
catch (error) {
|
|
374
|
-
// Network or other error - continue polling
|
|
375
|
-
this.pollingAttempts++;
|
|
376
|
-
if (options === null || options === void 0 ? void 0 : options.onStatusUpdate) {
|
|
377
|
-
options.onStatusUpdate({
|
|
378
|
-
status: 'pending',
|
|
379
|
-
message: `Network error, retrying... (attempt ${this.pollingAttempts}/${maxAttempts})`
|
|
380
|
-
});
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
finally {
|
|
384
|
-
// Always clear the polling flag when done
|
|
385
|
-
this.isPollingInProgress = false;
|
|
386
|
-
}
|
|
387
|
-
});
|
|
388
|
-
// Start initial poll
|
|
389
|
-
poll();
|
|
390
|
-
// Set up interval for subsequent polls
|
|
391
|
-
this.pollingIntervalId = setInterval(poll, interval);
|
|
392
|
-
});
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
/**
|
|
396
|
-
* Stop polling
|
|
397
|
-
*/
|
|
398
|
-
stopPolling() {
|
|
399
|
-
if (this.pollingIntervalId) {
|
|
400
|
-
console.log('[Desktop QR] Stopping polling');
|
|
401
|
-
clearInterval(this.pollingIntervalId);
|
|
402
|
-
this.pollingIntervalId = undefined;
|
|
403
|
-
}
|
|
404
|
-
this.pollingAttempts = 0;
|
|
405
|
-
this.isPollingInProgress = false;
|
|
406
|
-
// Don't clear pollingReject here - it's needed by cancel()
|
|
407
|
-
}
|
|
408
|
-
/**
|
|
409
|
-
* Check if polling is currently active
|
|
410
|
-
*/
|
|
411
|
-
isPolling() {
|
|
412
|
-
return this.pollingIntervalId !== undefined;
|
|
413
|
-
}
|
|
414
|
-
/**
|
|
415
|
-
* Format response for backend processing
|
|
416
|
-
* Desktop strategy typically returns the credential from mobile authentication
|
|
417
|
-
*/
|
|
418
|
-
formatResponse(response) {
|
|
419
|
-
if (!response.authenticated || !response.credential) {
|
|
420
|
-
throw new Error('Authentication not completed');
|
|
421
|
-
}
|
|
422
|
-
return {
|
|
423
|
-
credential: response.credential,
|
|
424
|
-
session: response.session
|
|
425
|
-
};
|
|
426
|
-
}
|
|
427
|
-
/**
|
|
428
|
-
* Check if desktop authentication is supported
|
|
429
|
-
* Desktop auth with QR codes works in any modern browser
|
|
430
|
-
*/
|
|
431
|
-
isSupported() {
|
|
432
|
-
// Check for required browser APIs
|
|
433
|
-
return typeof window !== 'undefined' &&
|
|
434
|
-
typeof fetch !== 'undefined' &&
|
|
435
|
-
typeof Promise !== 'undefined';
|
|
436
|
-
}
|
|
437
|
-
/**
|
|
438
|
-
* Clean up resources (stop polling if active)
|
|
439
|
-
*/
|
|
440
|
-
cleanup() {
|
|
441
|
-
this.stopPolling();
|
|
442
|
-
this.isCancelled = false;
|
|
443
|
-
this.onCancel = undefined;
|
|
444
|
-
this.pollingReject = undefined;
|
|
445
|
-
}
|
|
446
|
-
/**
|
|
447
|
-
* Cancel the ongoing authentication
|
|
448
|
-
*/
|
|
449
|
-
cancel() {
|
|
450
|
-
var _a;
|
|
451
|
-
console.log('[Desktop QR] Cancelling authentication');
|
|
452
|
-
this.isCancelled = true;
|
|
453
|
-
this.stopPolling();
|
|
454
|
-
(_a = this.onCancel) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
455
|
-
// Immediately reject the polling promise
|
|
456
|
-
if (this.pollingReject) {
|
|
457
|
-
this.pollingReject({
|
|
458
|
-
code: 'USER_DENIED',
|
|
459
|
-
message: 'Authentication cancelled by user'
|
|
460
|
-
});
|
|
461
|
-
this.pollingReject = undefined;
|
|
462
|
-
}
|
|
463
|
-
}
|
|
464
|
-
}
|
|
465
|
-
exports.DesktopHandler = DesktopHandler;
|
|
466
|
-
/**
|
|
467
|
-
* Helper function to display QR code in a modal or inline
|
|
468
|
-
*/
|
|
469
|
-
function createQRCodeDisplay(qrCodeData, options) {
|
|
470
|
-
const container = (options === null || options === void 0 ? void 0 : options.container) || document.createElement('div');
|
|
471
|
-
container.className = 'phone-auth-qr-container';
|
|
472
|
-
// Determine QR code to display
|
|
473
|
-
let qrCodeSrc;
|
|
474
|
-
if (typeof qrCodeData === 'string') {
|
|
475
|
-
// Simple string QR code
|
|
476
|
-
qrCodeSrc = qrCodeData;
|
|
477
|
-
}
|
|
478
|
-
else if (qrCodeData && typeof qrCodeData === 'object') {
|
|
479
|
-
// QRCodeData object - prefer iOS QR if available
|
|
480
|
-
if (qrCodeData.iosQRCode) {
|
|
481
|
-
qrCodeSrc = qrCodeData.iosQRCode;
|
|
482
|
-
}
|
|
483
|
-
else if (qrCodeData.androidQRCode) {
|
|
484
|
-
qrCodeSrc = qrCodeData.androidQRCode;
|
|
485
|
-
}
|
|
486
|
-
else {
|
|
487
|
-
throw new Error('Invalid QRCodeData: missing QR code images');
|
|
488
|
-
}
|
|
489
|
-
}
|
|
490
|
-
else {
|
|
491
|
-
throw new Error('Invalid qrCodeData: must be string or QRCodeData object');
|
|
492
|
-
}
|
|
493
|
-
// Create QR code image
|
|
494
|
-
const img = document.createElement('img');
|
|
495
|
-
img.src = qrCodeSrc;
|
|
496
|
-
img.alt = 'QR Code for authentication';
|
|
497
|
-
img.style.width = `${(options === null || options === void 0 ? void 0 : options.size) || 256}px`;
|
|
498
|
-
img.style.height = `${(options === null || options === void 0 ? void 0 : options.size) || 256}px`;
|
|
499
|
-
img.style.display = 'block';
|
|
500
|
-
img.style.margin = '0 auto';
|
|
501
|
-
// Add title if provided
|
|
502
|
-
if (options === null || options === void 0 ? void 0 : options.title) {
|
|
503
|
-
const title = document.createElement('h3');
|
|
504
|
-
title.textContent = options.title;
|
|
505
|
-
title.style.textAlign = 'center';
|
|
506
|
-
title.style.marginBottom = '1rem';
|
|
507
|
-
container.appendChild(title);
|
|
508
|
-
}
|
|
509
|
-
container.appendChild(img);
|
|
510
|
-
// Add description if provided
|
|
511
|
-
if (options === null || options === void 0 ? void 0 : options.description) {
|
|
512
|
-
const desc = document.createElement('p');
|
|
513
|
-
desc.textContent = options.description;
|
|
514
|
-
desc.style.textAlign = 'center';
|
|
515
|
-
desc.style.marginTop = '1rem';
|
|
516
|
-
desc.style.color = '#666';
|
|
517
|
-
container.appendChild(desc);
|
|
518
|
-
}
|
|
519
|
-
return container;
|
|
520
|
-
}
|
|
521
|
-
/**
|
|
522
|
-
* Helper function to create a modal for QR code display
|
|
523
|
-
* Supports both string QR codes and QRCodeData objects for dual-platform support
|
|
524
|
-
*/
|
|
525
|
-
function showQRCodeModal(qrCodeData, options) {
|
|
526
|
-
// Create modal overlay
|
|
527
|
-
const overlay = document.createElement('div');
|
|
528
|
-
overlay.style.cssText = `
|
|
529
|
-
position: fixed;
|
|
530
|
-
top: 0;
|
|
531
|
-
left: 0;
|
|
532
|
-
right: 0;
|
|
533
|
-
bottom: 0;
|
|
534
|
-
background-color: rgba(0, 0, 0, 0.5);
|
|
535
|
-
display: flex;
|
|
536
|
-
align-items: center;
|
|
537
|
-
justify-content: center;
|
|
538
|
-
z-index: 9999;
|
|
539
|
-
`;
|
|
540
|
-
// Create modal content
|
|
541
|
-
const modal = document.createElement('div');
|
|
542
|
-
modal.style.cssText = `
|
|
543
|
-
background: white;
|
|
544
|
-
padding: 2rem;
|
|
545
|
-
border-radius: 8px;
|
|
546
|
-
max-width: 400px;
|
|
547
|
-
position: relative;
|
|
548
|
-
`;
|
|
549
|
-
// Add close button
|
|
550
|
-
const closeBtn = document.createElement('button');
|
|
551
|
-
closeBtn.textContent = '×';
|
|
552
|
-
closeBtn.style.cssText = `
|
|
553
|
-
position: absolute;
|
|
554
|
-
top: 10px;
|
|
555
|
-
right: 10px;
|
|
556
|
-
background: none;
|
|
557
|
-
border: none;
|
|
558
|
-
font-size: 24px;
|
|
559
|
-
cursor: pointer;
|
|
560
|
-
color: #999;
|
|
561
|
-
`;
|
|
562
|
-
closeBtn.onclick = () => {
|
|
563
|
-
document.body.removeChild(overlay);
|
|
564
|
-
if (options === null || options === void 0 ? void 0 : options.onClose) {
|
|
565
|
-
options.onClose();
|
|
566
|
-
}
|
|
567
|
-
};
|
|
568
|
-
modal.appendChild(closeBtn);
|
|
569
|
-
// Add QR code display
|
|
570
|
-
const qrDisplay = createQRCodeDisplay(qrCodeData, {
|
|
571
|
-
title: (options === null || options === void 0 ? void 0 : options.title) || 'Scan QR Code to Authenticate',
|
|
572
|
-
description: (options === null || options === void 0 ? void 0 : options.description) || 'Use your mobile device to scan this QR code'
|
|
573
|
-
});
|
|
574
|
-
modal.appendChild(qrDisplay);
|
|
575
|
-
// Add loading spinner placeholder
|
|
576
|
-
const statusDiv = document.createElement('div');
|
|
577
|
-
statusDiv.id = 'desktop-auth-status';
|
|
578
|
-
statusDiv.style.cssText = `
|
|
579
|
-
text-align: center;
|
|
580
|
-
margin-top: 1rem;
|
|
581
|
-
color: #666;
|
|
582
|
-
font-size: 14px;
|
|
583
|
-
`;
|
|
584
|
-
modal.appendChild(statusDiv);
|
|
585
|
-
overlay.appendChild(modal);
|
|
586
|
-
document.body.appendChild(overlay);
|
|
587
|
-
// Close modal on overlay click
|
|
588
|
-
overlay.onclick = (e) => {
|
|
589
|
-
if (e.target === overlay) {
|
|
590
|
-
document.body.removeChild(overlay);
|
|
591
|
-
if (options === null || options === void 0 ? void 0 : options.onClose) {
|
|
592
|
-
options.onClose();
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
};
|
|
596
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Strategy Handlers Export
|
|
3
|
-
* Provides implementations for TS43, Link, and Desktop authentication strategies
|
|
4
|
-
*/
|
|
5
|
-
export type { StrategyHandler } from './types';
|
|
6
|
-
export { TS43Handler } from './ts43';
|
|
7
|
-
export { LinkHandler } from './link';
|
|
8
|
-
export type { LinkAuthOptions, LinkAuthResult, PollingStatus as LinkPollingStatus } from './link';
|
|
9
|
-
export { DesktopHandler, createQRCodeDisplay, showQRCodeModal } from './desktop';
|
|
10
|
-
export type { DesktopAuthOptions, DesktopAuthResult, PollingStatus } from './desktop';
|
|
11
|
-
export type { TS43Data, LinkData } from '../types';
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Strategy Handlers Export
|
|
4
|
-
* Provides implementations for TS43, Link, and Desktop authentication strategies
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.showQRCodeModal = exports.createQRCodeDisplay = exports.DesktopHandler = exports.LinkHandler = exports.TS43Handler = void 0;
|
|
8
|
-
var ts43_1 = require("./ts43");
|
|
9
|
-
Object.defineProperty(exports, "TS43Handler", { enumerable: true, get: function () { return ts43_1.TS43Handler; } });
|
|
10
|
-
var link_1 = require("./link");
|
|
11
|
-
Object.defineProperty(exports, "LinkHandler", { enumerable: true, get: function () { return link_1.LinkHandler; } });
|
|
12
|
-
var desktop_1 = require("./desktop");
|
|
13
|
-
Object.defineProperty(exports, "DesktopHandler", { enumerable: true, get: function () { return desktop_1.DesktopHandler; } });
|
|
14
|
-
Object.defineProperty(exports, "createQRCodeDisplay", { enumerable: true, get: function () { return desktop_1.createQRCodeDisplay; } });
|
|
15
|
-
Object.defineProperty(exports, "showQRCodeModal", { enumerable: true, get: function () { return desktop_1.showQRCodeModal; } });
|