@pelican-identity/auth-core 1.2.3 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +2 -0
- package/dist/constants.js.map +1 -0
- package/dist/engine/engine.d.ts.map +1 -1
- package/dist/engine/engine.js +8 -9
- package/dist/engine/engine.js.map +1 -1
- package/dist/index.d.mts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -476
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +46 -13
- package/dist/index.mjs.map +1 -1
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/types.js +2 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utilities/crypto.d.ts.map +1 -0
- package/dist/utilities/crypto.js +37 -0
- package/dist/utilities/crypto.js.map +1 -0
- package/dist/utilities/stateMachine.d.ts.map +1 -0
- package/dist/utilities/stateMachine.js +18 -0
- package/dist/utilities/stateMachine.js.map +1 -0
- package/dist/utilities/storage.d.ts.map +1 -0
- package/dist/utilities/storage.js +92 -0
- package/dist/utilities/storage.js.map +1 -0
- package/dist/utilities/transport.d.ts +22 -0
- package/dist/utilities/transport.d.ts.map +1 -0
- package/dist/utilities/transport.js +57 -0
- package/dist/utilities/transport.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,uBAAuB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EAGpB,MAAM,gBAAgB,CAAC;AAYxB,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,CAAC;AAMxC,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IAEnD,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,UAAU,CAAuB;IAEzC,OAAO,CAAC,iBAAiB,CAAC,CAAa;IAEvC,OAAO,CAAC,SAAS,CAEV;IAEP,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;gBAEzC,MAAM,EAAE,iBAAiB;IAsBrC,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EACpC,KAAK,EAAE,CAAC,EACR,EAAE,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAWhC,KAAK;IAqCX,IAAI;YAOU,aAAa;YAiBb,cAAc;
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EAGpB,MAAM,gBAAgB,CAAC;AAYxB,KAAK,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,IAAI,CAAC;AAMxC,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAuB;IAC9C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IAEnD,OAAO,CAAC,SAAS,CAAC,CAAY;IAC9B,OAAO,CAAC,SAAS,CAAM;IACvB,OAAO,CAAC,UAAU,CAAuB;IAEzC,OAAO,CAAC,iBAAiB,CAAC,CAAa;IAEvC,OAAO,CAAC,SAAS,CAEV;IAEP,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;gBAEzC,MAAM,EAAE,iBAAiB;IAsBrC,EAAE,CAAC,CAAC,SAAS,MAAM,mBAAmB,EACpC,KAAK,EAAE,CAAC,EACR,EAAE,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;IAWhC,KAAK;IAqCX,IAAI;YAOU,aAAa;YAiBb,cAAc;IAkC5B,OAAO,CAAC,aAAa;IAiCrB,OAAO,CAAC,iBAAiB;YAwCX,cAAc;IA4B5B,OAAO,CAAC,wBAAwB;IAYhC,OAAO,CAAC,wBAAwB;IAQhC,OAAO,CAAC,SAAS;IAsBjB,OAAO,CAAC,mBAAmB;IAQ3B,OAAO,CAAC,YAAY;IAMpB,OAAO;IAMP,OAAO,CAAC,IAAI;IAOZ,OAAO,CAAC,IAAI;CAIb"}
|
package/dist/engine/engine.js
CHANGED
|
@@ -87,15 +87,17 @@ export class PelicanAuthentication {
|
|
|
87
87
|
this.emit("deeplink", `pelicanvault://auth/deep-link?data=${encodeURIComponent(JSON.stringify(payload))}`);
|
|
88
88
|
}
|
|
89
89
|
else {
|
|
90
|
-
const qr = await QRCode.toDataURL(JSON.stringify(payload)
|
|
90
|
+
const qr = await QRCode.toDataURL(JSON.stringify(payload), {
|
|
91
|
+
type: "image/png",
|
|
92
|
+
scale: 3,
|
|
93
|
+
color: { light: "#FFFFF5", dark: "#121212" },
|
|
94
|
+
});
|
|
91
95
|
this.emit("qr", qr);
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
handleMessage(msg) {
|
|
95
|
-
console.log(msg);
|
|
96
99
|
switch (msg.type) {
|
|
97
100
|
case "paired":
|
|
98
|
-
console.log("Paired");
|
|
99
101
|
this.stateMachine.transition("paired");
|
|
100
102
|
this.transport.send({
|
|
101
103
|
type: "authenticate",
|
|
@@ -199,21 +201,18 @@ export class PelicanAuthentication {
|
|
|
199
201
|
authType: this.config.authType,
|
|
200
202
|
});
|
|
201
203
|
}
|
|
202
|
-
|
|
203
|
-
this.transport?.close();
|
|
204
|
-
}, 150);
|
|
204
|
+
this.transport?.close();
|
|
205
205
|
clearAuthSession();
|
|
206
206
|
this.resetSession();
|
|
207
207
|
if (!this.config.continuousMode) {
|
|
208
208
|
this.detachVisibilityRecovery();
|
|
209
209
|
}
|
|
210
|
-
this.stateMachine.transition(success ? "confirmed" : "
|
|
210
|
+
this.stateMachine.transition(success ? "confirmed" : "idle");
|
|
211
211
|
}
|
|
212
212
|
restartIfContinuous() {
|
|
213
|
+
this.stateMachine.transition("idle");
|
|
213
214
|
if (!this.config.continuousMode)
|
|
214
215
|
return;
|
|
215
|
-
this.terminate(false);
|
|
216
|
-
this.stateMachine.transition("idle");
|
|
217
216
|
setTimeout(() => {
|
|
218
217
|
this.start();
|
|
219
218
|
}, 150);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"AAAA,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,MAAM,MAAM,QAAQ,CAAC;AAO5B,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,gBAAgB,GAEjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAQvC,MAAM,OAAO,qBAAqB;IAgBhC,YAAY,MAAyB;QAfpB,WAAM,GAAG,IAAI,aAAa,EAAE,CAAC;QAC7B,iBAAY,GAAG,IAAI,YAAY,EAAE,CAAC;QAG3C,cAAS,GAAG,EAAE,CAAC;QACf,eAAU,GAAkB,IAAI,CAAC;QAIjC,cAAS,GAEb,EAAE,CAAC;QAKL,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAE1D,IAAI,CAAC,MAAM,GAAG;YACZ,cAAc,EAAE,KAAK;YACrB,WAAW,EAAE,KAAK;YAClB,GAAG,MAAM;SACV,CAAC;QAGF,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QAC1D,IAAI,CAAC,wBAAwB,EAAE,CAAC;IAClC,CAAC;IAQD,EAAE,CACA,KAAQ,EACR,EAAoC;;QAEpC,MAAA,IAAI,CAAC,SAAS,EAAC,KAAK,SAAL,KAAK,IAAM,IAAI,GAAG,EAAE,EAAC;QACpC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC/B,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAE,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC;IAMD,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,YAAY,CAAC,OAAO,KAAK,MAAM;YAAE,OAAO;QAEjD,IAAI,CAAC,YAAY,EAAE,CAAC;QACpB,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;QAE7C,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;YAGzC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,oBAAoB,EAAE,CAAC;YACrD,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;YAE3D,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,CAAC;gBAC7B,MAAM,EAAE,GAAG,EAAE;oBAEX,IAAI,CAAC,SAAU,CAAC,IAAI,CAAC;wBACnB,IAAI,EAAE,UAAU;wBAChB,SAAS,EAAE,IAAI,CAAC,SAAS;wBACzB,GAAG,IAAI,CAAC,MAAM;qBACf,CAAC,CAAC;oBACH,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;gBAChD,CAAC;gBACD,SAAS,EAAE,CAAC,GAAmB,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;gBAC3D,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;aACnE,CAAC,CAAC;YAEH,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC9B,MAAM,IAAI,CAAC,cAAc,EAAE,CAAC;QAC9B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,IAAI,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;IAKD,IAAI;QACF,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IAKO,KAAK,CAAC,aAAa;QACzB,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QACvD,MAAM,GAAG,GAAG,MAAM,KAAK,CACrB,GAAG,OAAO,qBAAqB,SAAS,cAAc,QAAQ,eAAe,SAAS,EAAE,CACzF,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAKO,KAAK,CAAC,cAAc;QAC1B,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;YAChC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC9B,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,SAAS;YAChC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;SAC1B,CAAC;QAEF,MAAM,WAAW,GACf,IAAI,CAAC,MAAM,CAAC,WAAW;YACvB,CAAC,sBAAsB,CAAC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;QAEpD,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YAEpC,gBAAgB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC,GAAG,KAAM,CAAC,CAAC;YAC9D,IAAI,CAAC,IAAI,CACP,UAAU,EACV,sCAAsC,kBAAkB,CACtD,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CACxB,EAAE,CACJ,CAAC;QACJ,CAAC;aAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/engine/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -155,8 +155,13 @@ type TransportHandlers = {
|
|
|
155
155
|
declare class Transport {
|
|
156
156
|
private socket?;
|
|
157
157
|
private handlers;
|
|
158
|
+
private reconnectAttempts;
|
|
159
|
+
private maxReconnectAttempts;
|
|
160
|
+
private isExplicitlyClosed;
|
|
161
|
+
private url?;
|
|
158
162
|
constructor(handlers: TransportHandlers);
|
|
159
163
|
connect(url: string): void;
|
|
164
|
+
private attemptReconnect;
|
|
160
165
|
send(payload: ISocketMessage): void;
|
|
161
166
|
close(): void;
|
|
162
167
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -155,8 +155,13 @@ type TransportHandlers = {
|
|
|
155
155
|
declare class Transport {
|
|
156
156
|
private socket?;
|
|
157
157
|
private handlers;
|
|
158
|
+
private reconnectAttempts;
|
|
159
|
+
private maxReconnectAttempts;
|
|
160
|
+
private isExplicitlyClosed;
|
|
161
|
+
private url?;
|
|
158
162
|
constructor(handlers: TransportHandlers);
|
|
159
163
|
connect(url: string): void;
|
|
164
|
+
private attemptReconnect;
|
|
160
165
|
send(payload: ISocketMessage): void;
|
|
161
166
|
close(): void;
|
|
162
167
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,eAAe,CAAC;AAE9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,477 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
var nacl__default = /*#__PURE__*/_interopDefault(nacl);
|
|
10
|
-
var QRCode__default = /*#__PURE__*/_interopDefault(QRCode);
|
|
11
|
-
|
|
12
|
-
// src/utilities/crypto.ts
|
|
13
|
-
var CryptoService = class {
|
|
14
|
-
generateSymmetricKey() {
|
|
15
|
-
const key = nacl__default.default.randomBytes(32);
|
|
16
|
-
return tweetnaclUtil.encodeBase64(key);
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Encrypt with symmetric key (secret-key encryption)
|
|
20
|
-
* Use this when both parties share the same secret key
|
|
21
|
-
* @param plaintext - Message to encrypt
|
|
22
|
-
* @param keyString - Symmetric key (base64)
|
|
23
|
-
* @returns Encrypted message with nonce
|
|
24
|
-
*/
|
|
25
|
-
encryptSymmetric({
|
|
26
|
-
plaintext,
|
|
27
|
-
keyString
|
|
28
|
-
}) {
|
|
29
|
-
const key = tweetnaclUtil.decodeBase64(keyString);
|
|
30
|
-
const nonce = nacl__default.default.randomBytes(24);
|
|
31
|
-
const messageBytes = new TextEncoder().encode(plaintext);
|
|
32
|
-
const ciphertext = nacl__default.default.secretbox(messageBytes, nonce, key);
|
|
33
|
-
return {
|
|
34
|
-
cipher: tweetnaclUtil.encodeBase64(ciphertext),
|
|
35
|
-
nonce: tweetnaclUtil.encodeBase64(nonce)
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Decrypt with symmetric key
|
|
40
|
-
* @param encrypted - Encrypted message with nonce
|
|
41
|
-
* @param keyString - Symmetric key (base64)
|
|
42
|
-
* @returns Decrypted plaintext
|
|
43
|
-
*/
|
|
44
|
-
decryptSymmetric({
|
|
45
|
-
encrypted,
|
|
46
|
-
keyString
|
|
47
|
-
}) {
|
|
48
|
-
try {
|
|
49
|
-
const key = tweetnaclUtil.decodeBase64(keyString);
|
|
50
|
-
const ciphertextBytes = tweetnaclUtil.decodeBase64(encrypted.cipher);
|
|
51
|
-
const nonceBytes = tweetnaclUtil.decodeBase64(encrypted.nonce);
|
|
52
|
-
const decrypted = nacl__default.default.secretbox.open(ciphertextBytes, nonceBytes, key);
|
|
53
|
-
if (!decrypted) {
|
|
54
|
-
throw new Error("Decryption failed - invalid key or corrupted data");
|
|
55
|
-
}
|
|
56
|
-
const decoded = new TextDecoder().decode(decrypted);
|
|
57
|
-
return decoded;
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error("Decryption failed", error);
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
var crypto_default = CryptoService;
|
|
65
|
-
|
|
66
|
-
// src/utilities/storage.ts
|
|
67
|
-
var AuthStorage = class {
|
|
68
|
-
constructor() {
|
|
69
|
-
this.prefix = "pelican_auth_";
|
|
70
|
-
this.defaultTTL = 5 * 60 * 1e3;
|
|
71
|
-
// 5 minutes
|
|
72
|
-
this.memoryCache = /* @__PURE__ */ new Map();
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Store auth session with automatic cleanup
|
|
76
|
-
*/
|
|
77
|
-
set(key, value, options = {}) {
|
|
78
|
-
const { ttlMs = this.defaultTTL, useSessionStorage = true } = options;
|
|
79
|
-
const expiresAt = Date.now() + ttlMs;
|
|
80
|
-
const data = { value, expiresAt };
|
|
81
|
-
if (useSessionStorage) {
|
|
82
|
-
try {
|
|
83
|
-
sessionStorage.setItem(`${this.prefix}${key}`, JSON.stringify(data));
|
|
84
|
-
} catch (error) {
|
|
85
|
-
console.warn("SessionStorage unavailable, using memory:", error);
|
|
86
|
-
this.setMemory(key, data);
|
|
87
|
-
}
|
|
88
|
-
} else {
|
|
89
|
-
this.setMemory(key, data);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Get stored value if not expired
|
|
94
|
-
*/
|
|
95
|
-
get(key) {
|
|
96
|
-
try {
|
|
97
|
-
const stored = sessionStorage.getItem(`${this.prefix}${key}`);
|
|
98
|
-
if (stored) {
|
|
99
|
-
const data = JSON.parse(stored);
|
|
100
|
-
if (Date.now() > data.expiresAt) {
|
|
101
|
-
this.remove(key);
|
|
102
|
-
return null;
|
|
103
|
-
}
|
|
104
|
-
return data.value;
|
|
105
|
-
}
|
|
106
|
-
} catch (error) {
|
|
107
|
-
}
|
|
108
|
-
return this.getMemory(key);
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Remove specific key
|
|
112
|
-
*/
|
|
113
|
-
remove(key) {
|
|
114
|
-
try {
|
|
115
|
-
sessionStorage.removeItem(`${this.prefix}${key}`);
|
|
116
|
-
} catch (error) {
|
|
117
|
-
}
|
|
118
|
-
this.memoryCache.delete(key);
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Clear all auth data
|
|
122
|
-
*/
|
|
123
|
-
clear() {
|
|
124
|
-
try {
|
|
125
|
-
Object.keys(sessionStorage).forEach((key) => {
|
|
126
|
-
if (key.startsWith(this.prefix)) {
|
|
127
|
-
sessionStorage.removeItem(key);
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
} catch (error) {
|
|
131
|
-
}
|
|
132
|
-
this.memoryCache.clear();
|
|
133
|
-
}
|
|
134
|
-
// ========================================
|
|
135
|
-
// Memory cache helpers
|
|
136
|
-
// ========================================
|
|
137
|
-
setMemory(key, data) {
|
|
138
|
-
this.memoryCache.set(key, data);
|
|
139
|
-
const ttl = data.expiresAt - Date.now();
|
|
140
|
-
setTimeout(() => {
|
|
141
|
-
this.memoryCache.delete(key);
|
|
142
|
-
}, ttl);
|
|
143
|
-
}
|
|
144
|
-
getMemory(key) {
|
|
145
|
-
const data = this.memoryCache.get(key);
|
|
146
|
-
if (!data) return null;
|
|
147
|
-
if (Date.now() > data.expiresAt) {
|
|
148
|
-
this.memoryCache.delete(key);
|
|
149
|
-
return null;
|
|
150
|
-
}
|
|
151
|
-
return data.value;
|
|
152
|
-
}
|
|
153
|
-
};
|
|
154
|
-
var storage = new AuthStorage();
|
|
155
|
-
var storeAuthSession = (sessionId, sessionKey, ttlMs) => {
|
|
156
|
-
storage.set("session", { sessionId, sessionKey }, { ttlMs });
|
|
157
|
-
};
|
|
158
|
-
var getAuthSession = () => {
|
|
159
|
-
return storage.get("session");
|
|
160
|
-
};
|
|
161
|
-
var clearAuthSession = () => {
|
|
162
|
-
storage.remove("session");
|
|
163
|
-
};
|
|
164
|
-
var clearAllAuthData = () => {
|
|
165
|
-
storage.clear();
|
|
166
|
-
};
|
|
167
|
-
|
|
168
|
-
// src/utilities/stateMachine.ts
|
|
169
|
-
var StateMachine = class {
|
|
170
|
-
constructor() {
|
|
171
|
-
this.state = "idle";
|
|
172
|
-
this.listeners = /* @__PURE__ */ new Set();
|
|
173
|
-
}
|
|
174
|
-
get current() {
|
|
175
|
-
return this.state;
|
|
176
|
-
}
|
|
177
|
-
transition(next) {
|
|
178
|
-
this.state = next;
|
|
179
|
-
this.listeners.forEach((l) => l(next));
|
|
180
|
-
}
|
|
181
|
-
subscribe(fn) {
|
|
182
|
-
this.listeners.add(fn);
|
|
183
|
-
return () => this.listeners.delete(fn);
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
// src/utilities/transport.ts
|
|
188
|
-
var Transport = class {
|
|
189
|
-
constructor(handlers) {
|
|
190
|
-
this.handlers = handlers;
|
|
191
|
-
}
|
|
192
|
-
connect(url) {
|
|
193
|
-
this.socket = new WebSocket(url);
|
|
194
|
-
this.socket.onopen = () => this.handlers.onOpen?.();
|
|
195
|
-
this.socket.onmessage = (e) => this.handlers.onMessage?.(e.data);
|
|
196
|
-
this.socket.onerror = (e) => this.handlers.onError?.(e);
|
|
197
|
-
this.socket.onclose = (e) => this.handlers.onClose?.(e);
|
|
198
|
-
}
|
|
199
|
-
send(payload) {
|
|
200
|
-
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
201
|
-
this.socket.send(JSON.stringify(payload));
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
close() {
|
|
205
|
-
this.socket?.close();
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
// src/constants.ts
|
|
210
|
-
var BASEURL = "http://localhost:8080";
|
|
211
|
-
|
|
212
|
-
// src/engine/engine.ts
|
|
213
|
-
var PelicanAuthentication = class {
|
|
214
|
-
constructor(config) {
|
|
215
|
-
this.crypto = new crypto_default();
|
|
216
|
-
this.stateMachine = new StateMachine();
|
|
217
|
-
this.sessionId = "";
|
|
218
|
-
this.sessionKey = null;
|
|
219
|
-
this.listeners = {};
|
|
220
|
-
if (!config.publicKey) throw new Error("Missing publicKey");
|
|
221
|
-
if (!config.projectId) throw new Error("Missing projectId");
|
|
222
|
-
if (!config.authType) throw new Error("Missing authType");
|
|
223
|
-
this.config = {
|
|
224
|
-
continuousMode: false,
|
|
225
|
-
forceQRCode: false,
|
|
226
|
-
...config
|
|
227
|
-
};
|
|
228
|
-
this.stateMachine.subscribe((s) => this.emit("state", s));
|
|
229
|
-
this.attachVisibilityRecovery();
|
|
230
|
-
}
|
|
231
|
-
/* -------------------- public API -------------------- */
|
|
232
|
-
/**
|
|
233
|
-
* Subscribe to SDK events (qr, deeplink, success, error, state)
|
|
234
|
-
* @returns Unsubscribe function
|
|
235
|
-
*/
|
|
236
|
-
on(event, cb) {
|
|
237
|
-
var _a;
|
|
238
|
-
(_a = this.listeners)[event] ?? (_a[event] = /* @__PURE__ */ new Set());
|
|
239
|
-
this.listeners[event].add(cb);
|
|
240
|
-
return () => this.listeners[event].delete(cb);
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Initializes the authentication flow.
|
|
244
|
-
* Fetches a relay, establishes a WebSocket, and generates the E2EE session key.
|
|
245
|
-
*/
|
|
246
|
-
async start() {
|
|
247
|
-
if (this.stateMachine.current !== "idle") return;
|
|
248
|
-
this.resetSession();
|
|
249
|
-
this.stateMachine.transition("initializing");
|
|
250
|
-
try {
|
|
251
|
-
const relay = await this.fetchRelayUrl();
|
|
252
|
-
this.sessionKey = this.crypto.generateSymmetricKey();
|
|
253
|
-
this.sessionId = crypto.randomUUID() + crypto.randomUUID();
|
|
254
|
-
this.transport = new Transport({
|
|
255
|
-
onOpen: () => {
|
|
256
|
-
this.transport.send({
|
|
257
|
-
type: "register",
|
|
258
|
-
sessionID: this.sessionId,
|
|
259
|
-
...this.config
|
|
260
|
-
});
|
|
261
|
-
this.stateMachine.transition("awaiting-pair");
|
|
262
|
-
},
|
|
263
|
-
onMessage: (msg) => this.handleMessage(msg),
|
|
264
|
-
onError: () => this.fail(new Error("WebSocket connection failed"))
|
|
265
|
-
});
|
|
266
|
-
this.transport.connect(relay);
|
|
267
|
-
await this.emitEntryPoint();
|
|
268
|
-
} catch (err) {
|
|
269
|
-
this.fail(err instanceof Error ? err : new Error("Start failed"));
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Manually stops the authentication process and closes connections.
|
|
274
|
-
*/
|
|
275
|
-
stop() {
|
|
276
|
-
this.terminate(false);
|
|
277
|
-
}
|
|
278
|
-
/* -------------------- internals -------------------- */
|
|
279
|
-
/** Fetches the WebSocket Relay URL from the backend */
|
|
280
|
-
async fetchRelayUrl() {
|
|
281
|
-
const { publicKey, projectId, authType } = this.config;
|
|
282
|
-
const res = await fetch(
|
|
283
|
-
`${BASEURL}/relay?public_key=${publicKey}&auth_type=${authType}&project_id=${projectId}`
|
|
284
|
-
);
|
|
285
|
-
if (!res.ok) {
|
|
286
|
-
throw new Error("Failed to fetch relay URL");
|
|
287
|
-
}
|
|
288
|
-
const json = await res.json();
|
|
289
|
-
return json.relay_url;
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Decides whether to show a QR code (Desktop) or a Deep Link (Mobile).
|
|
293
|
-
*/
|
|
294
|
-
async emitEntryPoint() {
|
|
295
|
-
const payload = {
|
|
296
|
-
sessionID: this.sessionId,
|
|
297
|
-
sessionKey: this.sessionKey,
|
|
298
|
-
publicKey: this.config.publicKey,
|
|
299
|
-
authType: this.config.authType,
|
|
300
|
-
projectId: this.config.projectId,
|
|
301
|
-
url: window.location.href
|
|
302
|
-
};
|
|
303
|
-
const shouldUseQR = this.config.forceQRCode || !/Android|iPhone|iPad/i.test(navigator.userAgent);
|
|
304
|
-
if (!shouldUseQR && this.sessionKey) {
|
|
305
|
-
storeAuthSession(this.sessionId, this.sessionKey, 5 * 6e4);
|
|
306
|
-
this.emit(
|
|
307
|
-
"deeplink",
|
|
308
|
-
`pelicanvault://auth/deep-link?data=${encodeURIComponent(
|
|
309
|
-
JSON.stringify(payload)
|
|
310
|
-
)}`
|
|
311
|
-
);
|
|
312
|
-
} else {
|
|
313
|
-
const qr = await QRCode__default.default.toDataURL(JSON.stringify(payload));
|
|
314
|
-
this.emit("qr", qr);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
/** Main WebSocket message router */
|
|
318
|
-
handleMessage(msg) {
|
|
319
|
-
console.log(msg);
|
|
320
|
-
switch (msg.type) {
|
|
321
|
-
case "paired":
|
|
322
|
-
console.log("Paired");
|
|
323
|
-
this.stateMachine.transition("paired");
|
|
324
|
-
this.transport.send({
|
|
325
|
-
type: "authenticate",
|
|
326
|
-
sessionID: this.sessionId,
|
|
327
|
-
...this.config,
|
|
328
|
-
url: window.location.href
|
|
329
|
-
});
|
|
330
|
-
return;
|
|
331
|
-
case "phone-auth-success":
|
|
332
|
-
this.handleAuthSuccess(msg);
|
|
333
|
-
return;
|
|
334
|
-
case "phone-terminated":
|
|
335
|
-
this.fail(new Error("Authenticating device terminated the connection"));
|
|
336
|
-
this.restartIfContinuous();
|
|
337
|
-
return;
|
|
338
|
-
case "confirmed":
|
|
339
|
-
this.terminate(true);
|
|
340
|
-
this.restartIfContinuous();
|
|
341
|
-
return;
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
/**
|
|
345
|
-
* Decrypts the identity payload received from the phone using the session key.
|
|
346
|
-
*/
|
|
347
|
-
handleAuthSuccess(msg) {
|
|
348
|
-
if (!this.sessionKey || !msg.cipher || !msg.nonce) {
|
|
349
|
-
this.fail(new Error("Invalid authentication payload"));
|
|
350
|
-
this.restartIfContinuous();
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
try {
|
|
354
|
-
const decrypted = this.crypto.decryptSymmetric({
|
|
355
|
-
encrypted: { cipher: msg.cipher, nonce: msg.nonce },
|
|
356
|
-
keyString: this.sessionKey
|
|
357
|
-
});
|
|
358
|
-
if (!decrypted) {
|
|
359
|
-
this.fail(new Error("Invalid authentication data"));
|
|
360
|
-
this.restartIfContinuous();
|
|
361
|
-
return;
|
|
362
|
-
}
|
|
363
|
-
const result = JSON.parse(decrypted);
|
|
364
|
-
this.emit("success", result);
|
|
365
|
-
this.stateMachine.transition("authenticated");
|
|
366
|
-
this.transport?.send({
|
|
367
|
-
type: "confirm",
|
|
368
|
-
sessionID: this.sessionId
|
|
369
|
-
});
|
|
370
|
-
} catch {
|
|
371
|
-
this.fail(new Error("Failed to decrypt authentication data"));
|
|
372
|
-
this.restartIfContinuous();
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Logic to handle users returning to the browser tab after using the mobile app.
|
|
377
|
-
* Checks the server for a completed session that might have finished while in background.
|
|
378
|
-
*/
|
|
379
|
-
async getCachedEntry(cached) {
|
|
380
|
-
try {
|
|
381
|
-
const res = await fetch(
|
|
382
|
-
`${BASEURL}/session?session_id=${cached.sessionId}`
|
|
383
|
-
);
|
|
384
|
-
if (!res.ok) throw new Error("Invalid session");
|
|
385
|
-
const data = await res.json();
|
|
386
|
-
const decrypted = this.crypto.decryptSymmetric({
|
|
387
|
-
encrypted: { cipher: data.cipher, nonce: data.nonce },
|
|
388
|
-
keyString: cached.sessionKey
|
|
389
|
-
});
|
|
390
|
-
if (!decrypted) {
|
|
391
|
-
this.fail(new Error("Invalid session data"));
|
|
392
|
-
this.restartIfContinuous();
|
|
393
|
-
return;
|
|
394
|
-
}
|
|
395
|
-
const result = JSON.parse(decrypted);
|
|
396
|
-
this.emit("success", result);
|
|
397
|
-
clearAuthSession();
|
|
398
|
-
} catch {
|
|
399
|
-
this.fail(new Error("Session recovery failed"));
|
|
400
|
-
this.restartIfContinuous();
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
attachVisibilityRecovery() {
|
|
404
|
-
this.visibilityHandler = async () => {
|
|
405
|
-
if (document.visibilityState !== "visible") return;
|
|
406
|
-
const cached = getAuthSession();
|
|
407
|
-
if (!cached) return;
|
|
408
|
-
await this.getCachedEntry(cached);
|
|
409
|
-
};
|
|
410
|
-
document.addEventListener("visibilitychange", this.visibilityHandler);
|
|
411
|
-
}
|
|
412
|
-
detachVisibilityRecovery() {
|
|
413
|
-
if (this.visibilityHandler) {
|
|
414
|
-
document.removeEventListener("visibilitychange", this.visibilityHandler);
|
|
415
|
-
this.visibilityHandler = void 0;
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
/** Cleans up the current session state */
|
|
419
|
-
terminate(success) {
|
|
420
|
-
if (!this.transport) return;
|
|
421
|
-
if (!success) {
|
|
422
|
-
this.transport?.send({
|
|
423
|
-
type: "client-terminated",
|
|
424
|
-
sessionID: this.sessionId,
|
|
425
|
-
projectId: this.config.projectId,
|
|
426
|
-
publicKey: this.config.publicKey,
|
|
427
|
-
authType: this.config.authType
|
|
428
|
-
});
|
|
429
|
-
}
|
|
430
|
-
setTimeout(() => {
|
|
431
|
-
this.transport?.close();
|
|
432
|
-
}, 150);
|
|
433
|
-
clearAuthSession();
|
|
434
|
-
this.resetSession();
|
|
435
|
-
if (!this.config.continuousMode) {
|
|
436
|
-
this.detachVisibilityRecovery();
|
|
437
|
-
}
|
|
438
|
-
this.stateMachine.transition(success ? "confirmed" : "terminated");
|
|
439
|
-
}
|
|
440
|
-
restartIfContinuous() {
|
|
441
|
-
if (!this.config.continuousMode) return;
|
|
442
|
-
this.terminate(false);
|
|
443
|
-
this.stateMachine.transition("idle");
|
|
444
|
-
setTimeout(() => {
|
|
445
|
-
this.start();
|
|
446
|
-
}, 150);
|
|
447
|
-
}
|
|
448
|
-
resetSession() {
|
|
449
|
-
this.sessionId = "";
|
|
450
|
-
this.sessionKey = null;
|
|
451
|
-
}
|
|
452
|
-
/** Completely destroys the instance and removes all listeners */
|
|
453
|
-
destroy() {
|
|
454
|
-
this.detachVisibilityRecovery();
|
|
455
|
-
this.transport?.close();
|
|
456
|
-
this.listeners = {};
|
|
457
|
-
}
|
|
458
|
-
emit(event, payload) {
|
|
459
|
-
this.listeners[event]?.forEach((cb) => cb(payload));
|
|
460
|
-
}
|
|
461
|
-
fail(err) {
|
|
462
|
-
this.emit("error", err);
|
|
463
|
-
this.stateMachine.transition("error");
|
|
464
|
-
}
|
|
465
|
-
};
|
|
466
|
-
|
|
467
|
-
exports.BASEURL = BASEURL;
|
|
468
|
-
exports.CryptoService = CryptoService;
|
|
469
|
-
exports.PelicanAuthentication = PelicanAuthentication;
|
|
470
|
-
exports.StateMachine = StateMachine;
|
|
471
|
-
exports.Transport = Transport;
|
|
472
|
-
exports.clearAllAuthData = clearAllAuthData;
|
|
473
|
-
exports.clearAuthSession = clearAuthSession;
|
|
474
|
-
exports.getAuthSession = getAuthSession;
|
|
475
|
-
exports.storeAuthSession = storeAuthSession;
|
|
476
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
export * from "./types/types";
|
|
2
|
+
export { PelicanAuthentication } from "./engine/engine";
|
|
3
|
+
export { CryptoService } from "./utilities/crypto";
|
|
4
|
+
export { StateMachine } from "./utilities/stateMachine";
|
|
5
|
+
export { Transport } from "./utilities/transport";
|
|
6
|
+
export * from "./utilities/storage";
|
|
7
|
+
export { BASEURL } from "./constants";
|
|
477
8
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utilities/crypto.ts","../src/utilities/storage.ts","../src/utilities/stateMachine.ts","../src/utilities/transport.ts","../src/constants.ts","../src/engine/engine.ts"],"names":["nacl","encodeBase64","decodeBase64","QRCode"],"mappings":"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","file":"index.js","sourcesContent":["import nacl from \"tweetnacl\";\nimport { decodeBase64, encodeBase64 } from \"tweetnacl-util\";\n\ninterface EncryptedMessage {\n cipher: string; // Base64 encoded\n nonce: string; // Base64 encoded\n}\n\nexport class CryptoService {\n generateSymmetricKey(): string {\n const key = nacl.randomBytes(32);\n return encodeBase64(key);\n }\n\n /**\n * Encrypt with symmetric key (secret-key encryption)\n * Use this when both parties share the same secret key\n * @param plaintext - Message to encrypt\n * @param keyString - Symmetric key (base64)\n * @returns Encrypted message with nonce\n */\n encryptSymmetric({\n plaintext,\n keyString,\n }: {\n plaintext: string;\n keyString: string;\n }): EncryptedMessage {\n const key = decodeBase64(keyString);\n const nonce = nacl.randomBytes(24);\n\n const messageBytes = new TextEncoder().encode(plaintext);\n\n const ciphertext = nacl.secretbox(messageBytes, nonce, key);\n\n return {\n cipher: encodeBase64(ciphertext),\n nonce: encodeBase64(nonce),\n };\n }\n\n /**\n * Decrypt with symmetric key\n * @param encrypted - Encrypted message with nonce\n * @param keyString - Symmetric key (base64)\n * @returns Decrypted plaintext\n */\n decryptSymmetric({\n encrypted,\n keyString,\n }: {\n encrypted: EncryptedMessage;\n keyString: string;\n }): string | null {\n try {\n const key = decodeBase64(keyString);\n const ciphertextBytes = decodeBase64(encrypted.cipher);\n const nonceBytes = decodeBase64(encrypted.nonce);\n\n const decrypted = nacl.secretbox.open(ciphertextBytes, nonceBytes, key);\n\n if (!decrypted) {\n throw new Error(\"Decryption failed - invalid key or corrupted data\");\n }\n\n const decoded = new TextDecoder().decode(decrypted);\n return decoded;\n } catch (error) {\n console.error(\"Decryption failed\", error);\n return null;\n }\n }\n}\n\nexport default CryptoService;\nexport type { EncryptedMessage };\n","// hybridStorage.ts\n/**\n * Hybrid storage: Try sessionStorage first, fallback to memory\n * Best of both worlds - survives page refresh but auto-cleans\n */\n\ninterface StorageOptions {\n ttlMs?: number;\n useSessionStorage?: boolean;\n}\n\nclass AuthStorage {\n private readonly prefix = \"pelican_auth_\";\n private readonly defaultTTL = 5 * 60 * 1000; // 5 minutes\n private memoryCache: Map<string, { value: any; expiresAt: number }> =\n new Map();\n\n /**\n * Store auth session with automatic cleanup\n */\n set(key: string, value: any, options: StorageOptions = {}): void {\n const { ttlMs = this.defaultTTL, useSessionStorage = true } = options;\n\n const expiresAt = Date.now() + ttlMs;\n const data = { value, expiresAt };\n\n // Try sessionStorage first\n if (useSessionStorage) {\n try {\n sessionStorage.setItem(`${this.prefix}${key}`, JSON.stringify(data));\n } catch (error) {\n console.warn(\"SessionStorage unavailable, using memory:\", error);\n this.setMemory(key, data);\n }\n } else {\n this.setMemory(key, data);\n }\n }\n\n /**\n * Get stored value if not expired\n */\n get(key: string): any | null {\n // Try sessionStorage first\n try {\n const stored = sessionStorage.getItem(`${this.prefix}${key}`);\n if (stored) {\n const data = JSON.parse(stored);\n\n // Check expiration\n if (Date.now() > data.expiresAt) {\n this.remove(key);\n return null;\n }\n\n return data.value;\n }\n } catch (error) {\n // Fallback to memory\n }\n\n // Try memory cache\n return this.getMemory(key);\n }\n\n /**\n * Remove specific key\n */\n remove(key: string): void {\n try {\n sessionStorage.removeItem(`${this.prefix}${key}`);\n } catch (error) {\n // Ignore\n }\n this.memoryCache.delete(key);\n }\n\n /**\n * Clear all auth data\n */\n clear(): void {\n // Clear sessionStorage\n try {\n Object.keys(sessionStorage).forEach((key) => {\n if (key.startsWith(this.prefix)) {\n sessionStorage.removeItem(key);\n }\n });\n } catch (error) {\n // Ignore\n }\n\n // Clear memory\n this.memoryCache.clear();\n }\n\n // ========================================\n // Memory cache helpers\n // ========================================\n\n private setMemory(\n key: string,\n data: { value: any; expiresAt: number }\n ): void {\n this.memoryCache.set(key, data);\n\n // Schedule cleanup\n const ttl = data.expiresAt - Date.now();\n setTimeout(() => {\n this.memoryCache.delete(key);\n }, ttl);\n }\n\n private getMemory(key: string): any | null {\n const data = this.memoryCache.get(key);\n if (!data) return null;\n\n if (Date.now() > data.expiresAt) {\n this.memoryCache.delete(key);\n return null;\n }\n\n return data.value;\n }\n}\n\n// Singleton instance\nconst storage = new AuthStorage();\n\n// ========================================\n// Convenience functions for auth flow\n// ========================================\n\nexport interface AuthSession {\n sessionId: string;\n sessionKey: string;\n}\n\nexport const storeAuthSession = (\n sessionId: string,\n sessionKey: string,\n ttlMs?: number\n): void => {\n storage.set(\"session\", { sessionId, sessionKey }, { ttlMs });\n};\n\nexport const getAuthSession = (): AuthSession | null => {\n return storage.get(\"session\");\n};\n\nexport const clearAuthSession = (): void => {\n storage.remove(\"session\");\n};\n\nexport const clearAllAuthData = (): void => {\n storage.clear();\n};\n\nexport default storage;\n","import type { PelicanAuthState } from \"../types/types\";\n\nexport class StateMachine {\n private state: PelicanAuthState = \"idle\";\n private listeners = new Set<(s: PelicanAuthState) => void>();\n\n get current() {\n return this.state;\n }\n\n transition(next: PelicanAuthState) {\n this.state = next;\n this.listeners.forEach((l) => l(next));\n }\n\n subscribe(fn: (s: PelicanAuthState) => void) {\n this.listeners.add(fn);\n return () => this.listeners.delete(fn);\n }\n}\n","import { ISocketMessage } from \"../types/types\";\n\ntype TransportHandlers = {\n onOpen?: () => void;\n onMessage?: (msg: ISocketMessage) => void;\n onError?: (err: Event) => void;\n onClose?: (ev: CloseEvent) => void;\n};\n\ninterface PelicanMessageEvent extends MessageEvent {\n data: ISocketMessage;\n}\nexport class Transport {\n private socket?: WebSocket;\n private handlers: TransportHandlers;\n\n constructor(handlers: TransportHandlers) {\n this.handlers = handlers;\n }\n\n connect(url: string) {\n this.socket = new WebSocket(url);\n\n this.socket.onopen = () => this.handlers.onOpen?.();\n this.socket.onmessage = (e: PelicanMessageEvent) =>\n this.handlers.onMessage?.(e.data);\n this.socket.onerror = (e: Event) => this.handlers.onError?.(e);\n this.socket.onclose = (e: CloseEvent) => this.handlers.onClose?.(e);\n }\n\n send(payload: ISocketMessage) {\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.socket.send(JSON.stringify(payload));\n }\n }\n\n close() {\n this.socket?.close();\n }\n}\n","export const BASEURL = \"http://localhost:8080\";\n","import CryptoService from \"../utilities/crypto\";\nimport QRCode from \"qrcode\";\nimport {\n PelicanAuthConfig,\n PelicanAuthEventMap,\n ISocketMessage,\n IdentityResult,\n} from \"../types/types\";\nimport {\n storeAuthSession,\n getAuthSession,\n clearAuthSession,\n AuthSession,\n} from \"../utilities/storage\";\nimport { StateMachine } from \"../utilities/stateMachine\";\nimport { Transport } from \"../utilities/transport\";\n\nimport { BASEURL } from \"../constants\";\n\ntype Listener<T> = (payload: T) => void;\n\n/**\n * PelicanAuth SDK\n * Handles cross-device authentication via WebSockets and E2EE (End-to-End Encryption).\n */\nexport class PelicanAuthentication {\n private readonly crypto = new CryptoService();\n private readonly stateMachine = new StateMachine();\n\n private transport?: Transport;\n private sessionId = \"\";\n private sessionKey: string | null = null;\n\n private visibilityHandler?: () => void;\n\n private listeners: {\n [K in keyof PelicanAuthEventMap]?: Set<Listener<any>>;\n } = {};\n\n private readonly config: Required<PelicanAuthConfig>;\n\n constructor(config: PelicanAuthConfig) {\n if (!config.publicKey) throw new Error(\"Missing publicKey\");\n if (!config.projectId) throw new Error(\"Missing projectId\");\n if (!config.authType) throw new Error(\"Missing authType\");\n\n this.config = {\n continuousMode: false,\n forceQRCode: false,\n ...config,\n };\n\n // Sync internal state machine changes with the 'state' event\n this.stateMachine.subscribe((s) => this.emit(\"state\", s));\n this.attachVisibilityRecovery();\n }\n\n /* -------------------- public API -------------------- */\n\n /**\n * Subscribe to SDK events (qr, deeplink, success, error, state)\n * @returns Unsubscribe function\n */\n on<K extends keyof PelicanAuthEventMap>(\n event: K,\n cb: Listener<PelicanAuthEventMap[K]>\n ) {\n this.listeners[event] ??= new Set();\n this.listeners[event]!.add(cb);\n return () => this.listeners[event]!.delete(cb);\n }\n\n /**\n * Initializes the authentication flow.\n * Fetches a relay, establishes a WebSocket, and generates the E2EE session key.\n */\n async start() {\n if (this.stateMachine.current !== \"idle\") return;\n\n this.resetSession();\n this.stateMachine.transition(\"initializing\");\n\n try {\n const relay = await this.fetchRelayUrl();\n\n // Generate a fresh symmetric key for this specific session\n this.sessionKey = this.crypto.generateSymmetricKey();\n this.sessionId = crypto.randomUUID() + crypto.randomUUID();\n\n this.transport = new Transport({\n onOpen: () => {\n // Register this browser session with the relay\n this.transport!.send({\n type: \"register\",\n sessionID: this.sessionId,\n ...this.config,\n });\n this.stateMachine.transition(\"awaiting-pair\");\n },\n onMessage: (msg: ISocketMessage) => this.handleMessage(msg),\n onError: () => this.fail(new Error(\"WebSocket connection failed\")),\n });\n\n this.transport.connect(relay);\n await this.emitEntryPoint();\n } catch (err) {\n this.fail(err instanceof Error ? err : new Error(\"Start failed\"));\n }\n }\n\n /**\n * Manually stops the authentication process and closes connections.\n */\n stop() {\n this.terminate(false);\n }\n\n /* -------------------- internals -------------------- */\n\n /** Fetches the WebSocket Relay URL from the backend */\n private async fetchRelayUrl(): Promise<string> {\n const { publicKey, projectId, authType } = this.config;\n const res = await fetch(\n `${BASEURL}/relay?public_key=${publicKey}&auth_type=${authType}&project_id=${projectId}`\n );\n\n if (!res.ok) {\n throw new Error(\"Failed to fetch relay URL\");\n }\n\n const json = await res.json();\n return json.relay_url;\n }\n\n /**\n * Decides whether to show a QR code (Desktop) or a Deep Link (Mobile).\n */\n private async emitEntryPoint() {\n const payload = {\n sessionID: this.sessionId,\n sessionKey: this.sessionKey,\n publicKey: this.config.publicKey,\n authType: this.config.authType,\n projectId: this.config.projectId,\n url: window.location.href,\n };\n\n const shouldUseQR =\n this.config.forceQRCode ||\n !/Android|iPhone|iPad/i.test(navigator.userAgent);\n\n if (!shouldUseQR && this.sessionKey) {\n // For mobile: Store session locally so we can recover when the user returns from the app\n storeAuthSession(this.sessionId, this.sessionKey, 5 * 60_000);\n this.emit(\n \"deeplink\",\n `pelicanvault://auth/deep-link?data=${encodeURIComponent(\n JSON.stringify(payload)\n )}`\n );\n } else {\n // For desktop: Generate a QR code for the mobile app to scan\n const qr = await QRCode.toDataURL(JSON.stringify(payload));\n this.emit(\"qr\", qr);\n }\n }\n\n /** Main WebSocket message router */\n private handleMessage(msg: ISocketMessage) {\n console.log(msg);\n\n switch (msg.type) {\n case \"paired\":\n console.log(\"Paired\");\n\n this.stateMachine.transition(\"paired\");\n this.transport!.send({\n type: \"authenticate\",\n sessionID: this.sessionId,\n ...this.config,\n url: window.location.href,\n });\n return;\n\n case \"phone-auth-success\":\n // Mobile device successfully authenticated and sent encrypted credentials\n this.handleAuthSuccess(msg);\n return;\n\n case \"phone-terminated\":\n this.fail(new Error(\"Authenticating device terminated the connection\"));\n this.restartIfContinuous();\n return;\n\n case \"confirmed\":\n // Handshake complete\n this.terminate(true);\n this.restartIfContinuous();\n return;\n }\n }\n\n /**\n * Decrypts the identity payload received from the phone using the session key.\n */\n private handleAuthSuccess(msg: ISocketMessage) {\n if (!this.sessionKey || !msg.cipher || !msg.nonce) {\n this.fail(new Error(\"Invalid authentication payload\"));\n this.restartIfContinuous();\n return;\n }\n\n try {\n const decrypted = this.crypto.decryptSymmetric({\n encrypted: { cipher: msg.cipher, nonce: msg.nonce },\n keyString: this.sessionKey,\n });\n\n if (!decrypted) {\n this.fail(new Error(\"Invalid authentication data\"));\n this.restartIfContinuous();\n return;\n }\n\n const result: IdentityResult = JSON.parse(decrypted);\n\n this.emit(\"success\", result);\n this.stateMachine.transition(\"authenticated\");\n\n // Signal to the relay/phone that we have received and decrypted the data\n this.transport?.send({\n type: \"confirm\",\n sessionID: this.sessionId,\n });\n } catch {\n this.fail(new Error(\"Failed to decrypt authentication data\"));\n this.restartIfContinuous();\n }\n }\n\n /**\n * Logic to handle users returning to the browser tab after using the mobile app.\n * Checks the server for a completed session that might have finished while in background.\n */\n\n private async getCachedEntry(cached: AuthSession) {\n try {\n const res = await fetch(\n `${BASEURL}/session?session_id=${cached.sessionId}`\n );\n\n if (!res.ok) throw new Error(\"Invalid session\");\n\n const data = await res.json();\n const decrypted = this.crypto.decryptSymmetric({\n encrypted: { cipher: data.cipher, nonce: data.nonce },\n keyString: cached.sessionKey,\n });\n\n if (!decrypted) {\n this.fail(new Error(\"Invalid session data\"));\n this.restartIfContinuous();\n return;\n }\n const result: IdentityResult = JSON.parse(decrypted);\n this.emit(\"success\", result);\n clearAuthSession();\n } catch {\n this.fail(new Error(\"Session recovery failed\"));\n this.restartIfContinuous();\n }\n }\n\n private attachVisibilityRecovery() {\n this.visibilityHandler = async () => {\n if (document.visibilityState !== \"visible\") return;\n\n const cached = getAuthSession();\n if (!cached) return;\n await this.getCachedEntry(cached);\n };\n\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n\n private detachVisibilityRecovery() {\n if (this.visibilityHandler) {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n this.visibilityHandler = undefined;\n }\n }\n\n /** Cleans up the current session state */\n private terminate(success: boolean) {\n if (!this.transport) return;\n if (!success) {\n this.transport?.send({\n type: \"client-terminated\",\n sessionID: this.sessionId,\n projectId: this.config.projectId,\n publicKey: this.config.publicKey,\n authType: this.config.authType,\n });\n }\n\n setTimeout(() => {\n this.transport?.close();\n }, 150);\n\n clearAuthSession();\n this.resetSession();\n\n if (!this.config.continuousMode) {\n this.detachVisibilityRecovery();\n }\n this.stateMachine.transition(success ? \"confirmed\" : \"terminated\");\n }\n\n private restartIfContinuous() {\n if (!this.config.continuousMode) return;\n this.terminate(false);\n this.stateMachine.transition(\"idle\");\n\n setTimeout(() => {\n this.start();\n }, 150);\n }\n\n private resetSession() {\n this.sessionId = \"\";\n this.sessionKey = null;\n }\n\n /** Completely destroys the instance and removes all listeners */\n destroy() {\n this.detachVisibilityRecovery();\n this.transport?.close();\n this.listeners = {};\n }\n\n private emit<K extends keyof PelicanAuthEventMap>(\n event: K,\n payload: PelicanAuthEventMap[K]\n ) {\n this.listeners[event]?.forEach((cb) => cb(payload));\n }\n\n private fail(err: Error) {\n this.emit(\"error\", err);\n this.stateMachine.transition(\"error\");\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,eAAe,CAAC;AAE9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGxD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClD,cAAc,qBAAqB,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.mjs
CHANGED
|
@@ -180,14 +180,47 @@ var StateMachine = class {
|
|
|
180
180
|
// src/utilities/transport.ts
|
|
181
181
|
var Transport = class {
|
|
182
182
|
constructor(handlers) {
|
|
183
|
+
this.reconnectAttempts = 0;
|
|
184
|
+
this.maxReconnectAttempts = 5;
|
|
185
|
+
this.isExplicitlyClosed = false;
|
|
183
186
|
this.handlers = handlers;
|
|
184
187
|
}
|
|
185
188
|
connect(url) {
|
|
189
|
+
this.url = url;
|
|
190
|
+
this.isExplicitlyClosed = false;
|
|
186
191
|
this.socket = new WebSocket(url);
|
|
187
|
-
this.socket.onopen = () =>
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
192
|
+
this.socket.onopen = () => {
|
|
193
|
+
this.reconnectAttempts = 0;
|
|
194
|
+
this.handlers.onOpen?.();
|
|
195
|
+
};
|
|
196
|
+
this.socket.onmessage = (e) => {
|
|
197
|
+
try {
|
|
198
|
+
const data = JSON.parse(e.data);
|
|
199
|
+
this.handlers.onMessage?.(data);
|
|
200
|
+
} catch (err) {
|
|
201
|
+
console.error("Failed to parse message", err);
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
this.socket.onerror = (e) => {
|
|
205
|
+
this.handlers.onError?.(e);
|
|
206
|
+
};
|
|
207
|
+
this.socket.onclose = (e) => {
|
|
208
|
+
this.handlers.onClose?.(e);
|
|
209
|
+
if (!this.isExplicitlyClosed) {
|
|
210
|
+
this.attemptReconnect();
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
attemptReconnect() {
|
|
215
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
216
|
+
console.error("\u274C Max reconnect attempts reached");
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
this.reconnectAttempts++;
|
|
220
|
+
const delay = Math.pow(2, this.reconnectAttempts) * 500;
|
|
221
|
+
setTimeout(() => {
|
|
222
|
+
if (this.url) this.connect(this.url);
|
|
223
|
+
}, delay);
|
|
191
224
|
}
|
|
192
225
|
send(payload) {
|
|
193
226
|
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
@@ -195,6 +228,7 @@ var Transport = class {
|
|
|
195
228
|
}
|
|
196
229
|
}
|
|
197
230
|
close() {
|
|
231
|
+
this.isExplicitlyClosed = true;
|
|
198
232
|
this.socket?.close();
|
|
199
233
|
}
|
|
200
234
|
};
|
|
@@ -303,16 +337,18 @@ var PelicanAuthentication = class {
|
|
|
303
337
|
)}`
|
|
304
338
|
);
|
|
305
339
|
} else {
|
|
306
|
-
const qr = await QRCode.toDataURL(JSON.stringify(payload)
|
|
340
|
+
const qr = await QRCode.toDataURL(JSON.stringify(payload), {
|
|
341
|
+
type: "image/png",
|
|
342
|
+
scale: 3,
|
|
343
|
+
color: { light: "#FFFFF5", dark: "#121212" }
|
|
344
|
+
});
|
|
307
345
|
this.emit("qr", qr);
|
|
308
346
|
}
|
|
309
347
|
}
|
|
310
348
|
/** Main WebSocket message router */
|
|
311
349
|
handleMessage(msg) {
|
|
312
|
-
console.log(msg);
|
|
313
350
|
switch (msg.type) {
|
|
314
351
|
case "paired":
|
|
315
|
-
console.log("Paired");
|
|
316
352
|
this.stateMachine.transition("paired");
|
|
317
353
|
this.transport.send({
|
|
318
354
|
type: "authenticate",
|
|
@@ -420,20 +456,17 @@ var PelicanAuthentication = class {
|
|
|
420
456
|
authType: this.config.authType
|
|
421
457
|
});
|
|
422
458
|
}
|
|
423
|
-
|
|
424
|
-
this.transport?.close();
|
|
425
|
-
}, 150);
|
|
459
|
+
this.transport?.close();
|
|
426
460
|
clearAuthSession();
|
|
427
461
|
this.resetSession();
|
|
428
462
|
if (!this.config.continuousMode) {
|
|
429
463
|
this.detachVisibilityRecovery();
|
|
430
464
|
}
|
|
431
|
-
this.stateMachine.transition(success ? "confirmed" : "
|
|
465
|
+
this.stateMachine.transition(success ? "confirmed" : "idle");
|
|
432
466
|
}
|
|
433
467
|
restartIfContinuous() {
|
|
434
|
-
if (!this.config.continuousMode) return;
|
|
435
|
-
this.terminate(false);
|
|
436
468
|
this.stateMachine.transition("idle");
|
|
469
|
+
if (!this.config.continuousMode) return;
|
|
437
470
|
setTimeout(() => {
|
|
438
471
|
this.start();
|
|
439
472
|
}, 150);
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utilities/crypto.ts","../src/utilities/storage.ts","../src/utilities/stateMachine.ts","../src/utilities/transport.ts","../src/constants.ts","../src/engine/engine.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import nacl from \"tweetnacl\";\nimport { decodeBase64, encodeBase64 } from \"tweetnacl-util\";\n\ninterface EncryptedMessage {\n cipher: string; // Base64 encoded\n nonce: string; // Base64 encoded\n}\n\nexport class CryptoService {\n generateSymmetricKey(): string {\n const key = nacl.randomBytes(32);\n return encodeBase64(key);\n }\n\n /**\n * Encrypt with symmetric key (secret-key encryption)\n * Use this when both parties share the same secret key\n * @param plaintext - Message to encrypt\n * @param keyString - Symmetric key (base64)\n * @returns Encrypted message with nonce\n */\n encryptSymmetric({\n plaintext,\n keyString,\n }: {\n plaintext: string;\n keyString: string;\n }): EncryptedMessage {\n const key = decodeBase64(keyString);\n const nonce = nacl.randomBytes(24);\n\n const messageBytes = new TextEncoder().encode(plaintext);\n\n const ciphertext = nacl.secretbox(messageBytes, nonce, key);\n\n return {\n cipher: encodeBase64(ciphertext),\n nonce: encodeBase64(nonce),\n };\n }\n\n /**\n * Decrypt with symmetric key\n * @param encrypted - Encrypted message with nonce\n * @param keyString - Symmetric key (base64)\n * @returns Decrypted plaintext\n */\n decryptSymmetric({\n encrypted,\n keyString,\n }: {\n encrypted: EncryptedMessage;\n keyString: string;\n }): string | null {\n try {\n const key = decodeBase64(keyString);\n const ciphertextBytes = decodeBase64(encrypted.cipher);\n const nonceBytes = decodeBase64(encrypted.nonce);\n\n const decrypted = nacl.secretbox.open(ciphertextBytes, nonceBytes, key);\n\n if (!decrypted) {\n throw new Error(\"Decryption failed - invalid key or corrupted data\");\n }\n\n const decoded = new TextDecoder().decode(decrypted);\n return decoded;\n } catch (error) {\n console.error(\"Decryption failed\", error);\n return null;\n }\n }\n}\n\nexport default CryptoService;\nexport type { EncryptedMessage };\n","// hybridStorage.ts\n/**\n * Hybrid storage: Try sessionStorage first, fallback to memory\n * Best of both worlds - survives page refresh but auto-cleans\n */\n\ninterface StorageOptions {\n ttlMs?: number;\n useSessionStorage?: boolean;\n}\n\nclass AuthStorage {\n private readonly prefix = \"pelican_auth_\";\n private readonly defaultTTL = 5 * 60 * 1000; // 5 minutes\n private memoryCache: Map<string, { value: any; expiresAt: number }> =\n new Map();\n\n /**\n * Store auth session with automatic cleanup\n */\n set(key: string, value: any, options: StorageOptions = {}): void {\n const { ttlMs = this.defaultTTL, useSessionStorage = true } = options;\n\n const expiresAt = Date.now() + ttlMs;\n const data = { value, expiresAt };\n\n // Try sessionStorage first\n if (useSessionStorage) {\n try {\n sessionStorage.setItem(`${this.prefix}${key}`, JSON.stringify(data));\n } catch (error) {\n console.warn(\"SessionStorage unavailable, using memory:\", error);\n this.setMemory(key, data);\n }\n } else {\n this.setMemory(key, data);\n }\n }\n\n /**\n * Get stored value if not expired\n */\n get(key: string): any | null {\n // Try sessionStorage first\n try {\n const stored = sessionStorage.getItem(`${this.prefix}${key}`);\n if (stored) {\n const data = JSON.parse(stored);\n\n // Check expiration\n if (Date.now() > data.expiresAt) {\n this.remove(key);\n return null;\n }\n\n return data.value;\n }\n } catch (error) {\n // Fallback to memory\n }\n\n // Try memory cache\n return this.getMemory(key);\n }\n\n /**\n * Remove specific key\n */\n remove(key: string): void {\n try {\n sessionStorage.removeItem(`${this.prefix}${key}`);\n } catch (error) {\n // Ignore\n }\n this.memoryCache.delete(key);\n }\n\n /**\n * Clear all auth data\n */\n clear(): void {\n // Clear sessionStorage\n try {\n Object.keys(sessionStorage).forEach((key) => {\n if (key.startsWith(this.prefix)) {\n sessionStorage.removeItem(key);\n }\n });\n } catch (error) {\n // Ignore\n }\n\n // Clear memory\n this.memoryCache.clear();\n }\n\n // ========================================\n // Memory cache helpers\n // ========================================\n\n private setMemory(\n key: string,\n data: { value: any; expiresAt: number }\n ): void {\n this.memoryCache.set(key, data);\n\n // Schedule cleanup\n const ttl = data.expiresAt - Date.now();\n setTimeout(() => {\n this.memoryCache.delete(key);\n }, ttl);\n }\n\n private getMemory(key: string): any | null {\n const data = this.memoryCache.get(key);\n if (!data) return null;\n\n if (Date.now() > data.expiresAt) {\n this.memoryCache.delete(key);\n return null;\n }\n\n return data.value;\n }\n}\n\n// Singleton instance\nconst storage = new AuthStorage();\n\n// ========================================\n// Convenience functions for auth flow\n// ========================================\n\nexport interface AuthSession {\n sessionId: string;\n sessionKey: string;\n}\n\nexport const storeAuthSession = (\n sessionId: string,\n sessionKey: string,\n ttlMs?: number\n): void => {\n storage.set(\"session\", { sessionId, sessionKey }, { ttlMs });\n};\n\nexport const getAuthSession = (): AuthSession | null => {\n return storage.get(\"session\");\n};\n\nexport const clearAuthSession = (): void => {\n storage.remove(\"session\");\n};\n\nexport const clearAllAuthData = (): void => {\n storage.clear();\n};\n\nexport default storage;\n","import type { PelicanAuthState } from \"../types/types\";\n\nexport class StateMachine {\n private state: PelicanAuthState = \"idle\";\n private listeners = new Set<(s: PelicanAuthState) => void>();\n\n get current() {\n return this.state;\n }\n\n transition(next: PelicanAuthState) {\n this.state = next;\n this.listeners.forEach((l) => l(next));\n }\n\n subscribe(fn: (s: PelicanAuthState) => void) {\n this.listeners.add(fn);\n return () => this.listeners.delete(fn);\n }\n}\n","import { ISocketMessage } from \"../types/types\";\n\ntype TransportHandlers = {\n onOpen?: () => void;\n onMessage?: (msg: ISocketMessage) => void;\n onError?: (err: Event) => void;\n onClose?: (ev: CloseEvent) => void;\n};\n\ninterface PelicanMessageEvent extends MessageEvent {\n data: ISocketMessage;\n}\nexport class Transport {\n private socket?: WebSocket;\n private handlers: TransportHandlers;\n\n constructor(handlers: TransportHandlers) {\n this.handlers = handlers;\n }\n\n connect(url: string) {\n this.socket = new WebSocket(url);\n\n this.socket.onopen = () => this.handlers.onOpen?.();\n this.socket.onmessage = (e: PelicanMessageEvent) =>\n this.handlers.onMessage?.(e.data);\n this.socket.onerror = (e: Event) => this.handlers.onError?.(e);\n this.socket.onclose = (e: CloseEvent) => this.handlers.onClose?.(e);\n }\n\n send(payload: ISocketMessage) {\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.socket.send(JSON.stringify(payload));\n }\n }\n\n close() {\n this.socket?.close();\n }\n}\n","export const BASEURL = \"http://localhost:8080\";\n","import CryptoService from \"../utilities/crypto\";\nimport QRCode from \"qrcode\";\nimport {\n PelicanAuthConfig,\n PelicanAuthEventMap,\n ISocketMessage,\n IdentityResult,\n} from \"../types/types\";\nimport {\n storeAuthSession,\n getAuthSession,\n clearAuthSession,\n AuthSession,\n} from \"../utilities/storage\";\nimport { StateMachine } from \"../utilities/stateMachine\";\nimport { Transport } from \"../utilities/transport\";\n\nimport { BASEURL } from \"../constants\";\n\ntype Listener<T> = (payload: T) => void;\n\n/**\n * PelicanAuth SDK\n * Handles cross-device authentication via WebSockets and E2EE (End-to-End Encryption).\n */\nexport class PelicanAuthentication {\n private readonly crypto = new CryptoService();\n private readonly stateMachine = new StateMachine();\n\n private transport?: Transport;\n private sessionId = \"\";\n private sessionKey: string | null = null;\n\n private visibilityHandler?: () => void;\n\n private listeners: {\n [K in keyof PelicanAuthEventMap]?: Set<Listener<any>>;\n } = {};\n\n private readonly config: Required<PelicanAuthConfig>;\n\n constructor(config: PelicanAuthConfig) {\n if (!config.publicKey) throw new Error(\"Missing publicKey\");\n if (!config.projectId) throw new Error(\"Missing projectId\");\n if (!config.authType) throw new Error(\"Missing authType\");\n\n this.config = {\n continuousMode: false,\n forceQRCode: false,\n ...config,\n };\n\n // Sync internal state machine changes with the 'state' event\n this.stateMachine.subscribe((s) => this.emit(\"state\", s));\n this.attachVisibilityRecovery();\n }\n\n /* -------------------- public API -------------------- */\n\n /**\n * Subscribe to SDK events (qr, deeplink, success, error, state)\n * @returns Unsubscribe function\n */\n on<K extends keyof PelicanAuthEventMap>(\n event: K,\n cb: Listener<PelicanAuthEventMap[K]>\n ) {\n this.listeners[event] ??= new Set();\n this.listeners[event]!.add(cb);\n return () => this.listeners[event]!.delete(cb);\n }\n\n /**\n * Initializes the authentication flow.\n * Fetches a relay, establishes a WebSocket, and generates the E2EE session key.\n */\n async start() {\n if (this.stateMachine.current !== \"idle\") return;\n\n this.resetSession();\n this.stateMachine.transition(\"initializing\");\n\n try {\n const relay = await this.fetchRelayUrl();\n\n // Generate a fresh symmetric key for this specific session\n this.sessionKey = this.crypto.generateSymmetricKey();\n this.sessionId = crypto.randomUUID() + crypto.randomUUID();\n\n this.transport = new Transport({\n onOpen: () => {\n // Register this browser session with the relay\n this.transport!.send({\n type: \"register\",\n sessionID: this.sessionId,\n ...this.config,\n });\n this.stateMachine.transition(\"awaiting-pair\");\n },\n onMessage: (msg: ISocketMessage) => this.handleMessage(msg),\n onError: () => this.fail(new Error(\"WebSocket connection failed\")),\n });\n\n this.transport.connect(relay);\n await this.emitEntryPoint();\n } catch (err) {\n this.fail(err instanceof Error ? err : new Error(\"Start failed\"));\n }\n }\n\n /**\n * Manually stops the authentication process and closes connections.\n */\n stop() {\n this.terminate(false);\n }\n\n /* -------------------- internals -------------------- */\n\n /** Fetches the WebSocket Relay URL from the backend */\n private async fetchRelayUrl(): Promise<string> {\n const { publicKey, projectId, authType } = this.config;\n const res = await fetch(\n `${BASEURL}/relay?public_key=${publicKey}&auth_type=${authType}&project_id=${projectId}`\n );\n\n if (!res.ok) {\n throw new Error(\"Failed to fetch relay URL\");\n }\n\n const json = await res.json();\n return json.relay_url;\n }\n\n /**\n * Decides whether to show a QR code (Desktop) or a Deep Link (Mobile).\n */\n private async emitEntryPoint() {\n const payload = {\n sessionID: this.sessionId,\n sessionKey: this.sessionKey,\n publicKey: this.config.publicKey,\n authType: this.config.authType,\n projectId: this.config.projectId,\n url: window.location.href,\n };\n\n const shouldUseQR =\n this.config.forceQRCode ||\n !/Android|iPhone|iPad/i.test(navigator.userAgent);\n\n if (!shouldUseQR && this.sessionKey) {\n // For mobile: Store session locally so we can recover when the user returns from the app\n storeAuthSession(this.sessionId, this.sessionKey, 5 * 60_000);\n this.emit(\n \"deeplink\",\n `pelicanvault://auth/deep-link?data=${encodeURIComponent(\n JSON.stringify(payload)\n )}`\n );\n } else {\n // For desktop: Generate a QR code for the mobile app to scan\n const qr = await QRCode.toDataURL(JSON.stringify(payload));\n this.emit(\"qr\", qr);\n }\n }\n\n /** Main WebSocket message router */\n private handleMessage(msg: ISocketMessage) {\n console.log(msg);\n\n switch (msg.type) {\n case \"paired\":\n console.log(\"Paired\");\n\n this.stateMachine.transition(\"paired\");\n this.transport!.send({\n type: \"authenticate\",\n sessionID: this.sessionId,\n ...this.config,\n url: window.location.href,\n });\n return;\n\n case \"phone-auth-success\":\n // Mobile device successfully authenticated and sent encrypted credentials\n this.handleAuthSuccess(msg);\n return;\n\n case \"phone-terminated\":\n this.fail(new Error(\"Authenticating device terminated the connection\"));\n this.restartIfContinuous();\n return;\n\n case \"confirmed\":\n // Handshake complete\n this.terminate(true);\n this.restartIfContinuous();\n return;\n }\n }\n\n /**\n * Decrypts the identity payload received from the phone using the session key.\n */\n private handleAuthSuccess(msg: ISocketMessage) {\n if (!this.sessionKey || !msg.cipher || !msg.nonce) {\n this.fail(new Error(\"Invalid authentication payload\"));\n this.restartIfContinuous();\n return;\n }\n\n try {\n const decrypted = this.crypto.decryptSymmetric({\n encrypted: { cipher: msg.cipher, nonce: msg.nonce },\n keyString: this.sessionKey,\n });\n\n if (!decrypted) {\n this.fail(new Error(\"Invalid authentication data\"));\n this.restartIfContinuous();\n return;\n }\n\n const result: IdentityResult = JSON.parse(decrypted);\n\n this.emit(\"success\", result);\n this.stateMachine.transition(\"authenticated\");\n\n // Signal to the relay/phone that we have received and decrypted the data\n this.transport?.send({\n type: \"confirm\",\n sessionID: this.sessionId,\n });\n } catch {\n this.fail(new Error(\"Failed to decrypt authentication data\"));\n this.restartIfContinuous();\n }\n }\n\n /**\n * Logic to handle users returning to the browser tab after using the mobile app.\n * Checks the server for a completed session that might have finished while in background.\n */\n\n private async getCachedEntry(cached: AuthSession) {\n try {\n const res = await fetch(\n `${BASEURL}/session?session_id=${cached.sessionId}`\n );\n\n if (!res.ok) throw new Error(\"Invalid session\");\n\n const data = await res.json();\n const decrypted = this.crypto.decryptSymmetric({\n encrypted: { cipher: data.cipher, nonce: data.nonce },\n keyString: cached.sessionKey,\n });\n\n if (!decrypted) {\n this.fail(new Error(\"Invalid session data\"));\n this.restartIfContinuous();\n return;\n }\n const result: IdentityResult = JSON.parse(decrypted);\n this.emit(\"success\", result);\n clearAuthSession();\n } catch {\n this.fail(new Error(\"Session recovery failed\"));\n this.restartIfContinuous();\n }\n }\n\n private attachVisibilityRecovery() {\n this.visibilityHandler = async () => {\n if (document.visibilityState !== \"visible\") return;\n\n const cached = getAuthSession();\n if (!cached) return;\n await this.getCachedEntry(cached);\n };\n\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n\n private detachVisibilityRecovery() {\n if (this.visibilityHandler) {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n this.visibilityHandler = undefined;\n }\n }\n\n /** Cleans up the current session state */\n private terminate(success: boolean) {\n if (!this.transport) return;\n if (!success) {\n this.transport?.send({\n type: \"client-terminated\",\n sessionID: this.sessionId,\n projectId: this.config.projectId,\n publicKey: this.config.publicKey,\n authType: this.config.authType,\n });\n }\n\n setTimeout(() => {\n this.transport?.close();\n }, 150);\n\n clearAuthSession();\n this.resetSession();\n\n if (!this.config.continuousMode) {\n this.detachVisibilityRecovery();\n }\n this.stateMachine.transition(success ? \"confirmed\" : \"terminated\");\n }\n\n private restartIfContinuous() {\n if (!this.config.continuousMode) return;\n this.terminate(false);\n this.stateMachine.transition(\"idle\");\n\n setTimeout(() => {\n this.start();\n }, 150);\n }\n\n private resetSession() {\n this.sessionId = \"\";\n this.sessionKey = null;\n }\n\n /** Completely destroys the instance and removes all listeners */\n destroy() {\n this.detachVisibilityRecovery();\n this.transport?.close();\n this.listeners = {};\n }\n\n private emit<K extends keyof PelicanAuthEventMap>(\n event: K,\n payload: PelicanAuthEventMap[K]\n ) {\n this.listeners[event]?.forEach((cb) => cb(payload));\n }\n\n private fail(err: Error) {\n this.emit(\"error\", err);\n this.stateMachine.transition(\"error\");\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utilities/crypto.ts","../src/utilities/storage.ts","../src/utilities/stateMachine.ts","../src/utilities/transport.ts","../src/constants.ts","../src/engine/engine.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import nacl from \"tweetnacl\";\nimport { decodeBase64, encodeBase64 } from \"tweetnacl-util\";\n\ninterface EncryptedMessage {\n cipher: string; // Base64 encoded\n nonce: string; // Base64 encoded\n}\n\nexport class CryptoService {\n generateSymmetricKey(): string {\n const key = nacl.randomBytes(32);\n return encodeBase64(key);\n }\n\n /**\n * Encrypt with symmetric key (secret-key encryption)\n * Use this when both parties share the same secret key\n * @param plaintext - Message to encrypt\n * @param keyString - Symmetric key (base64)\n * @returns Encrypted message with nonce\n */\n encryptSymmetric({\n plaintext,\n keyString,\n }: {\n plaintext: string;\n keyString: string;\n }): EncryptedMessage {\n const key = decodeBase64(keyString);\n const nonce = nacl.randomBytes(24);\n\n const messageBytes = new TextEncoder().encode(plaintext);\n\n const ciphertext = nacl.secretbox(messageBytes, nonce, key);\n\n return {\n cipher: encodeBase64(ciphertext),\n nonce: encodeBase64(nonce),\n };\n }\n\n /**\n * Decrypt with symmetric key\n * @param encrypted - Encrypted message with nonce\n * @param keyString - Symmetric key (base64)\n * @returns Decrypted plaintext\n */\n decryptSymmetric({\n encrypted,\n keyString,\n }: {\n encrypted: EncryptedMessage;\n keyString: string;\n }): string | null {\n try {\n const key = decodeBase64(keyString);\n const ciphertextBytes = decodeBase64(encrypted.cipher);\n const nonceBytes = decodeBase64(encrypted.nonce);\n\n const decrypted = nacl.secretbox.open(ciphertextBytes, nonceBytes, key);\n\n if (!decrypted) {\n throw new Error(\"Decryption failed - invalid key or corrupted data\");\n }\n\n const decoded = new TextDecoder().decode(decrypted);\n return decoded;\n } catch (error) {\n console.error(\"Decryption failed\", error);\n return null;\n }\n }\n}\n\nexport default CryptoService;\nexport type { EncryptedMessage };\n","// hybridStorage.ts\n/**\n * Hybrid storage: Try sessionStorage first, fallback to memory\n * Best of both worlds - survives page refresh but auto-cleans\n */\n\ninterface StorageOptions {\n ttlMs?: number;\n useSessionStorage?: boolean;\n}\n\nclass AuthStorage {\n private readonly prefix = \"pelican_auth_\";\n private readonly defaultTTL = 5 * 60 * 1000; // 5 minutes\n private memoryCache: Map<string, { value: any; expiresAt: number }> =\n new Map();\n\n /**\n * Store auth session with automatic cleanup\n */\n set(key: string, value: any, options: StorageOptions = {}): void {\n const { ttlMs = this.defaultTTL, useSessionStorage = true } = options;\n\n const expiresAt = Date.now() + ttlMs;\n const data = { value, expiresAt };\n\n // Try sessionStorage first\n if (useSessionStorage) {\n try {\n sessionStorage.setItem(`${this.prefix}${key}`, JSON.stringify(data));\n } catch (error) {\n console.warn(\"SessionStorage unavailable, using memory:\", error);\n this.setMemory(key, data);\n }\n } else {\n this.setMemory(key, data);\n }\n }\n\n /**\n * Get stored value if not expired\n */\n get(key: string): any | null {\n // Try sessionStorage first\n try {\n const stored = sessionStorage.getItem(`${this.prefix}${key}`);\n if (stored) {\n const data = JSON.parse(stored);\n\n // Check expiration\n if (Date.now() > data.expiresAt) {\n this.remove(key);\n return null;\n }\n\n return data.value;\n }\n } catch (error) {\n // Fallback to memory\n }\n\n // Try memory cache\n return this.getMemory(key);\n }\n\n /**\n * Remove specific key\n */\n remove(key: string): void {\n try {\n sessionStorage.removeItem(`${this.prefix}${key}`);\n } catch (error) {\n // Ignore\n }\n this.memoryCache.delete(key);\n }\n\n /**\n * Clear all auth data\n */\n clear(): void {\n // Clear sessionStorage\n try {\n Object.keys(sessionStorage).forEach((key) => {\n if (key.startsWith(this.prefix)) {\n sessionStorage.removeItem(key);\n }\n });\n } catch (error) {\n // Ignore\n }\n\n // Clear memory\n this.memoryCache.clear();\n }\n\n // ========================================\n // Memory cache helpers\n // ========================================\n\n private setMemory(\n key: string,\n data: { value: any; expiresAt: number }\n ): void {\n this.memoryCache.set(key, data);\n\n // Schedule cleanup\n const ttl = data.expiresAt - Date.now();\n setTimeout(() => {\n this.memoryCache.delete(key);\n }, ttl);\n }\n\n private getMemory(key: string): any | null {\n const data = this.memoryCache.get(key);\n if (!data) return null;\n\n if (Date.now() > data.expiresAt) {\n this.memoryCache.delete(key);\n return null;\n }\n\n return data.value;\n }\n}\n\n// Singleton instance\nconst storage = new AuthStorage();\n\n// ========================================\n// Convenience functions for auth flow\n// ========================================\n\nexport interface AuthSession {\n sessionId: string;\n sessionKey: string;\n}\n\nexport const storeAuthSession = (\n sessionId: string,\n sessionKey: string,\n ttlMs?: number\n): void => {\n storage.set(\"session\", { sessionId, sessionKey }, { ttlMs });\n};\n\nexport const getAuthSession = (): AuthSession | null => {\n return storage.get(\"session\");\n};\n\nexport const clearAuthSession = (): void => {\n storage.remove(\"session\");\n};\n\nexport const clearAllAuthData = (): void => {\n storage.clear();\n};\n\nexport default storage;\n","import type { PelicanAuthState } from \"../types/types\";\n\nexport class StateMachine {\n private state: PelicanAuthState = \"idle\";\n private listeners = new Set<(s: PelicanAuthState) => void>();\n\n get current() {\n return this.state;\n }\n\n transition(next: PelicanAuthState) {\n this.state = next;\n this.listeners.forEach((l) => l(next));\n }\n\n subscribe(fn: (s: PelicanAuthState) => void) {\n this.listeners.add(fn);\n return () => this.listeners.delete(fn);\n }\n}\n","import { ISocketMessage } from \"../types/types\";\n\ntype TransportHandlers = {\n onOpen?: () => void;\n onMessage?: (msg: ISocketMessage) => void;\n onError?: (err: Event) => void;\n onClose?: (ev: CloseEvent) => void;\n};\n\nexport class Transport {\n private socket?: WebSocket;\n private handlers: TransportHandlers;\n private reconnectAttempts = 0;\n private maxReconnectAttempts = 5;\n private isExplicitlyClosed = false;\n private url?: string;\n\n constructor(handlers: TransportHandlers) {\n this.handlers = handlers;\n }\n\n connect(url: string) {\n this.url = url;\n this.isExplicitlyClosed = false;\n this.socket = new WebSocket(url);\n\n this.socket.onopen = () => {\n this.reconnectAttempts = 0;\n this.handlers.onOpen?.();\n };\n this.socket.onmessage = (e: MessageEvent) => {\n try {\n const data = JSON.parse(e.data);\n this.handlers.onMessage?.(data);\n } catch (err) {\n console.error(\"Failed to parse message\", err);\n }\n };\n this.socket.onerror = (e: Event) => {\n this.handlers.onError?.(e);\n };\n this.socket.onclose = (e: CloseEvent) => {\n this.handlers.onClose?.(e);\n\n // Only reconnect if the user didn't call .close() manually\n if (!this.isExplicitlyClosed) {\n this.attemptReconnect();\n }\n };\n }\n\n private attemptReconnect() {\n if (this.reconnectAttempts >= this.maxReconnectAttempts) {\n console.error(\"❌ Max reconnect attempts reached\");\n return;\n }\n\n this.reconnectAttempts++;\n\n const delay = Math.pow(2, this.reconnectAttempts) * 500;\n setTimeout(() => {\n if (this.url) this.connect(this.url);\n }, delay);\n }\n send(payload: ISocketMessage) {\n if (this.socket?.readyState === WebSocket.OPEN) {\n this.socket.send(JSON.stringify(payload));\n }\n }\n\n close() {\n this.isExplicitlyClosed = true;\n this.socket?.close();\n }\n}\n","export const BASEURL = \"http://localhost:8080\";\n","import CryptoService from \"../utilities/crypto\";\nimport QRCode from \"qrcode\";\nimport {\n PelicanAuthConfig,\n PelicanAuthEventMap,\n ISocketMessage,\n IdentityResult,\n} from \"../types/types\";\nimport {\n storeAuthSession,\n getAuthSession,\n clearAuthSession,\n AuthSession,\n} from \"../utilities/storage\";\nimport { StateMachine } from \"../utilities/stateMachine\";\nimport { Transport } from \"../utilities/transport\";\n\nimport { BASEURL } from \"../constants\";\n\ntype Listener<T> = (payload: T) => void;\n\n/**\n * PelicanAuth SDK\n * Handles cross-device authentication via WebSockets and E2EE (End-to-End Encryption).\n */\nexport class PelicanAuthentication {\n private readonly crypto = new CryptoService();\n private readonly stateMachine = new StateMachine();\n\n private transport?: Transport;\n private sessionId = \"\";\n private sessionKey: string | null = null;\n\n private visibilityHandler?: () => void;\n\n private listeners: {\n [K in keyof PelicanAuthEventMap]?: Set<Listener<any>>;\n } = {};\n\n private readonly config: Required<PelicanAuthConfig>;\n\n constructor(config: PelicanAuthConfig) {\n if (!config.publicKey) throw new Error(\"Missing publicKey\");\n if (!config.projectId) throw new Error(\"Missing projectId\");\n if (!config.authType) throw new Error(\"Missing authType\");\n\n this.config = {\n continuousMode: false,\n forceQRCode: false,\n ...config,\n };\n\n // Sync internal state machine changes with the 'state' event\n this.stateMachine.subscribe((s) => this.emit(\"state\", s));\n this.attachVisibilityRecovery();\n }\n\n /* -------------------- public API -------------------- */\n\n /**\n * Subscribe to SDK events (qr, deeplink, success, error, state)\n * @returns Unsubscribe function\n */\n on<K extends keyof PelicanAuthEventMap>(\n event: K,\n cb: Listener<PelicanAuthEventMap[K]>\n ) {\n this.listeners[event] ??= new Set();\n this.listeners[event]!.add(cb);\n return () => this.listeners[event]!.delete(cb);\n }\n\n /**\n * Initializes the authentication flow.\n * Fetches a relay, establishes a WebSocket, and generates the E2EE session key.\n */\n async start() {\n if (this.stateMachine.current !== \"idle\") return;\n\n this.resetSession();\n this.stateMachine.transition(\"initializing\");\n\n try {\n const relay = await this.fetchRelayUrl();\n\n // Generate a fresh symmetric key for this specific session\n this.sessionKey = this.crypto.generateSymmetricKey();\n this.sessionId = crypto.randomUUID() + crypto.randomUUID();\n\n this.transport = new Transport({\n onOpen: () => {\n // Register this browser session with the relay\n this.transport!.send({\n type: \"register\",\n sessionID: this.sessionId,\n ...this.config,\n });\n this.stateMachine.transition(\"awaiting-pair\");\n },\n onMessage: (msg: ISocketMessage) => this.handleMessage(msg),\n onError: () => this.fail(new Error(\"WebSocket connection failed\")),\n });\n\n this.transport.connect(relay);\n await this.emitEntryPoint();\n } catch (err) {\n this.fail(err instanceof Error ? err : new Error(\"Start failed\"));\n }\n }\n\n /**\n * Manually stops the authentication process and closes connections.\n */\n stop() {\n this.terminate(false);\n }\n\n /* -------------------- internals -------------------- */\n\n /** Fetches the WebSocket Relay URL from the backend */\n private async fetchRelayUrl(): Promise<string> {\n const { publicKey, projectId, authType } = this.config;\n const res = await fetch(\n `${BASEURL}/relay?public_key=${publicKey}&auth_type=${authType}&project_id=${projectId}`\n );\n\n if (!res.ok) {\n throw new Error(\"Failed to fetch relay URL\");\n }\n\n const json = await res.json();\n return json.relay_url;\n }\n\n /**\n * Decides whether to show a QR code (Desktop) or a Deep Link (Mobile).\n */\n private async emitEntryPoint() {\n const payload = {\n sessionID: this.sessionId,\n sessionKey: this.sessionKey,\n publicKey: this.config.publicKey,\n authType: this.config.authType,\n projectId: this.config.projectId,\n url: window.location.href,\n };\n\n const shouldUseQR =\n this.config.forceQRCode ||\n !/Android|iPhone|iPad/i.test(navigator.userAgent);\n\n if (!shouldUseQR && this.sessionKey) {\n // For mobile: Store session locally so we can recover when the user returns from the app\n storeAuthSession(this.sessionId, this.sessionKey, 5 * 60_000);\n this.emit(\n \"deeplink\",\n `pelicanvault://auth/deep-link?data=${encodeURIComponent(\n JSON.stringify(payload)\n )}`\n );\n } else {\n const qr = await QRCode.toDataURL(JSON.stringify(payload), {\n type: \"image/png\",\n scale: 3,\n color: { light: \"#FFFFF5\", dark: \"#121212\" },\n });\n this.emit(\"qr\", qr);\n }\n }\n\n /** Main WebSocket message router */\n private handleMessage(msg: ISocketMessage) {\n switch (msg.type) {\n case \"paired\":\n this.stateMachine.transition(\"paired\");\n this.transport!.send({\n type: \"authenticate\",\n sessionID: this.sessionId,\n ...this.config,\n url: window.location.href,\n });\n return;\n\n case \"phone-auth-success\":\n // Mobile device successfully authenticated and sent encrypted credentials\n this.handleAuthSuccess(msg);\n return;\n\n case \"phone-terminated\":\n this.fail(new Error(\"Authenticating device terminated the connection\"));\n this.restartIfContinuous();\n return;\n\n case \"confirmed\":\n // Handshake complete\n this.terminate(true);\n this.restartIfContinuous();\n return;\n }\n }\n\n /**\n * Decrypts the identity payload received from the phone using the session key.\n */\n private handleAuthSuccess(msg: ISocketMessage) {\n if (!this.sessionKey || !msg.cipher || !msg.nonce) {\n this.fail(new Error(\"Invalid authentication payload\"));\n this.restartIfContinuous();\n return;\n }\n\n try {\n const decrypted = this.crypto.decryptSymmetric({\n encrypted: { cipher: msg.cipher, nonce: msg.nonce },\n keyString: this.sessionKey,\n });\n\n if (!decrypted) {\n this.fail(new Error(\"Invalid authentication data\"));\n this.restartIfContinuous();\n return;\n }\n\n const result: IdentityResult = JSON.parse(decrypted);\n\n this.emit(\"success\", result);\n this.stateMachine.transition(\"authenticated\");\n\n // Signal to the relay/phone that we have received and decrypted the data\n this.transport?.send({\n type: \"confirm\",\n sessionID: this.sessionId,\n });\n } catch {\n this.fail(new Error(\"Failed to decrypt authentication data\"));\n this.restartIfContinuous();\n }\n }\n\n /**\n * Logic to handle users returning to the browser tab after using the mobile app.\n * Checks the server for a completed session that might have finished while in background.\n */\n\n private async getCachedEntry(cached: AuthSession) {\n try {\n const res = await fetch(\n `${BASEURL}/session?session_id=${cached.sessionId}`\n );\n\n if (!res.ok) throw new Error(\"Invalid session\");\n\n const data = await res.json();\n const decrypted = this.crypto.decryptSymmetric({\n encrypted: { cipher: data.cipher, nonce: data.nonce },\n keyString: cached.sessionKey,\n });\n\n if (!decrypted) {\n this.fail(new Error(\"Invalid session data\"));\n this.restartIfContinuous();\n return;\n }\n const result: IdentityResult = JSON.parse(decrypted);\n this.emit(\"success\", result);\n clearAuthSession();\n } catch {\n this.fail(new Error(\"Session recovery failed\"));\n this.restartIfContinuous();\n }\n }\n\n private attachVisibilityRecovery() {\n this.visibilityHandler = async () => {\n if (document.visibilityState !== \"visible\") return;\n\n const cached = getAuthSession();\n if (!cached) return;\n await this.getCachedEntry(cached);\n };\n\n document.addEventListener(\"visibilitychange\", this.visibilityHandler);\n }\n\n private detachVisibilityRecovery() {\n if (this.visibilityHandler) {\n document.removeEventListener(\"visibilitychange\", this.visibilityHandler);\n this.visibilityHandler = undefined;\n }\n }\n\n /** Cleans up the current session state */\n private terminate(success: boolean) {\n if (!this.transport) return;\n if (!success) {\n this.transport?.send({\n type: \"client-terminated\",\n sessionID: this.sessionId,\n projectId: this.config.projectId,\n publicKey: this.config.publicKey,\n authType: this.config.authType,\n });\n }\n\n this.transport?.close();\n clearAuthSession();\n this.resetSession();\n\n if (!this.config.continuousMode) {\n this.detachVisibilityRecovery();\n }\n this.stateMachine.transition(success ? \"confirmed\" : \"idle\");\n }\n\n private restartIfContinuous() {\n this.stateMachine.transition(\"idle\");\n if (!this.config.continuousMode) return;\n setTimeout(() => {\n this.start();\n }, 150);\n }\n\n private resetSession() {\n this.sessionId = \"\";\n this.sessionKey = null;\n }\n\n /** Completely destroys the instance and removes all listeners */\n destroy() {\n this.detachVisibilityRecovery();\n this.transport?.close();\n this.listeners = {};\n }\n\n private emit<K extends keyof PelicanAuthEventMap>(\n event: K,\n payload: PelicanAuthEventMap[K]\n ) {\n this.listeners[event]?.forEach((cb) => cb(payload));\n }\n\n private fail(err: Error) {\n this.emit(\"error\", err);\n this.stateMachine.transition(\"error\");\n }\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,QAAQ,GAAG,iBAAiB,CAAC;AAE9D,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,cAAc,GACd,eAAe,GACf,QAAQ,GACR,eAAe,GACf,eAAe,GACf,WAAW,GACX,OAAO,GACP,YAAY,CAAC;AAEjB,MAAM,WAAW,iBAAiB;IAKhC,SAAS,EAAE,MAAM,CAAC;IAMlB,SAAS,EAAE,MAAM,CAAC;IAQlB,QAAQ,EAAE,QAAQ,CAAC;IAanB,cAAc,CAAC,EAAE,OAAO,CAAC;IAazB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,gBAAgB,CAAC;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,cAAc,CAAC;IACxB,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,IAAI,EACA,WAAW,GACX,kBAAkB,GAClB,mBAAmB,GACnB,kBAAkB,GAClB,MAAM,GACN,QAAQ,GACR,oBAAoB,GACpB,cAAc,GACd,SAAS,GACT,UAAU,CAAC;IAEf,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;KAAE,CAAC;CAChD;AAED,MAAM,WAAW,MAAM;IAErB,EAAE,EAAE,MAAM,CAAC;IAEX,OAAO,EAAE,MAAM,CAAC;IAEhB,WAAW,EAAE,MAAM,CAAC;IAEpB,MAAM,EAAE,MAAM,CAAC;IAEf,UAAU,EAAE,MAAM,CAAC;IAEnB,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,WAAW,MAAM;IAErB,EAAE,EAAE,MAAM,CAAC;IAEX,KAAK,EAAE,MAAM,CAAC;IAEd,UAAU,EAAE,MAAM,CAAC;IAEnB,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,MAAM,MAAM,WAAW,GACnB,kBAAkB,GAClB,UAAU,GACV,kBAAkB,GAClB,kBAAkB,CAAC;AAEvB,MAAM,WAAW,QAAQ;IAEvB,EAAE,EAAE,MAAM,CAAC;IAEX,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,WAAW,CAAC;IAE/C,aAAa,CAAC,EAAE,WAAW,CAAC;IAE5B,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE9B,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAE3B,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAE7B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAE/B,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAE7B;AAED,MAAM,WAAW,SAAS;IAExB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEpB,MAAM,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IAErC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAE7B,OAAO,EAAE,MAAM,CAAC;IAEhB,SAAS,CAAC,EAAE,SAAS,CAAC;IAEtB,eAAe,EAAE,QAAQ,CAAC;IAE1B,eAAe,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACrE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../../src/utilities/crypto.ts"],"names":[],"mappings":"AAGA,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf;AAED,qBAAa,aAAa;IACxB,oBAAoB,IAAI,MAAM;IAY9B,gBAAgB,CAAC,EACf,SAAS,EACT,SAAS,GACV,EAAE;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,gBAAgB;IAoBpB,gBAAgB,CAAC,EACf,SAAS,EACT,SAAS,GACV,EAAE;QACD,SAAS,EAAE,gBAAgB,CAAC;QAC5B,SAAS,EAAE,MAAM,CAAC;KACnB,GAAG,MAAM,GAAG,IAAI;CAmBlB;AAED,eAAe,aAAa,CAAC;AAC7B,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import nacl from "tweetnacl";
|
|
2
|
+
import { decodeBase64, encodeBase64 } from "tweetnacl-util";
|
|
3
|
+
export class CryptoService {
|
|
4
|
+
generateSymmetricKey() {
|
|
5
|
+
const key = nacl.randomBytes(32);
|
|
6
|
+
return encodeBase64(key);
|
|
7
|
+
}
|
|
8
|
+
encryptSymmetric({ plaintext, keyString, }) {
|
|
9
|
+
const key = decodeBase64(keyString);
|
|
10
|
+
const nonce = nacl.randomBytes(24);
|
|
11
|
+
const messageBytes = new TextEncoder().encode(plaintext);
|
|
12
|
+
const ciphertext = nacl.secretbox(messageBytes, nonce, key);
|
|
13
|
+
return {
|
|
14
|
+
cipher: encodeBase64(ciphertext),
|
|
15
|
+
nonce: encodeBase64(nonce),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
decryptSymmetric({ encrypted, keyString, }) {
|
|
19
|
+
try {
|
|
20
|
+
const key = decodeBase64(keyString);
|
|
21
|
+
const ciphertextBytes = decodeBase64(encrypted.cipher);
|
|
22
|
+
const nonceBytes = decodeBase64(encrypted.nonce);
|
|
23
|
+
const decrypted = nacl.secretbox.open(ciphertextBytes, nonceBytes, key);
|
|
24
|
+
if (!decrypted) {
|
|
25
|
+
throw new Error("Decryption failed - invalid key or corrupted data");
|
|
26
|
+
}
|
|
27
|
+
const decoded = new TextDecoder().decode(decrypted);
|
|
28
|
+
return decoded;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
console.error("Decryption failed", error);
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export default CryptoService;
|
|
37
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/utilities/crypto.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAO5D,MAAM,OAAO,aAAa;IACxB,oBAAoB;QAClB,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACjC,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IASD,gBAAgB,CAAC,EACf,SAAS,EACT,SAAS,GAIV;QACC,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAEnC,MAAM,YAAY,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAEzD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;QAE5D,OAAO;YACL,MAAM,EAAE,YAAY,CAAC,UAAU,CAAC;YAChC,KAAK,EAAE,YAAY,CAAC,KAAK,CAAC;SAC3B,CAAC;IACJ,CAAC;IAQD,gBAAgB,CAAC,EACf,SAAS,EACT,SAAS,GAIV;QACC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;YACpC,MAAM,eAAe,GAAG,YAAY,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;YACvD,MAAM,UAAU,GAAG,YAAY,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;YAEjD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,eAAe,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC;YAExE,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;YACvE,CAAC;YAED,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACpD,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF;AAED,eAAe,aAAa,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stateMachine.d.ts","sourceRoot":"","sources":["../../src/utilities/stateMachine.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,SAAS,CAA4C;IAE7D,IAAI,OAAO,qBAEV;IAED,UAAU,CAAC,IAAI,EAAE,gBAAgB;IAKjC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,gBAAgB,KAAK,IAAI;CAI5C"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export class StateMachine {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.state = "idle";
|
|
4
|
+
this.listeners = new Set();
|
|
5
|
+
}
|
|
6
|
+
get current() {
|
|
7
|
+
return this.state;
|
|
8
|
+
}
|
|
9
|
+
transition(next) {
|
|
10
|
+
this.state = next;
|
|
11
|
+
this.listeners.forEach((l) => l(next));
|
|
12
|
+
}
|
|
13
|
+
subscribe(fn) {
|
|
14
|
+
this.listeners.add(fn);
|
|
15
|
+
return () => this.listeners.delete(fn);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=stateMachine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stateMachine.js","sourceRoot":"","sources":["../../src/utilities/stateMachine.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,YAAY;IAAzB;QACU,UAAK,GAAqB,MAAM,CAAC;QACjC,cAAS,GAAG,IAAI,GAAG,EAAiC,CAAC;IAe/D,CAAC;IAbC,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,UAAU,CAAC,IAAsB;QAC/B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,SAAS,CAAC,EAAiC;QACzC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvB,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/utilities/storage.ts"],"names":[],"mappings":"AAMA,UAAU,cAAc;IACtB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,cAAM,WAAW;IACf,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiB;IAC5C,OAAO,CAAC,WAAW,CACP;IAKZ,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,GAAE,cAAmB,GAAG,IAAI;IAsBhE,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,GAAG,IAAI;IA0B5B,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAYzB,KAAK,IAAI,IAAI;IAoBb,OAAO,CAAC,SAAS;IAajB,OAAO,CAAC,SAAS;CAWlB;AAGD,QAAA,MAAM,OAAO,aAAoB,CAAC;AAMlC,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,gBAAgB,GAC3B,WAAW,MAAM,EACjB,YAAY,MAAM,EAClB,QAAQ,MAAM,KACb,IAEF,CAAC;AAEF,eAAO,MAAM,cAAc,QAAO,WAAW,GAAG,IAE/C,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,IAEnC,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAO,IAEnC,CAAC;AAEF,eAAe,OAAO,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
class AuthStorage {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.prefix = "pelican_auth_";
|
|
4
|
+
this.defaultTTL = 5 * 60 * 1000;
|
|
5
|
+
this.memoryCache = new Map();
|
|
6
|
+
}
|
|
7
|
+
set(key, value, options = {}) {
|
|
8
|
+
const { ttlMs = this.defaultTTL, useSessionStorage = true } = options;
|
|
9
|
+
const expiresAt = Date.now() + ttlMs;
|
|
10
|
+
const data = { value, expiresAt };
|
|
11
|
+
if (useSessionStorage) {
|
|
12
|
+
try {
|
|
13
|
+
sessionStorage.setItem(`${this.prefix}${key}`, JSON.stringify(data));
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
console.warn("SessionStorage unavailable, using memory:", error);
|
|
17
|
+
this.setMemory(key, data);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this.setMemory(key, data);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
get(key) {
|
|
25
|
+
try {
|
|
26
|
+
const stored = sessionStorage.getItem(`${this.prefix}${key}`);
|
|
27
|
+
if (stored) {
|
|
28
|
+
const data = JSON.parse(stored);
|
|
29
|
+
if (Date.now() > data.expiresAt) {
|
|
30
|
+
this.remove(key);
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return data.value;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
}
|
|
38
|
+
return this.getMemory(key);
|
|
39
|
+
}
|
|
40
|
+
remove(key) {
|
|
41
|
+
try {
|
|
42
|
+
sessionStorage.removeItem(`${this.prefix}${key}`);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
}
|
|
46
|
+
this.memoryCache.delete(key);
|
|
47
|
+
}
|
|
48
|
+
clear() {
|
|
49
|
+
try {
|
|
50
|
+
Object.keys(sessionStorage).forEach((key) => {
|
|
51
|
+
if (key.startsWith(this.prefix)) {
|
|
52
|
+
sessionStorage.removeItem(key);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
}
|
|
58
|
+
this.memoryCache.clear();
|
|
59
|
+
}
|
|
60
|
+
setMemory(key, data) {
|
|
61
|
+
this.memoryCache.set(key, data);
|
|
62
|
+
const ttl = data.expiresAt - Date.now();
|
|
63
|
+
setTimeout(() => {
|
|
64
|
+
this.memoryCache.delete(key);
|
|
65
|
+
}, ttl);
|
|
66
|
+
}
|
|
67
|
+
getMemory(key) {
|
|
68
|
+
const data = this.memoryCache.get(key);
|
|
69
|
+
if (!data)
|
|
70
|
+
return null;
|
|
71
|
+
if (Date.now() > data.expiresAt) {
|
|
72
|
+
this.memoryCache.delete(key);
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
return data.value;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const storage = new AuthStorage();
|
|
79
|
+
export const storeAuthSession = (sessionId, sessionKey, ttlMs) => {
|
|
80
|
+
storage.set("session", { sessionId, sessionKey }, { ttlMs });
|
|
81
|
+
};
|
|
82
|
+
export const getAuthSession = () => {
|
|
83
|
+
return storage.get("session");
|
|
84
|
+
};
|
|
85
|
+
export const clearAuthSession = () => {
|
|
86
|
+
storage.remove("session");
|
|
87
|
+
};
|
|
88
|
+
export const clearAllAuthData = () => {
|
|
89
|
+
storage.clear();
|
|
90
|
+
};
|
|
91
|
+
export default storage;
|
|
92
|
+
//# sourceMappingURL=storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/utilities/storage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { ISocketMessage } from "../types/types";
|
|
2
|
+
type TransportHandlers = {
|
|
3
|
+
onOpen?: () => void;
|
|
4
|
+
onMessage?: (msg: ISocketMessage) => void;
|
|
5
|
+
onError?: (err: Event) => void;
|
|
6
|
+
onClose?: (ev: CloseEvent) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare class Transport {
|
|
9
|
+
private socket?;
|
|
10
|
+
private handlers;
|
|
11
|
+
private reconnectAttempts;
|
|
12
|
+
private maxReconnectAttempts;
|
|
13
|
+
private isExplicitlyClosed;
|
|
14
|
+
private url?;
|
|
15
|
+
constructor(handlers: TransportHandlers);
|
|
16
|
+
connect(url: string): void;
|
|
17
|
+
private attemptReconnect;
|
|
18
|
+
send(payload: ISocketMessage): void;
|
|
19
|
+
close(): void;
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/utilities/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAEhD,KAAK,iBAAiB,GAAG;IACvB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,CAAC;IAC1C,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,UAAU,KAAK,IAAI,CAAC;CACpC,CAAC;AAEF,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAC,CAAY;IAC3B,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,oBAAoB,CAAK;IACjC,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,GAAG,CAAC,CAAS;gBAET,QAAQ,EAAE,iBAAiB;IAIvC,OAAO,CAAC,GAAG,EAAE,MAAM;IA8BnB,OAAO,CAAC,gBAAgB;IAaxB,IAAI,CAAC,OAAO,EAAE,cAAc;IAM5B,KAAK;CAIN"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
export class Transport {
|
|
2
|
+
constructor(handlers) {
|
|
3
|
+
this.reconnectAttempts = 0;
|
|
4
|
+
this.maxReconnectAttempts = 5;
|
|
5
|
+
this.isExplicitlyClosed = false;
|
|
6
|
+
this.handlers = handlers;
|
|
7
|
+
}
|
|
8
|
+
connect(url) {
|
|
9
|
+
this.url = url;
|
|
10
|
+
this.isExplicitlyClosed = false;
|
|
11
|
+
this.socket = new WebSocket(url);
|
|
12
|
+
this.socket.onopen = () => {
|
|
13
|
+
this.reconnectAttempts = 0;
|
|
14
|
+
this.handlers.onOpen?.();
|
|
15
|
+
};
|
|
16
|
+
this.socket.onmessage = (e) => {
|
|
17
|
+
try {
|
|
18
|
+
const data = JSON.parse(e.data);
|
|
19
|
+
this.handlers.onMessage?.(data);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
console.error("Failed to parse message", err);
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
this.socket.onerror = (e) => {
|
|
26
|
+
this.handlers.onError?.(e);
|
|
27
|
+
};
|
|
28
|
+
this.socket.onclose = (e) => {
|
|
29
|
+
this.handlers.onClose?.(e);
|
|
30
|
+
if (!this.isExplicitlyClosed) {
|
|
31
|
+
this.attemptReconnect();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
attemptReconnect() {
|
|
36
|
+
if (this.reconnectAttempts >= this.maxReconnectAttempts) {
|
|
37
|
+
console.error("❌ Max reconnect attempts reached");
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this.reconnectAttempts++;
|
|
41
|
+
const delay = Math.pow(2, this.reconnectAttempts) * 500;
|
|
42
|
+
setTimeout(() => {
|
|
43
|
+
if (this.url)
|
|
44
|
+
this.connect(this.url);
|
|
45
|
+
}, delay);
|
|
46
|
+
}
|
|
47
|
+
send(payload) {
|
|
48
|
+
if (this.socket?.readyState === WebSocket.OPEN) {
|
|
49
|
+
this.socket.send(JSON.stringify(payload));
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
close() {
|
|
53
|
+
this.isExplicitlyClosed = true;
|
|
54
|
+
this.socket?.close();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=transport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/utilities/transport.ts"],"names":[],"mappings":"AASA,MAAM,OAAO,SAAS;IAQpB,YAAY,QAA2B;QAL/B,sBAAiB,GAAG,CAAC,CAAC;QACtB,yBAAoB,GAAG,CAAC,CAAC;QACzB,uBAAkB,GAAG,KAAK,CAAC;QAIjC,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED,OAAO,CAAC,GAAW;QACjB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,kBAAkB,GAAG,KAAK,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC;QAEjC,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,GAAG,EAAE;YACxB,IAAI,CAAC,iBAAiB,GAAG,CAAC,CAAC;YAC3B,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;QAC3B,CAAC,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,SAAS,GAAG,CAAC,CAAe,EAAE,EAAE;YAC1C,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;gBAChC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,CAAC;YAClC,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,GAAG,CAAC,CAAC;YAChD,CAAC;QACH,CAAC,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,CAAQ,EAAE,EAAE;YACjC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,CAAC,CAAa,EAAE,EAAE;YACtC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;YAG3B,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE,CAAC;gBAC7B,IAAI,CAAC,gBAAgB,EAAE,CAAC;YAC1B,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAEO,gBAAgB;QACtB,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACxD,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;YAClD,OAAO;QACT,CAAC;QAED,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEzB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,iBAAiB,CAAC,GAAG,GAAG,CAAC;QACxD,UAAU,CAAC,GAAG,EAAE;YACd,IAAI,IAAI,CAAC,GAAG;gBAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACvC,CAAC,EAAE,KAAK,CAAC,CAAC;IACZ,CAAC;IACD,IAAI,CAAC,OAAuB;QAC1B,IAAI,IAAI,CAAC,MAAM,EAAE,UAAU,KAAK,SAAS,CAAC,IAAI,EAAE,CAAC;YAC/C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,KAAK;QACH,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC;QAC/B,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAC;IACvB,CAAC;CACF"}
|