@polyguard/sdk 1.1.3 → 1.1.6
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/dist/sdk.js +69 -37
- package/package.json +2 -2
- package/src/PolyguardWebsocketClientImpl.js +75 -36
package/dist/sdk.js
CHANGED
|
@@ -10969,7 +10969,7 @@
|
|
|
10969
10969
|
var PolyguardWebsocketClientImpl = class {
|
|
10970
10970
|
constructor(params = {}) {
|
|
10971
10971
|
this.apiClient = new ApiClient_default();
|
|
10972
|
-
const { apiKey, baseUrl, appId, apiServer, requiredProofs = ["Full Name"], scanType = "single", redirectUrl, callbackUrl, cookieName } = params;
|
|
10972
|
+
const { apiKey, baseUrl, appId, apiServer, requiredProofs = ["Full Name"], scanType = "single", redirectUrl, callbackUrl, cookieName, link_uuid } = params;
|
|
10973
10973
|
if (baseUrl) {
|
|
10974
10974
|
this.apiClient.basePath = baseUrl;
|
|
10975
10975
|
}
|
|
@@ -10992,6 +10992,7 @@
|
|
|
10992
10992
|
this.redirectUrl = redirectUrl;
|
|
10993
10993
|
this.callbackUrl = callbackUrl;
|
|
10994
10994
|
this.cookieName = cookieName;
|
|
10995
|
+
this.link_uuid = link_uuid;
|
|
10995
10996
|
}
|
|
10996
10997
|
buildModal() {
|
|
10997
10998
|
const modal = document.createElement("div");
|
|
@@ -11024,33 +11025,60 @@
|
|
|
11024
11025
|
`;
|
|
11025
11026
|
return modal;
|
|
11026
11027
|
}
|
|
11027
|
-
async verify() {
|
|
11028
|
-
|
|
11029
|
-
|
|
11030
|
-
|
|
11028
|
+
async verify(target = null, rawJwt = false) {
|
|
11029
|
+
let modal = null;
|
|
11030
|
+
let qrDiv = null;
|
|
11031
|
+
let isTargetMode = false;
|
|
11032
|
+
if (target) {
|
|
11033
|
+
isTargetMode = true;
|
|
11034
|
+
qrDiv = document.getElementById(target);
|
|
11035
|
+
if (!qrDiv) {
|
|
11036
|
+
throw new Error(`Target element with ID '${target}' not found`);
|
|
11037
|
+
}
|
|
11038
|
+
} else {
|
|
11039
|
+
modal = this.buildModal();
|
|
11040
|
+
}
|
|
11041
|
+
if (!isTargetMode) {
|
|
11042
|
+
document.body.appendChild(modal);
|
|
11043
|
+
qrDiv = modal.querySelector("#polyguard-qr");
|
|
11044
|
+
}
|
|
11031
11045
|
if (qrDiv) {
|
|
11032
11046
|
qrDiv.innerHTML = LOADING_SPINNER;
|
|
11033
11047
|
}
|
|
11034
11048
|
function cleanup() {
|
|
11035
|
-
if (
|
|
11049
|
+
if (isTargetMode) {
|
|
11050
|
+
if (qrDiv) {
|
|
11051
|
+
qrDiv.innerHTML = "";
|
|
11052
|
+
}
|
|
11053
|
+
} else if (modal && modal.parentNode) {
|
|
11054
|
+
modal.parentNode.removeChild(modal);
|
|
11055
|
+
}
|
|
11036
11056
|
}
|
|
11037
11057
|
return new Promise(async (resolve, reject) => {
|
|
11038
11058
|
let ws = null;
|
|
11039
11059
|
let closed = false;
|
|
11040
11060
|
function returnError(msg, score = "OFFLINE") {
|
|
11041
|
-
|
|
11042
|
-
|
|
11043
|
-
errDiv.textContent = msg;
|
|
11044
|
-
errDiv.style.display = "block";
|
|
11045
|
-
}
|
|
11046
|
-
setTimeout(() => {
|
|
11061
|
+
if (isTargetMode) {
|
|
11062
|
+
console.error("Polyguard Error:", msg);
|
|
11047
11063
|
cleanup();
|
|
11048
11064
|
resolve({ presence: { score, msg } });
|
|
11049
|
-
}
|
|
11065
|
+
} else {
|
|
11066
|
+
const errDiv = modal.querySelector("#polyguard-error");
|
|
11067
|
+
if (errDiv) {
|
|
11068
|
+
errDiv.textContent = msg;
|
|
11069
|
+
errDiv.style.display = "block";
|
|
11070
|
+
}
|
|
11071
|
+
setTimeout(() => {
|
|
11072
|
+
cleanup();
|
|
11073
|
+
resolve({ presence: { score, msg } });
|
|
11074
|
+
}, 1250);
|
|
11075
|
+
}
|
|
11050
11076
|
}
|
|
11051
11077
|
function clearError() {
|
|
11052
|
-
|
|
11053
|
-
|
|
11078
|
+
if (!isTargetMode) {
|
|
11079
|
+
const errDiv = modal.querySelector("#polyguard-error");
|
|
11080
|
+
if (errDiv) errDiv.style.display = "none";
|
|
11081
|
+
}
|
|
11054
11082
|
}
|
|
11055
11083
|
function handleClose() {
|
|
11056
11084
|
closed = true;
|
|
@@ -11058,12 +11086,15 @@
|
|
|
11058
11086
|
cleanup();
|
|
11059
11087
|
reject(new Error("User cancelled"));
|
|
11060
11088
|
}
|
|
11061
|
-
|
|
11062
|
-
|
|
11089
|
+
if (!isTargetMode) {
|
|
11090
|
+
modal.querySelector("#polyguard-modal-close").onclick = handleClose;
|
|
11091
|
+
modal.querySelector("#polyguard-modal-cancel").onclick = handleClose;
|
|
11092
|
+
}
|
|
11063
11093
|
try {
|
|
11064
11094
|
clearError();
|
|
11065
11095
|
const wsProtocol = window.location.protocol === "https:" ? "wss" : "ws";
|
|
11066
|
-
const
|
|
11096
|
+
const ticketUrl = this.link_uuid ? `https://${this.apiServer}/v2/ticket/${this.appId}/${this.link_uuid}` : `https://${this.apiServer}/v2/ticket/${this.appId}`;
|
|
11097
|
+
const ticketRes = await fetch(ticketUrl, {
|
|
11067
11098
|
method: "POST",
|
|
11068
11099
|
headers: { "Content-Type": "application/json" },
|
|
11069
11100
|
body: JSON.stringify({ requiredProofs: this.requiredProofs, scanType: this.scanType })
|
|
@@ -11103,26 +11134,27 @@
|
|
|
11103
11134
|
if (pcre) {
|
|
11104
11135
|
ws.send(JSON.stringify({ type: "pong", seq: pcre[1] }));
|
|
11105
11136
|
}
|
|
11106
|
-
|
|
11107
|
-
if (!qrDiv2) return;
|
|
11137
|
+
if (!qrDiv) return;
|
|
11108
11138
|
const isMobile = /Mobi|Android/i.test(navigator.userAgent);
|
|
11109
11139
|
if (isMobile) {
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
instructionText
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
instructionList.children[1]
|
|
11140
|
+
qrDiv.innerHTML = `<button id="polyguard-open-app-button" style="background: #7be7c2; color: #222; font-weight: 600; border-radius: 8px; border: none; padding: 10px 32px; font-size: 16px; cursor: pointer;">Open Polyguard App</button>`;
|
|
11141
|
+
qrDiv.style.background = "transparent";
|
|
11142
|
+
qrDiv.querySelector("#polyguard-open-app-button").onclick = () => window.location.assign(data.qr_url);
|
|
11143
|
+
if (!isTargetMode) {
|
|
11144
|
+
const instructionText = qrDiv.nextElementSibling;
|
|
11145
|
+
if (instructionText) {
|
|
11146
|
+
instructionText.textContent = "Tap the button to verify with the Polyguard app.";
|
|
11147
|
+
}
|
|
11148
|
+
const instructionList = instructionText.nextElementSibling;
|
|
11149
|
+
if (instructionList && instructionList.children[1]) {
|
|
11150
|
+
instructionList.children[1].textContent = "If you do not have the Polyguard app, you will be redirected to download it.";
|
|
11151
|
+
}
|
|
11120
11152
|
}
|
|
11121
11153
|
} else {
|
|
11122
11154
|
const startTime = Date.now();
|
|
11123
11155
|
console.log("time before qr code", startTime);
|
|
11124
11156
|
import_qrcode.default.toString(data.qr_url, { type: "svg" }, (err, svg) => {
|
|
11125
|
-
if (!err)
|
|
11157
|
+
if (!err) qrDiv.innerHTML = svg;
|
|
11126
11158
|
});
|
|
11127
11159
|
console.log("time to generate qr code", Date.now() - startTime);
|
|
11128
11160
|
}
|
|
@@ -11130,12 +11162,11 @@
|
|
|
11130
11162
|
} else if (data && data.jwt) {
|
|
11131
11163
|
cleanup();
|
|
11132
11164
|
ws.close();
|
|
11133
|
-
resolve(data.jwt);
|
|
11165
|
+
resolve(rawJwt ? data : data.jwt);
|
|
11134
11166
|
return;
|
|
11135
11167
|
} else if (data && data.status) {
|
|
11136
|
-
|
|
11137
|
-
|
|
11138
|
-
qrDiv2.innerHTML = LOADING_SPINNER;
|
|
11168
|
+
if (!qrDiv) return;
|
|
11169
|
+
qrDiv.innerHTML = LOADING_SPINNER;
|
|
11139
11170
|
return;
|
|
11140
11171
|
} else if (data && data.error) {
|
|
11141
11172
|
returnError(data.error);
|
|
@@ -11167,11 +11198,12 @@
|
|
|
11167
11198
|
/**
|
|
11168
11199
|
* Wrapper around verify that checks received proof values against expected values.
|
|
11169
11200
|
* @param {Object} expectedProofs - An object mapping proof names to expected values.
|
|
11201
|
+
* @param {string} target - Optional ID of target element to render QR code in.
|
|
11170
11202
|
* @returns {Promise<boolean>} - Resolves to true if all expected proofs match, false otherwise or if cancelled.
|
|
11171
11203
|
*/
|
|
11172
|
-
async require(expectedProofs = {}) {
|
|
11204
|
+
async require(expectedProofs = {}, target = null) {
|
|
11173
11205
|
try {
|
|
11174
|
-
const jwt = await this.verify();
|
|
11206
|
+
const jwt = await this.verify(target);
|
|
11175
11207
|
if (!jwt) return false;
|
|
11176
11208
|
const payload = JSON.parse(atob(jwt.split(".")[1]));
|
|
11177
11209
|
console.dir(payload);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@polyguard/sdk",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.6",
|
|
4
4
|
"main": "dist/sdk.js",
|
|
5
5
|
"module": "dist/sdk.js",
|
|
6
6
|
"browser": "dist/sdk.js",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"superagent": "^8.1.2"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
|
-
"esbuild": "^0.
|
|
23
|
+
"esbuild": "^0.25.0"
|
|
24
24
|
},
|
|
25
25
|
"repository": {
|
|
26
26
|
"type": "git",
|
|
@@ -24,7 +24,7 @@ const LOADING_SPINNER = `<svg xmlns="http://www.w3.org/2000/svg" width="200" hei
|
|
|
24
24
|
export class PolyguardWebsocketClientImpl {
|
|
25
25
|
constructor(params = {}) {
|
|
26
26
|
this.apiClient = new PolyguardApi.ApiClient();
|
|
27
|
-
const { apiKey, baseUrl, appId, apiServer, requiredProofs = ['Full Name'], scanType = 'single', redirectUrl, callbackUrl, cookieName } = params;
|
|
27
|
+
const { apiKey, baseUrl, appId, apiServer, requiredProofs = ['Full Name'], scanType = 'single', redirectUrl, callbackUrl, cookieName, link_uuid } = params;
|
|
28
28
|
if (baseUrl) {
|
|
29
29
|
this.apiClient.basePath = baseUrl;
|
|
30
30
|
}
|
|
@@ -49,6 +49,7 @@ export class PolyguardWebsocketClientImpl {
|
|
|
49
49
|
this.redirectUrl = redirectUrl;
|
|
50
50
|
this.callbackUrl = callbackUrl;
|
|
51
51
|
this.cookieName = cookieName;
|
|
52
|
+
this.link_uuid = link_uuid;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
buildModal() {
|
|
@@ -83,23 +84,46 @@ export class PolyguardWebsocketClientImpl {
|
|
|
83
84
|
return modal;
|
|
84
85
|
}
|
|
85
86
|
|
|
86
|
-
async verify() {
|
|
87
|
+
async verify(target = null, rawJwt = false) {
|
|
87
88
|
// Only websocket integration is supported for modal
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
let modal = null;
|
|
90
|
+
let qrDiv = null;
|
|
91
|
+
let isTargetMode = false;
|
|
90
92
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
+
if (target) {
|
|
94
|
+
// Target mode: render QR code in specified element
|
|
95
|
+
isTargetMode = true;
|
|
96
|
+
qrDiv = document.getElementById(target);
|
|
97
|
+
if (!qrDiv) {
|
|
98
|
+
throw new Error(`Target element with ID '${target}' not found`);
|
|
99
|
+
}
|
|
100
|
+
} else {
|
|
101
|
+
// Modal mode: create modal DOM
|
|
102
|
+
modal = this.buildModal();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!isTargetMode) {
|
|
106
|
+
// Show modal immediately with spinner
|
|
107
|
+
document.body.appendChild(modal);
|
|
108
|
+
|
|
109
|
+
// Initialize QR div with spinner
|
|
110
|
+
qrDiv = modal.querySelector('#polyguard-qr');
|
|
111
|
+
}
|
|
93
112
|
|
|
94
|
-
// Initialize QR div with spinner
|
|
95
|
-
const qrDiv = modal.querySelector('#polyguard-qr');
|
|
96
113
|
if (qrDiv) {
|
|
97
114
|
qrDiv.innerHTML = LOADING_SPINNER;
|
|
98
115
|
}
|
|
99
116
|
|
|
100
|
-
// Helper to cleanup modal
|
|
117
|
+
// Helper to cleanup modal or target
|
|
101
118
|
function cleanup() {
|
|
102
|
-
if (
|
|
119
|
+
if (isTargetMode) {
|
|
120
|
+
// Clear target element content
|
|
121
|
+
if (qrDiv) {
|
|
122
|
+
qrDiv.innerHTML = '';
|
|
123
|
+
}
|
|
124
|
+
} else if (modal && modal.parentNode) {
|
|
125
|
+
modal.parentNode.removeChild(modal);
|
|
126
|
+
}
|
|
103
127
|
}
|
|
104
128
|
// Promise for JWT
|
|
105
129
|
return new Promise(async (resolve, reject) => {
|
|
@@ -107,19 +131,28 @@ export class PolyguardWebsocketClientImpl {
|
|
|
107
131
|
let closed = false;
|
|
108
132
|
|
|
109
133
|
function returnError(msg, score = "OFFLINE") {
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
errDiv.style.display = 'block';
|
|
114
|
-
}
|
|
115
|
-
setTimeout(() => {
|
|
134
|
+
if (isTargetMode) {
|
|
135
|
+
// In target mode, just log the error and resolve with error data
|
|
136
|
+
console.error('Polyguard Error:', msg);
|
|
116
137
|
cleanup();
|
|
117
138
|
resolve({presence: { score: score, msg: msg }});
|
|
118
|
-
}
|
|
139
|
+
} else {
|
|
140
|
+
const errDiv = modal.querySelector('#polyguard-error');
|
|
141
|
+
if (errDiv) {
|
|
142
|
+
errDiv.textContent = msg;
|
|
143
|
+
errDiv.style.display = 'block';
|
|
144
|
+
}
|
|
145
|
+
setTimeout(() => {
|
|
146
|
+
cleanup();
|
|
147
|
+
resolve({presence: { score: score, msg: msg }});
|
|
148
|
+
}, 1250);
|
|
149
|
+
}
|
|
119
150
|
}
|
|
120
151
|
function clearError() {
|
|
121
|
-
|
|
122
|
-
|
|
152
|
+
if (!isTargetMode) {
|
|
153
|
+
const errDiv = modal.querySelector('#polyguard-error');
|
|
154
|
+
if (errDiv) errDiv.style.display = 'none';
|
|
155
|
+
}
|
|
123
156
|
}
|
|
124
157
|
// Close/cancel handler
|
|
125
158
|
function handleClose() {
|
|
@@ -129,15 +162,20 @@ export class PolyguardWebsocketClientImpl {
|
|
|
129
162
|
reject(new Error('User cancelled'));
|
|
130
163
|
}
|
|
131
164
|
|
|
132
|
-
// Set up close/cancel handlers
|
|
133
|
-
|
|
134
|
-
|
|
165
|
+
// Set up close/cancel handlers (only in modal mode)
|
|
166
|
+
if (!isTargetMode) {
|
|
167
|
+
modal.querySelector('#polyguard-modal-close').onclick = handleClose;
|
|
168
|
+
modal.querySelector('#polyguard-modal-cancel').onclick = handleClose;
|
|
169
|
+
}
|
|
135
170
|
|
|
136
171
|
// Start ticket/ws flow
|
|
137
172
|
try {
|
|
138
173
|
clearError();
|
|
139
174
|
const wsProtocol = window.location.protocol === 'https:' ? 'wss' : 'ws';
|
|
140
|
-
const
|
|
175
|
+
const ticketUrl = this.link_uuid
|
|
176
|
+
? `https://${this.apiServer}/v2/ticket/${this.appId}/${this.link_uuid}`
|
|
177
|
+
: `https://${this.apiServer}/v2/ticket/${this.appId}`;
|
|
178
|
+
const ticketRes = await fetch(ticketUrl, {
|
|
141
179
|
method: 'POST',
|
|
142
180
|
headers: { 'Content-Type': 'application/json' },
|
|
143
181
|
body: JSON.stringify({ requiredProofs: this.requiredProofs, scanType: this.scanType }),
|
|
@@ -182,7 +220,6 @@ export class PolyguardWebsocketClientImpl {
|
|
|
182
220
|
ws.send(JSON.stringify({ type: 'pong', seq: pcre[1] }));
|
|
183
221
|
}
|
|
184
222
|
|
|
185
|
-
const qrDiv = modal.querySelector('#polyguard-qr');
|
|
186
223
|
if (!qrDiv) return;
|
|
187
224
|
|
|
188
225
|
const isMobile = /Mobi|Android/i.test(navigator.userAgent);
|
|
@@ -193,14 +230,16 @@ export class PolyguardWebsocketClientImpl {
|
|
|
193
230
|
qrDiv.style.background = 'transparent';
|
|
194
231
|
qrDiv.querySelector('#polyguard-open-app-button').onclick = () => window.location.assign(data.qr_url);
|
|
195
232
|
|
|
196
|
-
// Update surrounding text
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
instructionText
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
instructionList.children[1]
|
|
233
|
+
// Update surrounding text only in modal mode
|
|
234
|
+
if (!isTargetMode) {
|
|
235
|
+
const instructionText = qrDiv.nextElementSibling;
|
|
236
|
+
if (instructionText) {
|
|
237
|
+
instructionText.textContent = 'Tap the button to verify with the Polyguard app.';
|
|
238
|
+
}
|
|
239
|
+
const instructionList = instructionText.nextElementSibling;
|
|
240
|
+
if (instructionList && instructionList.children[1]) {
|
|
241
|
+
instructionList.children[1].textContent = 'If you do not have the Polyguard app, you will be redirected to download it.';
|
|
242
|
+
}
|
|
204
243
|
}
|
|
205
244
|
} else {
|
|
206
245
|
const startTime = Date.now();
|
|
@@ -215,12 +254,11 @@ export class PolyguardWebsocketClientImpl {
|
|
|
215
254
|
} else if (data && data.jwt) {
|
|
216
255
|
cleanup();
|
|
217
256
|
ws.close();
|
|
218
|
-
resolve(data.jwt);
|
|
257
|
+
resolve(rawJwt ? data : data.jwt);
|
|
219
258
|
return;
|
|
220
259
|
} else if (data && data.status) {
|
|
221
260
|
// ignore
|
|
222
261
|
// generate a spinner in svg and set the qr code to it
|
|
223
|
-
const qrDiv = modal.querySelector('#polyguard-qr');
|
|
224
262
|
if (!qrDiv) return;
|
|
225
263
|
qrDiv.innerHTML = LOADING_SPINNER;
|
|
226
264
|
return;
|
|
@@ -257,11 +295,12 @@ export class PolyguardWebsocketClientImpl {
|
|
|
257
295
|
/**
|
|
258
296
|
* Wrapper around verify that checks received proof values against expected values.
|
|
259
297
|
* @param {Object} expectedProofs - An object mapping proof names to expected values.
|
|
298
|
+
* @param {string} target - Optional ID of target element to render QR code in.
|
|
260
299
|
* @returns {Promise<boolean>} - Resolves to true if all expected proofs match, false otherwise or if cancelled.
|
|
261
300
|
*/
|
|
262
|
-
async require(expectedProofs = {}) {
|
|
301
|
+
async require(expectedProofs = {}, target = null) {
|
|
263
302
|
try {
|
|
264
|
-
const jwt = await this.verify();
|
|
303
|
+
const jwt = await this.verify(target);
|
|
265
304
|
if (!jwt) return false;
|
|
266
305
|
// Decode JWT (without verifying signature)
|
|
267
306
|
const payload = JSON.parse(atob(jwt.split('.')[1]));
|