postex-auth-sdk-stage 2.1.0 → 2.3.0
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,137 +1,137 @@
|
|
|
1
|
-
function
|
|
1
|
+
function R() {
|
|
2
2
|
return typeof window < "u" && typeof window.PublicKeyCredential < "u" && typeof navigator < "u" && typeof navigator.credentials < "u";
|
|
3
3
|
}
|
|
4
|
-
async function
|
|
5
|
-
if (!
|
|
4
|
+
async function M() {
|
|
5
|
+
if (!R()) return !1;
|
|
6
6
|
try {
|
|
7
7
|
return await PublicKeyCredential.isConditionalMediationAvailable?.() ?? !1;
|
|
8
8
|
} catch {
|
|
9
9
|
return !1;
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
|
-
function
|
|
13
|
-
const e = new Uint8Array(
|
|
14
|
-
let
|
|
12
|
+
function O(o) {
|
|
13
|
+
const e = new Uint8Array(o);
|
|
14
|
+
let r = "";
|
|
15
15
|
for (let t = 0; t < e.byteLength; t++)
|
|
16
|
-
|
|
17
|
-
return btoa(
|
|
16
|
+
r += String.fromCharCode(e[t]);
|
|
17
|
+
return btoa(r);
|
|
18
18
|
}
|
|
19
|
-
function C(
|
|
20
|
-
if (typeof
|
|
19
|
+
function C(o) {
|
|
20
|
+
if (typeof o != "string" || !o)
|
|
21
21
|
throw new Error("Invalid base64: expected non-empty string");
|
|
22
|
-
const e =
|
|
22
|
+
const e = o.replace(/\s/g, "").replace(/-/g, "+").replace(/_/g, "/"), r = e.length % 4, t = r > 0 ? e + "=".repeat(4 - r) : e;
|
|
23
23
|
try {
|
|
24
|
-
const
|
|
25
|
-
for (let a = 0; a <
|
|
26
|
-
|
|
27
|
-
return
|
|
24
|
+
const s = atob(t), n = new Uint8Array(s.length);
|
|
25
|
+
for (let a = 0; a < s.length; a++)
|
|
26
|
+
n[a] = s.charCodeAt(a);
|
|
27
|
+
return n.buffer;
|
|
28
28
|
} catch {
|
|
29
29
|
throw new Error(
|
|
30
30
|
"Invalid base64: string is not correctly encoded. Check challenge/credentialId from server."
|
|
31
31
|
);
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
|
-
function
|
|
35
|
-
return
|
|
34
|
+
function h(o) {
|
|
35
|
+
return O(o).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
36
36
|
}
|
|
37
|
-
function
|
|
37
|
+
function j(o) {
|
|
38
38
|
return /^[0-9a-f]{8}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{4}-?[0-9a-f]{12}$/i.test(
|
|
39
|
-
|
|
39
|
+
o
|
|
40
40
|
);
|
|
41
41
|
}
|
|
42
|
-
function
|
|
43
|
-
const e =
|
|
44
|
-
for (let t = 0; t <
|
|
45
|
-
|
|
46
|
-
return
|
|
42
|
+
function H(o) {
|
|
43
|
+
const e = o.replace(/-/g, ""), r = new Uint8Array(e.length / 2);
|
|
44
|
+
for (let t = 0; t < r.length; t++)
|
|
45
|
+
r[t] = parseInt(e.substr(t * 2, 2), 16);
|
|
46
|
+
return r.buffer;
|
|
47
47
|
}
|
|
48
|
-
function
|
|
49
|
-
if (!
|
|
48
|
+
function P(o) {
|
|
49
|
+
if (!o || typeof o != "string")
|
|
50
50
|
throw new Error("Invalid input: expected non-empty string");
|
|
51
|
-
return
|
|
51
|
+
return j(o) ? H(o) : C(o);
|
|
52
52
|
}
|
|
53
|
-
function
|
|
54
|
-
return new TextEncoder().encode(
|
|
53
|
+
function k(o) {
|
|
54
|
+
return new TextEncoder().encode(o).buffer;
|
|
55
55
|
}
|
|
56
|
-
function
|
|
57
|
-
return String.fromCharCode(...
|
|
56
|
+
function J(o) {
|
|
57
|
+
return String.fromCharCode(...o);
|
|
58
58
|
}
|
|
59
|
-
const
|
|
60
|
-
function
|
|
61
|
-
return new Promise((
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
const t =
|
|
59
|
+
const F = "xpay_webauthn", W = 1, u = "passkey_data", E = "passkey_email", _ = "passkey_mobile_number";
|
|
60
|
+
function m() {
|
|
61
|
+
return new Promise((o, e) => {
|
|
62
|
+
const r = indexedDB.open(F, W);
|
|
63
|
+
r.onerror = () => e(r.error), r.onsuccess = () => o(r.result), r.onupgradeneeded = () => {
|
|
64
|
+
const t = r.result;
|
|
65
65
|
t.objectStoreNames.contains(u) || t.createObjectStore(u);
|
|
66
66
|
};
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
-
async function
|
|
69
|
+
async function G() {
|
|
70
70
|
try {
|
|
71
|
-
const
|
|
72
|
-
return new Promise((e,
|
|
73
|
-
const t =
|
|
74
|
-
|
|
71
|
+
const o = await m();
|
|
72
|
+
return new Promise((e, r) => {
|
|
73
|
+
const t = o.transaction(u, "readonly"), n = t.objectStore(u).get(E);
|
|
74
|
+
n.onerror = () => r(n.error), n.onsuccess = () => e(n.result ?? null), t.oncomplete = () => o.close();
|
|
75
75
|
});
|
|
76
76
|
} catch {
|
|
77
77
|
return null;
|
|
78
78
|
}
|
|
79
79
|
}
|
|
80
|
-
async function
|
|
80
|
+
async function Y(o) {
|
|
81
81
|
try {
|
|
82
|
-
const e = await
|
|
83
|
-
return new Promise((
|
|
84
|
-
const
|
|
85
|
-
a.onerror = () => t(a.error), a.onsuccess = () =>
|
|
82
|
+
const e = await m();
|
|
83
|
+
return new Promise((r, t) => {
|
|
84
|
+
const s = e.transaction(u, "readwrite"), a = s.objectStore(u).put(o, E);
|
|
85
|
+
a.onerror = () => t(a.error), a.onsuccess = () => r(), s.oncomplete = () => e.close();
|
|
86
86
|
});
|
|
87
87
|
} catch {
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
-
async function
|
|
90
|
+
async function V() {
|
|
91
91
|
try {
|
|
92
|
-
const
|
|
93
|
-
return new Promise((e,
|
|
94
|
-
const t =
|
|
95
|
-
|
|
92
|
+
const o = await m();
|
|
93
|
+
return new Promise((e, r) => {
|
|
94
|
+
const t = o.transaction(u, "readwrite"), n = t.objectStore(u).delete(E);
|
|
95
|
+
n.onerror = () => r(n.error), n.onsuccess = () => e(), t.oncomplete = () => o.close();
|
|
96
96
|
});
|
|
97
97
|
} catch {
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
-
async function
|
|
100
|
+
async function X() {
|
|
101
101
|
try {
|
|
102
|
-
const
|
|
103
|
-
return new Promise((e,
|
|
104
|
-
const t =
|
|
105
|
-
|
|
102
|
+
const o = await m();
|
|
103
|
+
return new Promise((e, r) => {
|
|
104
|
+
const t = o.transaction(u, "readonly"), n = t.objectStore(u).get(_);
|
|
105
|
+
n.onerror = () => r(n.error), n.onsuccess = () => e(n.result ?? null), t.oncomplete = () => o.close();
|
|
106
106
|
});
|
|
107
107
|
} catch {
|
|
108
108
|
return null;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
|
-
async function
|
|
111
|
+
async function Z(o) {
|
|
112
112
|
try {
|
|
113
|
-
const e = await
|
|
114
|
-
return new Promise((
|
|
115
|
-
const
|
|
116
|
-
a.onerror = () => t(a.error), a.onsuccess = () =>
|
|
113
|
+
const e = await m();
|
|
114
|
+
return new Promise((r, t) => {
|
|
115
|
+
const s = e.transaction(u, "readwrite"), a = s.objectStore(u).put(o, _);
|
|
116
|
+
a.onerror = () => t(a.error), a.onsuccess = () => r(), s.oncomplete = () => e.close();
|
|
117
117
|
});
|
|
118
118
|
} catch {
|
|
119
119
|
}
|
|
120
120
|
}
|
|
121
|
-
async function
|
|
121
|
+
async function Q() {
|
|
122
122
|
try {
|
|
123
|
-
const
|
|
124
|
-
return new Promise((e,
|
|
125
|
-
const t =
|
|
126
|
-
|
|
123
|
+
const o = await m();
|
|
124
|
+
return new Promise((e, r) => {
|
|
125
|
+
const t = o.transaction(u, "readwrite"), n = t.objectStore(u).delete(_);
|
|
126
|
+
n.onerror = () => r(n.error), n.onsuccess = () => e(), t.oncomplete = () => o.close();
|
|
127
127
|
});
|
|
128
128
|
} catch {
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
-
const S = "dpop_private_key",
|
|
132
|
-
function
|
|
133
|
-
if (!
|
|
134
|
-
const e =
|
|
131
|
+
const S = "dpop_private_key", A = "dpop_public_key_jwk";
|
|
132
|
+
function N(o) {
|
|
133
|
+
if (!o || typeof o != "object") return !1;
|
|
134
|
+
const e = o;
|
|
135
135
|
return e.kty === "EC" && e.crv === "P-256" && typeof e.x == "string" && typeof e.y == "string";
|
|
136
136
|
}
|
|
137
137
|
class g extends Error {
|
|
@@ -139,84 +139,84 @@ class g extends Error {
|
|
|
139
139
|
super(e), this.name = "DPoPProofGenerationError";
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
-
function
|
|
142
|
+
function ee(o) {
|
|
143
143
|
return {
|
|
144
144
|
kty: "EC",
|
|
145
145
|
crv: "P-256",
|
|
146
|
-
x:
|
|
147
|
-
y:
|
|
146
|
+
x: o.x,
|
|
147
|
+
y: o.y
|
|
148
148
|
};
|
|
149
149
|
}
|
|
150
|
-
async function
|
|
150
|
+
async function K(o) {
|
|
151
151
|
const e = JSON.stringify({
|
|
152
|
-
crv:
|
|
153
|
-
kty:
|
|
154
|
-
x:
|
|
155
|
-
y:
|
|
156
|
-
}),
|
|
152
|
+
crv: o.crv,
|
|
153
|
+
kty: o.kty,
|
|
154
|
+
x: o.x,
|
|
155
|
+
y: o.y
|
|
156
|
+
}), r = await crypto.subtle.digest(
|
|
157
157
|
"SHA-256",
|
|
158
158
|
new TextEncoder().encode(e)
|
|
159
159
|
);
|
|
160
|
-
return
|
|
160
|
+
return h(r);
|
|
161
161
|
}
|
|
162
|
-
async function
|
|
162
|
+
async function te(o) {
|
|
163
163
|
try {
|
|
164
|
-
const e = await
|
|
165
|
-
return new Promise((
|
|
166
|
-
const
|
|
167
|
-
a.onerror = () => t(a.error), a.onsuccess = () =>
|
|
164
|
+
const e = await m();
|
|
165
|
+
return new Promise((r, t) => {
|
|
166
|
+
const s = e.transaction(u, "readwrite"), a = s.objectStore(u).put(o, S);
|
|
167
|
+
a.onerror = () => t(a.error), a.onsuccess = () => r(), s.oncomplete = () => e.close();
|
|
168
168
|
});
|
|
169
169
|
} catch (e) {
|
|
170
170
|
console.error("Failed to store DPoP private key:", e);
|
|
171
171
|
}
|
|
172
172
|
}
|
|
173
|
-
async function
|
|
173
|
+
async function re(o) {
|
|
174
174
|
try {
|
|
175
|
-
const e = await
|
|
176
|
-
return new Promise((
|
|
177
|
-
const
|
|
178
|
-
a.onerror = () => t(a.error), a.onsuccess = () =>
|
|
175
|
+
const e = await m();
|
|
176
|
+
return new Promise((r, t) => {
|
|
177
|
+
const s = e.transaction(u, "readwrite"), a = s.objectStore(u).put(o, A);
|
|
178
|
+
a.onerror = () => t(a.error), a.onsuccess = () => r(), s.oncomplete = () => e.close();
|
|
179
179
|
});
|
|
180
180
|
} catch (e) {
|
|
181
181
|
console.error("Failed to store DPoP public key JWK:", e);
|
|
182
182
|
}
|
|
183
183
|
}
|
|
184
|
-
async function
|
|
184
|
+
async function q() {
|
|
185
185
|
try {
|
|
186
|
-
const
|
|
187
|
-
return new Promise((e,
|
|
188
|
-
const t =
|
|
189
|
-
|
|
186
|
+
const o = await m();
|
|
187
|
+
return new Promise((e, r) => {
|
|
188
|
+
const t = o.transaction(u, "readonly"), n = t.objectStore(u).get(S);
|
|
189
|
+
n.onerror = () => r(n.error), n.onsuccess = () => e(n.result ?? null), t.oncomplete = () => o.close();
|
|
190
190
|
});
|
|
191
191
|
} catch {
|
|
192
192
|
return null;
|
|
193
193
|
}
|
|
194
194
|
}
|
|
195
|
-
async function
|
|
195
|
+
async function $() {
|
|
196
196
|
try {
|
|
197
|
-
const
|
|
198
|
-
return new Promise((e,
|
|
199
|
-
const t =
|
|
200
|
-
|
|
197
|
+
const o = await m();
|
|
198
|
+
return new Promise((e, r) => {
|
|
199
|
+
const t = o.transaction(u, "readonly"), n = t.objectStore(u).get(A);
|
|
200
|
+
n.onerror = () => r(n.error), n.onsuccess = () => e(n.result ?? null), t.oncomplete = () => o.close();
|
|
201
201
|
});
|
|
202
202
|
} catch {
|
|
203
203
|
return null;
|
|
204
204
|
}
|
|
205
205
|
}
|
|
206
|
-
async function
|
|
206
|
+
async function T() {
|
|
207
207
|
try {
|
|
208
|
-
const
|
|
209
|
-
return new Promise((e,
|
|
210
|
-
const t =
|
|
211
|
-
|
|
212
|
-
|
|
208
|
+
const o = await m();
|
|
209
|
+
return new Promise((e, r) => {
|
|
210
|
+
const t = o.transaction(u, "readwrite"), s = t.objectStore(u);
|
|
211
|
+
s.delete(S), s.delete(A), t.onerror = () => r(t.error), t.oncomplete = () => {
|
|
212
|
+
o.close(), e();
|
|
213
213
|
};
|
|
214
214
|
});
|
|
215
215
|
} catch {
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
|
-
async function
|
|
219
|
-
const
|
|
218
|
+
async function ne() {
|
|
219
|
+
const o = await crypto.subtle.generateKey(
|
|
220
220
|
{
|
|
221
221
|
name: "ECDSA",
|
|
222
222
|
namedCurve: "P-256"
|
|
@@ -224,102 +224,102 @@ async function re() {
|
|
|
224
224
|
!1,
|
|
225
225
|
// Private key is non-extractable
|
|
226
226
|
["sign", "verify"]
|
|
227
|
-
), e = await crypto.subtle.exportKey("jwk",
|
|
228
|
-
return await
|
|
227
|
+
), e = await crypto.subtle.exportKey("jwk", o.publicKey), r = ee(e), t = await K(r);
|
|
228
|
+
return await te(o.privateKey), await re(r), { publicKey: r, thumbprint: t };
|
|
229
229
|
}
|
|
230
230
|
async function se() {
|
|
231
|
-
const
|
|
232
|
-
return
|
|
231
|
+
const o = await q(), e = await $();
|
|
232
|
+
return o && N(e) ? {
|
|
233
233
|
publicKey: e,
|
|
234
|
-
thumbprint: await
|
|
235
|
-
} : ((
|
|
234
|
+
thumbprint: await K(e)
|
|
235
|
+
} : ((o || e) && await T(), ne());
|
|
236
236
|
}
|
|
237
|
-
async function
|
|
237
|
+
async function oe(o, e, r) {
|
|
238
238
|
try {
|
|
239
|
-
const t = await
|
|
240
|
-
if (!t || !
|
|
239
|
+
const t = await q(), s = await $();
|
|
240
|
+
if (!t || !N(s))
|
|
241
241
|
throw new g(
|
|
242
242
|
"DPoP key material is unavailable or invalid"
|
|
243
243
|
);
|
|
244
|
-
const
|
|
244
|
+
const n = {
|
|
245
245
|
typ: "dpop+jwt",
|
|
246
246
|
alg: "ES256",
|
|
247
|
-
jwk:
|
|
247
|
+
jwk: s
|
|
248
248
|
// Public key in JWK format
|
|
249
249
|
}, a = new URL(
|
|
250
250
|
e,
|
|
251
251
|
typeof window < "u" ? window.location.origin : void 0
|
|
252
|
-
), l = `${a.origin}${a.pathname}`,
|
|
252
|
+
), l = `${a.origin}${a.pathname}`, c = {
|
|
253
253
|
jti: crypto.randomUUID(),
|
|
254
|
-
htm:
|
|
254
|
+
htm: o.toUpperCase(),
|
|
255
255
|
htu: l,
|
|
256
256
|
iat: Math.floor(Date.now() / 1e3)
|
|
257
257
|
};
|
|
258
|
-
if (
|
|
259
|
-
const
|
|
260
|
-
|
|
258
|
+
if (r) {
|
|
259
|
+
const z = new TextEncoder().encode(r), L = await crypto.subtle.digest("SHA-256", z);
|
|
260
|
+
c.ath = h(L);
|
|
261
261
|
}
|
|
262
|
-
const d =
|
|
263
|
-
new TextEncoder().encode(JSON.stringify(
|
|
264
|
-
),
|
|
265
|
-
new TextEncoder().encode(JSON.stringify(
|
|
266
|
-
),
|
|
262
|
+
const d = h(
|
|
263
|
+
new TextEncoder().encode(JSON.stringify(n)).buffer
|
|
264
|
+
), i = h(
|
|
265
|
+
new TextEncoder().encode(JSON.stringify(c)).buffer
|
|
266
|
+
), p = `${d}.${i}`, f = await crypto.subtle.sign(
|
|
267
267
|
{
|
|
268
268
|
name: "ECDSA",
|
|
269
269
|
hash: { name: "SHA-256" }
|
|
270
270
|
},
|
|
271
271
|
t,
|
|
272
|
-
new TextEncoder().encode(
|
|
273
|
-
),
|
|
274
|
-
return `${d}.${
|
|
272
|
+
new TextEncoder().encode(p)
|
|
273
|
+
), w = h(f);
|
|
274
|
+
return `${d}.${i}.${w}`;
|
|
275
275
|
} catch (t) {
|
|
276
276
|
throw console.error("Failed to generate DPoP proof:", t), t instanceof g ? t : new g("Failed to generate DPoP proof");
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
|
-
const
|
|
280
|
-
isWebAuthnSupported:
|
|
281
|
-
isConditionalUISupported:
|
|
282
|
-
arrayBufferToBase64:
|
|
279
|
+
const B = {
|
|
280
|
+
isWebAuthnSupported: R,
|
|
281
|
+
isConditionalUISupported: M,
|
|
282
|
+
arrayBufferToBase64: O,
|
|
283
283
|
base64ToArrayBuffer: C,
|
|
284
|
-
arrayBufferToBase64url:
|
|
285
|
-
base64urlToArrayBuffer:
|
|
286
|
-
stringToArrayBuffer:
|
|
287
|
-
uint8ArrayToString:
|
|
288
|
-
getPasskeyEmail:
|
|
289
|
-
setPasskeyEmail:
|
|
290
|
-
clearPasskeyEmail:
|
|
291
|
-
getPasskeyMobileNumber:
|
|
292
|
-
setPasskeyMobileNumber:
|
|
293
|
-
clearPasskeyMobileNumber:
|
|
284
|
+
arrayBufferToBase64url: h,
|
|
285
|
+
base64urlToArrayBuffer: P,
|
|
286
|
+
stringToArrayBuffer: k,
|
|
287
|
+
uint8ArrayToString: J,
|
|
288
|
+
getPasskeyEmail: G,
|
|
289
|
+
setPasskeyEmail: Y,
|
|
290
|
+
clearPasskeyEmail: V,
|
|
291
|
+
getPasskeyMobileNumber: X,
|
|
292
|
+
setPasskeyMobileNumber: Z,
|
|
293
|
+
clearPasskeyMobileNumber: Q
|
|
294
294
|
};
|
|
295
|
-
typeof window < "u" && (window.WebAuthn =
|
|
296
|
-
const
|
|
297
|
-
|
|
298
|
-
const
|
|
295
|
+
typeof window < "u" && (window.WebAuthn = B);
|
|
296
|
+
const ae = typeof window < "u" ? window : globalThis;
|
|
297
|
+
ae.WebAuthn = B;
|
|
298
|
+
const b = "postex-auth-token", ie = "postexglobal", ce = {
|
|
299
299
|
xstak: "https://auth-stage.xstak.com/public/v1",
|
|
300
300
|
postex: "https://auth-stage.postex.pk/public/v1",
|
|
301
301
|
callcourier: "https://auth-stage.callcourier.com.pk/public/v1",
|
|
302
302
|
postexglobal: "https://auth-stage.postexglobal.com/public/v1",
|
|
303
303
|
postexsa: "https://auth-stage.postex.sa/public/v1"
|
|
304
|
-
},
|
|
305
|
-
class
|
|
306
|
-
constructor(e,
|
|
307
|
-
super(t ?? `Request failed with status ${e}`), this.response = { status: e, data:
|
|
304
|
+
}, le = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/, ue = /^\+[1-9]\d{6,14}$/, de = /^\d{6}$/, he = /^[A-Za-z0-9_-]{16,512}$/, pe = /[\u0000-\u001F\u007F-\u009F]/, ye = /[A-Za-z]/, me = /[\u0400-\u04FF]/, v = 254, x = 16, I = 64;
|
|
305
|
+
class fe extends Error {
|
|
306
|
+
constructor(e, r, t) {
|
|
307
|
+
super(t ?? `Request failed with status ${e}`), this.response = { status: e, data: r }, this.name = "AuthSDKFetchError";
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
310
|
class y extends Error {
|
|
311
|
-
constructor(e,
|
|
312
|
-
super(
|
|
311
|
+
constructor(e, r, t = "invalid_input") {
|
|
312
|
+
super(r), this.field = e, this.code = t, this.name = "SDKValidationError";
|
|
313
313
|
}
|
|
314
314
|
}
|
|
315
|
-
const D = "
|
|
316
|
-
class
|
|
315
|
+
const D = "auth_sdk_refresh_token";
|
|
316
|
+
class U {
|
|
317
317
|
constructor(e) {
|
|
318
318
|
this.config = e, this.dpopInitializationPromise = this.createDPoPInitializationPromise();
|
|
319
319
|
}
|
|
320
320
|
getBaseUrl() {
|
|
321
|
-
const e = this.config.appId ??
|
|
322
|
-
return
|
|
321
|
+
const e = this.config.appId ?? ie;
|
|
322
|
+
return ce[e];
|
|
323
323
|
}
|
|
324
324
|
async initializeDPoPState() {
|
|
325
325
|
await se();
|
|
@@ -329,85 +329,86 @@ class M {
|
|
|
329
329
|
}
|
|
330
330
|
createDPoPInitializationPromise() {
|
|
331
331
|
const e = this.initializeDPoPState();
|
|
332
|
-
return e.catch(() => {
|
|
332
|
+
return e.catch((r) => {
|
|
333
|
+
console.warn("[AuthSDK] DPoP initialization failed:", r);
|
|
333
334
|
}), e;
|
|
334
335
|
}
|
|
335
336
|
resetDPoPInitialization() {
|
|
336
337
|
this.dpopInitializationPromise = this.createDPoPInitializationPromise();
|
|
337
338
|
}
|
|
338
|
-
async getRequiredDPoPProof(e,
|
|
339
|
-
return await this.ensureDPoPInitialized(),
|
|
339
|
+
async getRequiredDPoPProof(e, r, t) {
|
|
340
|
+
return await this.ensureDPoPInitialized(), oe(e.toUpperCase(), r, t);
|
|
340
341
|
}
|
|
341
342
|
containsControlChars(e) {
|
|
342
|
-
return
|
|
343
|
+
return pe.test(e);
|
|
343
344
|
}
|
|
344
345
|
hasMixedLatinAndCyrillic(e) {
|
|
345
|
-
return
|
|
346
|
+
return ye.test(e) && me.test(e);
|
|
346
347
|
}
|
|
347
|
-
assertNoControlChars(e,
|
|
348
|
-
if (this.containsControlChars(
|
|
348
|
+
assertNoControlChars(e, r) {
|
|
349
|
+
if (this.containsControlChars(r))
|
|
349
350
|
throw new y(
|
|
350
351
|
e,
|
|
351
352
|
`${e} must not contain control characters`
|
|
352
353
|
);
|
|
353
354
|
}
|
|
354
|
-
validateEmail(e,
|
|
355
|
+
validateEmail(e, r = "email") {
|
|
355
356
|
const t = e.trim();
|
|
356
357
|
if (!t)
|
|
357
|
-
throw new y(
|
|
358
|
-
if (t.length >
|
|
358
|
+
throw new y(r, `${r} is required`);
|
|
359
|
+
if (t.length > v)
|
|
359
360
|
throw new y(
|
|
360
|
-
|
|
361
|
-
`${
|
|
361
|
+
r,
|
|
362
|
+
`${r} must be ${v} characters or fewer`
|
|
362
363
|
);
|
|
363
|
-
this.assertNoControlChars(
|
|
364
|
-
const [
|
|
365
|
-
if (this.hasMixedLatinAndCyrillic(
|
|
364
|
+
this.assertNoControlChars(r, t);
|
|
365
|
+
const [s = ""] = t.split("@");
|
|
366
|
+
if (this.hasMixedLatinAndCyrillic(s))
|
|
366
367
|
throw new y(
|
|
367
|
-
|
|
368
|
-
`${
|
|
368
|
+
r,
|
|
369
|
+
`${r} must not mix Latin and Cyrillic characters in the local part`
|
|
369
370
|
);
|
|
370
|
-
if (!
|
|
371
|
-
throw new y(
|
|
371
|
+
if (!le.test(t))
|
|
372
|
+
throw new y(r, `${r} must be a valid email`);
|
|
372
373
|
return t;
|
|
373
374
|
}
|
|
374
|
-
validateMobileNumber(e,
|
|
375
|
+
validateMobileNumber(e, r = "mobileNumber") {
|
|
375
376
|
const t = e.trim();
|
|
376
377
|
if (!t)
|
|
377
|
-
throw new y(
|
|
378
|
-
if (t.length >
|
|
378
|
+
throw new y(r, `${r} is required`);
|
|
379
|
+
if (t.length > x)
|
|
379
380
|
throw new y(
|
|
380
|
-
|
|
381
|
-
`${
|
|
381
|
+
r,
|
|
382
|
+
`${r} must be ${x} characters or fewer`
|
|
382
383
|
);
|
|
383
|
-
if (this.assertNoControlChars(
|
|
384
|
-
throw new y(
|
|
384
|
+
if (this.assertNoControlChars(r, t), !ue.test(t))
|
|
385
|
+
throw new y(r, `${r} must be in E.164 format`);
|
|
385
386
|
return t;
|
|
386
387
|
}
|
|
387
|
-
validateOTP(e,
|
|
388
|
+
validateOTP(e, r = "otp") {
|
|
388
389
|
const t = e.trim();
|
|
389
|
-
if (this.assertNoControlChars(
|
|
390
|
-
throw new y(
|
|
390
|
+
if (this.assertNoControlChars(r, t), !de.test(t))
|
|
391
|
+
throw new y(r, `${r} must be a 6-digit code`);
|
|
391
392
|
return t;
|
|
392
393
|
}
|
|
393
|
-
validateMagicLinkToken(e,
|
|
394
|
+
validateMagicLinkToken(e, r = "token") {
|
|
394
395
|
const t = e.trim();
|
|
395
|
-
if (this.assertNoControlChars(
|
|
396
|
+
if (this.assertNoControlChars(r, t), !he.test(t))
|
|
396
397
|
throw new y(
|
|
397
|
-
|
|
398
|
-
`${
|
|
398
|
+
r,
|
|
399
|
+
`${r} must be 16-512 URL-safe characters`
|
|
399
400
|
);
|
|
400
401
|
return t;
|
|
401
402
|
}
|
|
402
403
|
validateRealm(e) {
|
|
403
|
-
const
|
|
404
|
-
if (
|
|
405
|
-
if (this.assertNoControlChars("realm",
|
|
404
|
+
const r = e?.trim();
|
|
405
|
+
if (r) {
|
|
406
|
+
if (this.assertNoControlChars("realm", r), r.length > I)
|
|
406
407
|
throw new y(
|
|
407
408
|
"realm",
|
|
408
|
-
`realm must be ${
|
|
409
|
+
`realm must be ${I} characters or fewer`
|
|
409
410
|
);
|
|
410
|
-
return
|
|
411
|
+
return r;
|
|
411
412
|
}
|
|
412
413
|
}
|
|
413
414
|
normalizeAndValidateIdentifier(e) {
|
|
@@ -419,25 +420,25 @@ class M {
|
|
|
419
420
|
normalizeAuthIdentifier(e) {
|
|
420
421
|
return this.normalizeAndValidateIdentifier(e);
|
|
421
422
|
}
|
|
422
|
-
extractRealm(e,
|
|
423
|
-
const t =
|
|
423
|
+
extractRealm(e, r) {
|
|
424
|
+
const t = r?.realm ?? (e && typeof e != "string" ? e.realm : void 0);
|
|
424
425
|
return this.validateRealm(t);
|
|
425
426
|
}
|
|
426
|
-
buildAuthRequestBody(e,
|
|
427
|
-
const t = this.normalizeAuthIdentifier(e),
|
|
427
|
+
buildAuthRequestBody(e, r) {
|
|
428
|
+
const t = this.normalizeAuthIdentifier(e), s = this.extractRealm(e, r);
|
|
428
429
|
return {
|
|
429
430
|
...t,
|
|
430
|
-
...
|
|
431
|
+
...s ? { realm: s } : {}
|
|
431
432
|
};
|
|
432
433
|
}
|
|
433
|
-
buildUrl(e,
|
|
434
|
-
const t = this.getBaseUrl().replace(/\/$/, ""),
|
|
435
|
-
if (!
|
|
436
|
-
const a = new URLSearchParams(
|
|
437
|
-
return `${
|
|
434
|
+
buildUrl(e, r) {
|
|
435
|
+
const t = this.getBaseUrl().replace(/\/$/, ""), s = e.startsWith("/") ? e : `/${e}`, n = `${t}${s}`;
|
|
436
|
+
if (!r || Object.keys(r).length === 0) return n;
|
|
437
|
+
const a = new URLSearchParams(r).toString();
|
|
438
|
+
return `${n}?${a}`;
|
|
438
439
|
}
|
|
439
|
-
async request(e,
|
|
440
|
-
const
|
|
440
|
+
async request(e, r, t) {
|
|
441
|
+
const s = this.buildUrl(r, t?.params), n = {
|
|
441
442
|
"Content-Type": "application/json",
|
|
442
443
|
Accept: "application/json",
|
|
443
444
|
"X-API-Key": this.config.apiKey ?? "",
|
|
@@ -445,22 +446,22 @@ class M {
|
|
|
445
446
|
}, a = {
|
|
446
447
|
method: e,
|
|
447
448
|
credentials: "include",
|
|
448
|
-
headers:
|
|
449
|
+
headers: n
|
|
449
450
|
};
|
|
450
451
|
t?.body !== void 0 && t?.body !== null && (a.body = JSON.stringify(t.body));
|
|
451
|
-
const l = await fetch(
|
|
452
|
+
const l = await fetch(s, a);
|
|
452
453
|
if (!l.ok) {
|
|
453
|
-
let
|
|
454
|
+
let i;
|
|
454
455
|
try {
|
|
455
|
-
const
|
|
456
|
-
|
|
456
|
+
const p = await l.text();
|
|
457
|
+
i = p ? JSON.parse(p) : void 0;
|
|
457
458
|
} catch {
|
|
458
|
-
|
|
459
|
+
i = void 0;
|
|
459
460
|
}
|
|
460
|
-
throw l.status === 401 && await this.clearTokens(), new
|
|
461
|
+
throw l.status === 401 && (await this.clearTokens(), await T(), this.resetDPoPInitialization()), new fe(l.status, i);
|
|
461
462
|
}
|
|
462
|
-
const
|
|
463
|
-
return { data:
|
|
463
|
+
const c = await l.text();
|
|
464
|
+
return { data: c ? JSON.parse(c) : {} };
|
|
464
465
|
}
|
|
465
466
|
/**
|
|
466
467
|
* Returns auth headers (Authorization + DPoP) for the given request.
|
|
@@ -468,24 +469,24 @@ class M {
|
|
|
468
469
|
* @param method - HTTP method (e.g. "GET", "POST")
|
|
469
470
|
* @param url - Full request URL
|
|
470
471
|
*/
|
|
471
|
-
async getRequestAuthHeaders(e,
|
|
472
|
-
const t = localStorage.getItem(
|
|
472
|
+
async getRequestAuthHeaders(e, r) {
|
|
473
|
+
const t = localStorage.getItem(b);
|
|
473
474
|
if (!t) return {};
|
|
474
|
-
const
|
|
475
|
+
const s = r.startsWith("http") ? r : `${this.getBaseUrl()}${r}`, n = await this.getRequiredDPoPProof(e, s, t);
|
|
475
476
|
return {
|
|
476
477
|
Authorization: `Bearer ${t}`,
|
|
477
|
-
DPoP:
|
|
478
|
+
DPoP: n
|
|
478
479
|
};
|
|
479
480
|
}
|
|
480
481
|
/**
|
|
481
482
|
* GET /auth/status - Check if client has trusted device session and what auth method is available.
|
|
482
483
|
* Returns no_session | session_found | webauthn_ready per PostEx Auth BFF spec.
|
|
483
484
|
*/
|
|
484
|
-
async getStatus(e,
|
|
485
|
-
const t = this.normalizeAuthIdentifier(e),
|
|
486
|
-
t.email && (
|
|
485
|
+
async getStatus(e, r) {
|
|
486
|
+
const t = this.normalizeAuthIdentifier(e), s = this.extractRealm(e, r), n = {};
|
|
487
|
+
t.email && (n.email = t.email), t.mobileNumber && (n.mobileNumber = t.mobileNumber), s && (n.realm = s);
|
|
487
488
|
const a = await this.request("GET", "/auth/status", {
|
|
488
|
-
params:
|
|
489
|
+
params: n
|
|
489
490
|
});
|
|
490
491
|
return a.data.data ?? a.data;
|
|
491
492
|
}
|
|
@@ -493,30 +494,30 @@ class M {
|
|
|
493
494
|
* POST /auth/initiate - Unified entry: returns webauthn_challenge or otp_sent.
|
|
494
495
|
* Sets auth_session cookie when otp_sent.
|
|
495
496
|
*/
|
|
496
|
-
async initiateAuth(e,
|
|
497
|
-
const t = this.buildAuthRequestBody(e,
|
|
497
|
+
async initiateAuth(e, r) {
|
|
498
|
+
const t = this.buildAuthRequestBody(e, r), s = await this.request("POST", "/auth/initiate", {
|
|
498
499
|
body: t
|
|
499
|
-
}),
|
|
500
|
+
}), n = s.data.data ?? s.data;
|
|
500
501
|
return {
|
|
501
|
-
status:
|
|
502
|
-
challenge:
|
|
503
|
-
credentialIds:
|
|
504
|
-
rp:
|
|
502
|
+
status: n.status,
|
|
503
|
+
challenge: n.challenge,
|
|
504
|
+
credentialIds: n.credentialIds,
|
|
505
|
+
rp: n.rp
|
|
505
506
|
};
|
|
506
507
|
}
|
|
507
508
|
/**
|
|
508
509
|
* POST /otp/initiate - Direct OTP initiation using email or mobile number.
|
|
509
510
|
* Requires at least one identifier: email or mobileNumber.
|
|
510
511
|
*/
|
|
511
|
-
async initiateOTP(e,
|
|
512
|
-
const t = this.normalizeAuthIdentifier(e),
|
|
513
|
-
if (!
|
|
512
|
+
async initiateOTP(e, r) {
|
|
513
|
+
const t = this.normalizeAuthIdentifier(e), s = this.extractRealm(e, r), n = t.email, a = t.mobileNumber;
|
|
514
|
+
if (!n && !a)
|
|
514
515
|
throw new y(
|
|
515
516
|
"identifier",
|
|
516
517
|
"Either mobileNumber or email is required"
|
|
517
518
|
);
|
|
518
519
|
const l = {};
|
|
519
|
-
|
|
520
|
+
n && (l.email = n), a && (l.mobileNumber = a), s && (l.realm = s);
|
|
520
521
|
const d = (await this.request("POST", "/otp/initiate", {
|
|
521
522
|
body: l
|
|
522
523
|
})).data;
|
|
@@ -529,27 +530,25 @@ class M {
|
|
|
529
530
|
* Stores tokens from the response.
|
|
530
531
|
*/
|
|
531
532
|
async verifyOTP(e) {
|
|
532
|
-
const
|
|
533
|
+
const r = this.validateOTP(e), t = await this.getRequiredDPoPProof(
|
|
533
534
|
"POST",
|
|
534
535
|
`${this.getBaseUrl()}/otp/verify`
|
|
535
|
-
),
|
|
536
|
-
body: { otp:
|
|
536
|
+
), s = await this.request("POST", "/otp/verify", {
|
|
537
|
+
body: { otp: r },
|
|
537
538
|
headers: { DPoP: t }
|
|
538
|
-
}),
|
|
539
|
+
}), n = s.data.data ?? s.data, a = n.AuthenticationResult ?? n, l = a.access_token ?? a.accessToken ?? a.AccessToken, c = a.refresh_token ?? a.refreshToken ?? a.RefreshToken, d = a.expires_in ?? a.expiresIn, i = a.token_type ?? a.tokenType;
|
|
539
540
|
return l && await this.storeTokens({
|
|
540
541
|
accessToken: l,
|
|
541
|
-
refreshToken:
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
tokenType: h ?? "Bearer"
|
|
542
|
+
refreshToken: c,
|
|
543
|
+
expiresIn: d,
|
|
544
|
+
tokenType: i
|
|
545
545
|
}), {
|
|
546
546
|
access_token: l,
|
|
547
|
-
refresh_token:
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
token_type: h,
|
|
547
|
+
refresh_token: c,
|
|
548
|
+
expires_in: d,
|
|
549
|
+
token_type: i,
|
|
551
550
|
verified: a.verified,
|
|
552
|
-
email: a.email ?? a.Email
|
|
551
|
+
email: a.email ?? a.Email,
|
|
553
552
|
...a
|
|
554
553
|
};
|
|
555
554
|
}
|
|
@@ -558,11 +557,11 @@ class M {
|
|
|
558
557
|
* No payload required, relies on auth_session cookie.
|
|
559
558
|
*/
|
|
560
559
|
async resendOTP() {
|
|
561
|
-
const e = await this.request("POST", "/otp/resend", {}),
|
|
560
|
+
const e = await this.request("POST", "/otp/resend", {}), r = e.data.data ?? e.data;
|
|
562
561
|
return {
|
|
563
|
-
success:
|
|
564
|
-
message:
|
|
565
|
-
...
|
|
562
|
+
success: r.success,
|
|
563
|
+
message: r.message,
|
|
564
|
+
...r
|
|
566
565
|
};
|
|
567
566
|
}
|
|
568
567
|
/**
|
|
@@ -571,30 +570,28 @@ class M {
|
|
|
571
570
|
*/
|
|
572
571
|
async verifySignupOTP({
|
|
573
572
|
mobileNumber: e,
|
|
574
|
-
otp:
|
|
573
|
+
otp: r
|
|
575
574
|
}) {
|
|
576
|
-
const t = this.validateMobileNumber(e),
|
|
575
|
+
const t = this.validateMobileNumber(e), s = this.validateOTP(r), n = await this.getRequiredDPoPProof(
|
|
577
576
|
"POST",
|
|
578
577
|
`${this.getBaseUrl()}/otp/signup/verify`
|
|
579
578
|
), a = await this.request("POST", "/otp/signup/verify", {
|
|
580
|
-
body: { mobileNumber: t, otp:
|
|
581
|
-
headers: { DPoP:
|
|
582
|
-
}), l = a.data.data ?? a.data,
|
|
579
|
+
body: { mobileNumber: t, otp: s },
|
|
580
|
+
headers: { DPoP: n }
|
|
581
|
+
}), l = a.data.data ?? a.data, c = l.AuthenticationResult ?? l, d = c.access_token ?? c.accessToken ?? c.AccessToken, i = c.refresh_token ?? c.refreshToken ?? c.RefreshToken, p = c.expires_in ?? c.expiresIn, f = c.token_type ?? c.tokenType;
|
|
583
582
|
return d && await this.storeTokens({
|
|
584
583
|
accessToken: d,
|
|
585
|
-
refreshToken:
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
tokenType: m ?? "Bearer"
|
|
584
|
+
refreshToken: i,
|
|
585
|
+
expiresIn: p,
|
|
586
|
+
tokenType: f
|
|
589
587
|
}), {
|
|
590
588
|
access_token: d,
|
|
591
|
-
refresh_token:
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
...i
|
|
589
|
+
refresh_token: i,
|
|
590
|
+
expires_in: p,
|
|
591
|
+
token_type: f,
|
|
592
|
+
verified: c.verified,
|
|
593
|
+
email: c.email ?? c.Email,
|
|
594
|
+
...c
|
|
598
595
|
};
|
|
599
596
|
}
|
|
600
597
|
/**
|
|
@@ -602,11 +599,11 @@ class M {
|
|
|
602
599
|
*/
|
|
603
600
|
async resendSignupOTP({
|
|
604
601
|
mobileNumber: e,
|
|
605
|
-
email:
|
|
602
|
+
email: r = ""
|
|
606
603
|
}) {
|
|
607
|
-
const t = this.validateMobileNumber(e),
|
|
608
|
-
body: { email:
|
|
609
|
-
}), a =
|
|
604
|
+
const t = this.validateMobileNumber(e), s = r ? this.validateEmail(r) : "", n = await this.request("POST", "/otp/signup/resend", {
|
|
605
|
+
body: { email: s, mobileNumber: t }
|
|
606
|
+
}), a = n.data.data ?? n.data;
|
|
610
607
|
return {
|
|
611
608
|
success: a.success,
|
|
612
609
|
message: a.message,
|
|
@@ -618,10 +615,10 @@ class M {
|
|
|
618
615
|
* Sets auth_session cookie on success.
|
|
619
616
|
*/
|
|
620
617
|
async verifyMagicLink(e) {
|
|
621
|
-
const
|
|
618
|
+
const r = this.validateMagicLinkToken(e);
|
|
622
619
|
await this.request("GET", "/verify/magic-link", {
|
|
623
620
|
params: {
|
|
624
|
-
token:
|
|
621
|
+
token: r,
|
|
625
622
|
redirect_mode: "frontend"
|
|
626
623
|
}
|
|
627
624
|
});
|
|
@@ -638,21 +635,19 @@ class M {
|
|
|
638
635
|
{
|
|
639
636
|
body: {}
|
|
640
637
|
}
|
|
641
|
-
),
|
|
642
|
-
return
|
|
643
|
-
accessToken:
|
|
644
|
-
refreshToken:
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
tokenType: i ?? "Bearer"
|
|
638
|
+
), r = e.data.data ?? e.data, t = r.AuthenticationResult ?? r, s = t.access_token ?? t.accessToken ?? t.AccessToken, n = t.refresh_token ?? t.refreshToken ?? t.RefreshToken, a = t.expires_in ?? t.expiresIn, l = t.token_type ?? t.tokenType;
|
|
639
|
+
return s && await this.storeTokens({
|
|
640
|
+
accessToken: s,
|
|
641
|
+
refreshToken: n,
|
|
642
|
+
expiresIn: a,
|
|
643
|
+
tokenType: l
|
|
648
644
|
}), {
|
|
649
|
-
access_token:
|
|
650
|
-
refresh_token:
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
token_type: i,
|
|
645
|
+
access_token: s,
|
|
646
|
+
refresh_token: n,
|
|
647
|
+
expires_in: a,
|
|
648
|
+
token_type: l,
|
|
654
649
|
verified: t.verified,
|
|
655
|
-
email: t.email ?? t.Email
|
|
650
|
+
email: t.email ?? t.Email,
|
|
656
651
|
...t
|
|
657
652
|
};
|
|
658
653
|
}
|
|
@@ -667,37 +662,37 @@ class M {
|
|
|
667
662
|
return e.data.data ?? e.data;
|
|
668
663
|
}
|
|
669
664
|
async registerPasskey(e) {
|
|
670
|
-
const
|
|
671
|
-
let
|
|
665
|
+
const r = this.validateEmail(e), t = await this.initiatePasskeyRegistration();
|
|
666
|
+
let s;
|
|
672
667
|
if (t?.user?.id)
|
|
673
668
|
try {
|
|
674
|
-
|
|
669
|
+
s = P(t.user.id);
|
|
675
670
|
} catch {
|
|
676
|
-
|
|
671
|
+
s = k(t.user.id);
|
|
677
672
|
}
|
|
678
673
|
else
|
|
679
|
-
|
|
680
|
-
const
|
|
674
|
+
s = k(r);
|
|
675
|
+
const n = (t.pubKeyCredParams ?? [
|
|
681
676
|
{ type: "public-key", alg: -7 },
|
|
682
677
|
{ type: "public-key", alg: -257 }
|
|
683
|
-
]).map((
|
|
678
|
+
]).map((w) => ({
|
|
684
679
|
type: "public-key",
|
|
685
|
-
alg:
|
|
686
|
-
})), a = t.excludeCredentials?.map((
|
|
680
|
+
alg: w.alg
|
|
681
|
+
})), a = t.excludeCredentials?.map((w) => ({
|
|
687
682
|
type: "public-key",
|
|
688
|
-
id:
|
|
683
|
+
id: P(w)
|
|
689
684
|
})), l = {
|
|
690
|
-
challenge:
|
|
685
|
+
challenge: P(t.challenge),
|
|
691
686
|
rp: {
|
|
692
687
|
name: t.rp?.name ?? "XPay",
|
|
693
688
|
id: t.rp?.id ?? window.location.hostname
|
|
694
689
|
},
|
|
695
690
|
user: {
|
|
696
|
-
id:
|
|
697
|
-
name: t.user?.name ??
|
|
698
|
-
displayName: t.user?.displayName ??
|
|
691
|
+
id: s,
|
|
692
|
+
name: t.user?.name ?? r,
|
|
693
|
+
displayName: t.user?.displayName ?? r
|
|
699
694
|
},
|
|
700
|
-
pubKeyCredParams:
|
|
695
|
+
pubKeyCredParams: n,
|
|
701
696
|
excludeCredentials: a,
|
|
702
697
|
timeout: t.timeout ?? 6e4,
|
|
703
698
|
attestation: "direct",
|
|
@@ -706,94 +701,92 @@ class M {
|
|
|
706
701
|
userVerification: "required",
|
|
707
702
|
authenticatorAttachment: "platform"
|
|
708
703
|
}
|
|
709
|
-
},
|
|
704
|
+
}, c = await navigator.credentials.create({
|
|
710
705
|
publicKey: l
|
|
711
706
|
});
|
|
712
|
-
if (!
|
|
713
|
-
const d =
|
|
714
|
-
clientDataJSON:
|
|
715
|
-
attestationObject:
|
|
716
|
-
rawId:
|
|
707
|
+
if (!c) throw new Error("Credential creation failed");
|
|
708
|
+
const d = c.response, i = {
|
|
709
|
+
clientDataJSON: h(d.clientDataJSON),
|
|
710
|
+
attestationObject: h(d.attestationObject),
|
|
711
|
+
rawId: h(c.rawId)
|
|
717
712
|
};
|
|
718
|
-
if (!
|
|
719
|
-
const
|
|
713
|
+
if (!i.rawId) throw new Error("Raw ID is required");
|
|
714
|
+
const p = await this.getRequiredDPoPProof(
|
|
720
715
|
"POST",
|
|
721
716
|
`${this.getBaseUrl()}/webauthn/register/challenge`
|
|
722
|
-
),
|
|
717
|
+
), f = await this.request(
|
|
723
718
|
"POST",
|
|
724
719
|
"/webauthn/register/challenge",
|
|
725
720
|
{
|
|
726
|
-
body:
|
|
727
|
-
headers: { DPoP:
|
|
721
|
+
body: i,
|
|
722
|
+
headers: { DPoP: p }
|
|
728
723
|
}
|
|
729
724
|
);
|
|
730
|
-
return
|
|
725
|
+
return f.data.data ?? f.data;
|
|
731
726
|
}
|
|
732
727
|
/**
|
|
733
728
|
* POST /webauthn/authenticate/challenge - Authenticate with passkey.
|
|
734
729
|
*/
|
|
735
730
|
async authenticateWithPasskey({
|
|
736
731
|
challenge: e,
|
|
737
|
-
rp:
|
|
732
|
+
rp: r,
|
|
738
733
|
credentialIds: t
|
|
739
734
|
}) {
|
|
740
|
-
const
|
|
735
|
+
const s = await navigator.credentials.get({
|
|
741
736
|
publicKey: {
|
|
742
|
-
challenge:
|
|
743
|
-
rpId:
|
|
744
|
-
allowCredentials: t.map((
|
|
737
|
+
challenge: P(e),
|
|
738
|
+
rpId: r?.host ?? void 0,
|
|
739
|
+
allowCredentials: t.map((w) => ({
|
|
745
740
|
type: "public-key",
|
|
746
|
-
id:
|
|
741
|
+
id: P(w),
|
|
747
742
|
transports: ["internal"]
|
|
748
743
|
})),
|
|
749
744
|
timeout: 6e4,
|
|
750
745
|
userVerification: "required"
|
|
751
746
|
}
|
|
752
747
|
});
|
|
753
|
-
if (!
|
|
754
|
-
const
|
|
755
|
-
clientDataJSON:
|
|
756
|
-
authenticatorData:
|
|
757
|
-
|
|
748
|
+
if (!s) throw new Error("Authentication failed");
|
|
749
|
+
const n = s.response, a = {
|
|
750
|
+
clientDataJSON: h(n.clientDataJSON),
|
|
751
|
+
authenticatorData: h(
|
|
752
|
+
n.authenticatorData
|
|
758
753
|
),
|
|
759
|
-
signature:
|
|
760
|
-
rawId:
|
|
761
|
-
userHandle:
|
|
754
|
+
signature: h(n.signature),
|
|
755
|
+
rawId: h(s.rawId),
|
|
756
|
+
userHandle: n.userHandle ? h(n.userHandle) : ""
|
|
762
757
|
}, l = await this.getRequiredDPoPProof(
|
|
763
758
|
"POST",
|
|
764
759
|
`${this.getBaseUrl()}/webauthn/authenticate/challenge`
|
|
765
|
-
),
|
|
760
|
+
), c = await this.request(
|
|
766
761
|
"POST",
|
|
767
762
|
"/webauthn/authenticate/challenge",
|
|
768
763
|
{
|
|
769
764
|
body: a,
|
|
770
765
|
headers: { DPoP: l }
|
|
771
766
|
}
|
|
772
|
-
), d =
|
|
773
|
-
return
|
|
774
|
-
accessToken:
|
|
775
|
-
refreshToken:
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
tokenType: c.tokenType ?? c.token_type ?? "Bearer"
|
|
767
|
+
), d = c.data.data ?? c.data, i = d.AuthenticationResult ?? d, p = i.AccessToken ?? i.accessToken ?? i.access_token, f = i.RefreshToken ?? i.refreshToken ?? i.refresh_token;
|
|
768
|
+
return p && await this.storeTokens({
|
|
769
|
+
accessToken: p,
|
|
770
|
+
refreshToken: f,
|
|
771
|
+
expiresIn: i.expiresIn ?? i.ExpiresIn,
|
|
772
|
+
tokenType: i.tokenType ?? i.token_type
|
|
779
773
|
}), {
|
|
780
|
-
access_token:
|
|
781
|
-
refresh_token:
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
...c
|
|
774
|
+
access_token: p,
|
|
775
|
+
refresh_token: f,
|
|
776
|
+
email: i.email,
|
|
777
|
+
name: i.name ?? i.userName,
|
|
778
|
+
expiresIn: i.expiresIn ?? i.ExpiresIn,
|
|
779
|
+
tokenType: i.tokenType ?? i.token_type,
|
|
780
|
+
...i
|
|
788
781
|
};
|
|
789
782
|
}
|
|
790
783
|
/**
|
|
791
784
|
* GET /webauthn/credentials/:username - Get user's passkey status.
|
|
792
785
|
*/
|
|
793
786
|
async getPasskeyStatus(e) {
|
|
794
|
-
const t = `/webauthn/credentials/${encodeURIComponent(e)}`,
|
|
795
|
-
headers:
|
|
796
|
-
}), a =
|
|
787
|
+
const t = `/webauthn/credentials/${encodeURIComponent(e)}`, s = await this.signRequest("GET", t), n = await this.request("GET", t, {
|
|
788
|
+
headers: s.headers
|
|
789
|
+
}), a = n.data.data ?? n.data;
|
|
797
790
|
return {
|
|
798
791
|
...a,
|
|
799
792
|
hasCredentials: !!(a.hasCredentials ?? a.credentialId)
|
|
@@ -803,38 +796,38 @@ class M {
|
|
|
803
796
|
* DELETE /webauthn/credentials/:username - Remove passkey.
|
|
804
797
|
*/
|
|
805
798
|
async removePasskey(e) {
|
|
806
|
-
const t = `/webauthn/credentials/${encodeURIComponent(e)}`,
|
|
799
|
+
const t = `/webauthn/credentials/${encodeURIComponent(e)}`, s = await this.signRequest("DELETE", t);
|
|
807
800
|
await this.request("DELETE", t, {
|
|
808
|
-
headers:
|
|
801
|
+
headers: s.headers
|
|
809
802
|
});
|
|
810
803
|
}
|
|
811
804
|
/**
|
|
812
805
|
* Signs a request with DPoP and Authorization headers (internal use).
|
|
813
806
|
*/
|
|
814
|
-
async signRequest(e,
|
|
815
|
-
const
|
|
816
|
-
return { ...t, headers: { ...t.headers, ...
|
|
807
|
+
async signRequest(e, r, t = {}) {
|
|
808
|
+
const s = r.startsWith("http") ? r : `${this.getBaseUrl()}${r}`, n = await this.getRequestAuthHeaders(e, s);
|
|
809
|
+
return { ...t, headers: { ...t.headers, ...n } };
|
|
817
810
|
}
|
|
818
811
|
/**
|
|
819
812
|
* Replaces native fetch or Axios with a DPoP-signed version.
|
|
820
813
|
*/
|
|
821
|
-
async authenticatedFetch(e,
|
|
822
|
-
const t = typeof e == "string" ? e : e instanceof URL ? e.toString() : e.url,
|
|
823
|
-
headers:
|
|
814
|
+
async authenticatedFetch(e, r) {
|
|
815
|
+
const t = typeof e == "string" ? e : e instanceof URL ? e.toString() : e.url, s = r?.method || "GET", n = await this.signRequest(s, t, {
|
|
816
|
+
headers: r?.headers
|
|
824
817
|
});
|
|
825
|
-
return fetch(e, { ...
|
|
818
|
+
return fetch(e, { ...r, headers: n.headers });
|
|
826
819
|
}
|
|
827
820
|
/**
|
|
828
821
|
* Store tokens from /webauthn/authenticate (per spec: sessionStorage preferred).
|
|
829
822
|
*/
|
|
830
823
|
async storeTokens(e) {
|
|
831
|
-
localStorage.setItem(
|
|
824
|
+
localStorage.setItem(b, e.accessToken), e.refreshToken && localStorage.setItem(D, e.refreshToken);
|
|
832
825
|
}
|
|
833
826
|
/**
|
|
834
827
|
* Clear stored tokens (call on logout).
|
|
835
828
|
*/
|
|
836
829
|
async clearTokens() {
|
|
837
|
-
localStorage.removeItem(
|
|
830
|
+
localStorage.removeItem(b), localStorage.removeItem(D);
|
|
838
831
|
}
|
|
839
832
|
/**
|
|
840
833
|
* POST /auth/refresh - Refresh access token using server-stored refresh token.
|
|
@@ -842,19 +835,17 @@ class M {
|
|
|
842
835
|
* Rate limit: 10 requests per minute.
|
|
843
836
|
*/
|
|
844
837
|
async refreshToken(e) {
|
|
845
|
-
const
|
|
846
|
-
body:
|
|
847
|
-
}),
|
|
848
|
-
return
|
|
849
|
-
accessToken:
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
tokenType: l
|
|
838
|
+
const r = this.extractRealm(void 0, e), t = await this.request("POST", "/auth/refresh", {
|
|
839
|
+
body: r ? { realm: r } : {}
|
|
840
|
+
}), s = t.data.data ?? t.data, n = s.access_token, a = s.token_type, l = s.expires_in;
|
|
841
|
+
return n && await this.storeTokens({
|
|
842
|
+
accessToken: n,
|
|
843
|
+
expiresIn: l,
|
|
844
|
+
tokenType: a
|
|
853
845
|
}), {
|
|
854
|
-
access_token:
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
expires_in: i
|
|
846
|
+
access_token: n,
|
|
847
|
+
token_type: a,
|
|
848
|
+
expires_in: l
|
|
858
849
|
};
|
|
859
850
|
}
|
|
860
851
|
/**
|
|
@@ -863,35 +854,35 @@ class M {
|
|
|
863
854
|
*/
|
|
864
855
|
async logout() {
|
|
865
856
|
try {
|
|
866
|
-
const
|
|
867
|
-
await this.request("POST", "/auth/logout",
|
|
857
|
+
const r = await this.getAccessToken() ? await this.signRequest("POST", "/auth/logout", { body: {} }) : { body: {} };
|
|
858
|
+
await this.request("POST", "/auth/logout", r), await T(), this.resetDPoPInitialization();
|
|
868
859
|
} catch {
|
|
869
860
|
}
|
|
870
861
|
await this.clearTokens();
|
|
871
862
|
}
|
|
872
863
|
async getAccessToken() {
|
|
873
|
-
return localStorage.getItem(
|
|
864
|
+
return localStorage.getItem(b);
|
|
874
865
|
}
|
|
875
866
|
}
|
|
876
|
-
typeof window < "u" && (window.AuthSDK =
|
|
877
|
-
const
|
|
878
|
-
|
|
867
|
+
typeof window < "u" && (window.AuthSDK = U);
|
|
868
|
+
const we = typeof window < "u" ? window : globalThis;
|
|
869
|
+
we.AuthSDK = U;
|
|
879
870
|
export {
|
|
880
|
-
|
|
881
|
-
|
|
871
|
+
U as AuthSDK,
|
|
872
|
+
fe as AuthSDKFetchError,
|
|
882
873
|
y as SDKValidationError,
|
|
883
|
-
|
|
884
|
-
|
|
874
|
+
O as arrayBufferToBase64,
|
|
875
|
+
h as arrayBufferToBase64url,
|
|
885
876
|
C as base64ToArrayBuffer,
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
877
|
+
P as base64urlToArrayBuffer,
|
|
878
|
+
V as clearPasskeyEmail,
|
|
879
|
+
Q as clearPasskeyMobileNumber,
|
|
880
|
+
G as getPasskeyEmail,
|
|
881
|
+
X as getPasskeyMobileNumber,
|
|
882
|
+
M as isConditionalUISupported,
|
|
883
|
+
R as isWebAuthnSupported,
|
|
884
|
+
Y as setPasskeyEmail,
|
|
885
|
+
Z as setPasskeyMobileNumber,
|
|
886
|
+
k as stringToArrayBuffer,
|
|
887
|
+
J as uint8ArrayToString
|
|
897
888
|
};
|