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