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