@calimero-network/mero-js 25.3.1 → 25.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/auth/index.d.ts +11 -2
- package/dist/auth/index.js +20 -3
- package/dist/cloud/enrol-redirect.d.ts +10 -24
- package/dist/cloud/enrol-redirect.js +16 -8
- package/dist/cloud/link-state.d.ts +5 -1
- package/dist/cloud/link-state.js +28 -21
- package/dist/index.browser.mjs +2 -2
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +92 -70
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +92 -70
- package/dist/index.mjs.map +4 -4
- package/dist/mero-js.d.ts +2 -2
- package/dist/mero-js.js +2 -2
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export * from "./auth-api/index.js";
|
|
|
5
5
|
export * from "./admin-api/index.js";
|
|
6
6
|
export * from "./errors/index.js";
|
|
7
7
|
export { parseAuthCallback, buildAuthLoginUrl } from "./auth/index.js";
|
|
8
|
-
export type { AuthCallbackResult, AuthLoginOptions } from "./auth/index.js";
|
|
8
|
+
export type { AuthCallbackResult, AuthLoginOptions, ParseAuthCallbackOptions, } from "./auth/index.js";
|
|
9
9
|
export { MemoryTokenStore, LocalStorageTokenStore, } from "./token-store/index.js";
|
|
10
10
|
export type { TokenStore } from "./token-store/index.js";
|
|
11
11
|
export { RpcClient, RpcError } from "./rpc/index.js";
|
package/dist/index.mjs
CHANGED
|
@@ -2684,8 +2684,73 @@ function createAdminApiClientFromHttpClient(httpClient, _config) {
|
|
|
2684
2684
|
return new AdminApiClient(httpClient);
|
|
2685
2685
|
}
|
|
2686
2686
|
|
|
2687
|
+
// src/cloud/link-state.ts
|
|
2688
|
+
var KEY = "calimero.cloud.link.pending";
|
|
2689
|
+
var STATE_PARAM = "link_state";
|
|
2690
|
+
var LIFETIME_MS = 10 * 60 * 1e3;
|
|
2691
|
+
var ACCOUNT_HEX = /^[0-9a-f]{64}$/;
|
|
2692
|
+
var MAX_PENDING = 20;
|
|
2693
|
+
function readPending(key, now) {
|
|
2694
|
+
try {
|
|
2695
|
+
const raw = localStorage.getItem(key);
|
|
2696
|
+
const pending = raw ? JSON.parse(raw) : {};
|
|
2697
|
+
return Object.fromEntries(
|
|
2698
|
+
Object.entries(pending).filter(
|
|
2699
|
+
([, p]) => p && typeof p.expiresAt === "number" && p.expiresAt > now
|
|
2700
|
+
)
|
|
2701
|
+
);
|
|
2702
|
+
} catch {
|
|
2703
|
+
return {};
|
|
2704
|
+
}
|
|
2705
|
+
}
|
|
2706
|
+
function writePending(key, pending) {
|
|
2707
|
+
try {
|
|
2708
|
+
localStorage.setItem(key, JSON.stringify(pending));
|
|
2709
|
+
} catch {
|
|
2710
|
+
}
|
|
2711
|
+
}
|
|
2712
|
+
function beginState(key, payload) {
|
|
2713
|
+
const now = Date.now();
|
|
2714
|
+
const pending = readPending(key, now);
|
|
2715
|
+
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
2716
|
+
const state = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(
|
|
2717
|
+
""
|
|
2718
|
+
);
|
|
2719
|
+
pending[state] = { ...payload, expiresAt: now + LIFETIME_MS };
|
|
2720
|
+
writePending(key, Object.fromEntries(Object.entries(pending).slice(-MAX_PENDING)));
|
|
2721
|
+
return state;
|
|
2722
|
+
}
|
|
2723
|
+
function takeState(key, state) {
|
|
2724
|
+
const pending = readPending(key, Date.now());
|
|
2725
|
+
if (!state || !Object.prototype.hasOwnProperty.call(pending, state))
|
|
2726
|
+
return null;
|
|
2727
|
+
const entry = pending[state];
|
|
2728
|
+
delete pending[state];
|
|
2729
|
+
writePending(key, pending);
|
|
2730
|
+
return entry;
|
|
2731
|
+
}
|
|
2732
|
+
function beginLinkState(account, returnTo) {
|
|
2733
|
+
if (!ACCOUNT_HEX.test(account)) {
|
|
2734
|
+
throw new Error("accountId must be 64 lowercase hex characters");
|
|
2735
|
+
}
|
|
2736
|
+
const url2 = new URL(returnTo);
|
|
2737
|
+
url2.searchParams.set(STATE_PARAM, beginState(KEY, { account }));
|
|
2738
|
+
return url2.toString();
|
|
2739
|
+
}
|
|
2740
|
+
function takeLinkState(search) {
|
|
2741
|
+
return takeState(KEY, new URLSearchParams(search).get(STATE_PARAM));
|
|
2742
|
+
}
|
|
2743
|
+
function withoutLinkState(search) {
|
|
2744
|
+
const params = new URLSearchParams(search);
|
|
2745
|
+
params.delete(STATE_PARAM);
|
|
2746
|
+
const rest = params.toString();
|
|
2747
|
+
return rest ? `?${rest}` : "";
|
|
2748
|
+
}
|
|
2749
|
+
|
|
2687
2750
|
// src/auth/index.ts
|
|
2688
|
-
|
|
2751
|
+
var PENDING_KEY = "calimero.auth.login.pending";
|
|
2752
|
+
var STATE_PARAM2 = "auth_state";
|
|
2753
|
+
function parseAuthCallback(url2, options = {}) {
|
|
2689
2754
|
try {
|
|
2690
2755
|
const hashIndex = url2.indexOf("#");
|
|
2691
2756
|
if (hashIndex === -1) return null;
|
|
@@ -2693,6 +2758,12 @@ function parseAuthCallback(url2) {
|
|
|
2693
2758
|
const params = new URLSearchParams(hash);
|
|
2694
2759
|
const accessToken = params.get("access_token");
|
|
2695
2760
|
if (!accessToken) return null;
|
|
2761
|
+
if (!options.allowUnsolicited && !takeState(PENDING_KEY, stateOf(url2, hashIndex))) {
|
|
2762
|
+
console.warn(
|
|
2763
|
+
"[mero-js] ignoring auth callback tokens: they answer no login begun in this browser"
|
|
2764
|
+
);
|
|
2765
|
+
return null;
|
|
2766
|
+
}
|
|
2696
2767
|
return {
|
|
2697
2768
|
accessToken,
|
|
2698
2769
|
refreshToken: params.get("refresh_token") ?? "",
|
|
@@ -2705,9 +2776,16 @@ function parseAuthCallback(url2) {
|
|
|
2705
2776
|
return null;
|
|
2706
2777
|
}
|
|
2707
2778
|
}
|
|
2779
|
+
function stateOf(url2, hashIndex) {
|
|
2780
|
+
const queryIndex = url2.indexOf("?");
|
|
2781
|
+
if (queryIndex === -1 || queryIndex > hashIndex) return null;
|
|
2782
|
+
return new URLSearchParams(url2.substring(queryIndex + 1, hashIndex)).get(STATE_PARAM2);
|
|
2783
|
+
}
|
|
2708
2784
|
function buildAuthLoginUrl(nodeUrl, opts) {
|
|
2785
|
+
const callback = new URL(opts.callbackUrl);
|
|
2786
|
+
callback.searchParams.set(STATE_PARAM2, beginState(PENDING_KEY, {}));
|
|
2709
2787
|
const params = new URLSearchParams();
|
|
2710
|
-
params.set("callback-url",
|
|
2788
|
+
params.set("callback-url", callback.toString());
|
|
2711
2789
|
if (opts.permissions && opts.permissions.length > 0) {
|
|
2712
2790
|
params.set("permissions", opts.permissions.join(","));
|
|
2713
2791
|
}
|
|
@@ -9123,12 +9201,12 @@ function createMeroClient(config) {
|
|
|
9123
9201
|
}
|
|
9124
9202
|
|
|
9125
9203
|
// src/account/session.ts
|
|
9126
|
-
var
|
|
9204
|
+
var KEY2 = "calimero.delegated.connection";
|
|
9127
9205
|
var CREDENTIAL_KEY = "calimero.delegated.credential";
|
|
9128
9206
|
function readDelegatedSession() {
|
|
9129
9207
|
if (typeof sessionStorage === "undefined") return null;
|
|
9130
9208
|
try {
|
|
9131
|
-
const raw = sessionStorage.getItem(
|
|
9209
|
+
const raw = sessionStorage.getItem(KEY2);
|
|
9132
9210
|
return raw ? JSON.parse(raw) : null;
|
|
9133
9211
|
} catch {
|
|
9134
9212
|
return null;
|
|
@@ -9136,13 +9214,13 @@ function readDelegatedSession() {
|
|
|
9136
9214
|
}
|
|
9137
9215
|
function saveDelegatedSession(s) {
|
|
9138
9216
|
try {
|
|
9139
|
-
sessionStorage.setItem(
|
|
9217
|
+
sessionStorage.setItem(KEY2, JSON.stringify(s));
|
|
9140
9218
|
} catch {
|
|
9141
9219
|
}
|
|
9142
9220
|
}
|
|
9143
9221
|
function clearDelegatedSession() {
|
|
9144
9222
|
try {
|
|
9145
|
-
sessionStorage.removeItem(
|
|
9223
|
+
sessionStorage.removeItem(KEY2);
|
|
9146
9224
|
} catch {
|
|
9147
9225
|
}
|
|
9148
9226
|
}
|
|
@@ -9940,64 +10018,6 @@ function base643(bytes) {
|
|
|
9940
10018
|
return btoa(binary);
|
|
9941
10019
|
}
|
|
9942
10020
|
|
|
9943
|
-
// src/cloud/link-state.ts
|
|
9944
|
-
var KEY2 = "calimero.cloud.link.pending";
|
|
9945
|
-
var STATE_PARAM = "link_state";
|
|
9946
|
-
var LIFETIME_MS = 10 * 60 * 1e3;
|
|
9947
|
-
var ACCOUNT_HEX = /^[0-9a-f]{64}$/;
|
|
9948
|
-
var MAX_PENDING = 20;
|
|
9949
|
-
function readPending(now) {
|
|
9950
|
-
try {
|
|
9951
|
-
const raw = localStorage.getItem(KEY2);
|
|
9952
|
-
const pending = raw ? JSON.parse(raw) : {};
|
|
9953
|
-
return Object.fromEntries(
|
|
9954
|
-
Object.entries(pending).filter(
|
|
9955
|
-
([, p]) => p && typeof p.expiresAt === "number" && p.expiresAt > now
|
|
9956
|
-
)
|
|
9957
|
-
);
|
|
9958
|
-
} catch {
|
|
9959
|
-
return {};
|
|
9960
|
-
}
|
|
9961
|
-
}
|
|
9962
|
-
function writePending(pending) {
|
|
9963
|
-
try {
|
|
9964
|
-
localStorage.setItem(KEY2, JSON.stringify(pending));
|
|
9965
|
-
} catch {
|
|
9966
|
-
}
|
|
9967
|
-
}
|
|
9968
|
-
function beginLinkState(account, returnTo) {
|
|
9969
|
-
if (!ACCOUNT_HEX.test(account)) {
|
|
9970
|
-
throw new Error("accountId must be 64 lowercase hex characters");
|
|
9971
|
-
}
|
|
9972
|
-
const url2 = new URL(returnTo);
|
|
9973
|
-
const now = Date.now();
|
|
9974
|
-
const pending = readPending(now);
|
|
9975
|
-
const bytes = crypto.getRandomValues(new Uint8Array(16));
|
|
9976
|
-
const state = Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join(
|
|
9977
|
-
""
|
|
9978
|
-
);
|
|
9979
|
-
pending[state] = { account, expiresAt: now + LIFETIME_MS };
|
|
9980
|
-
writePending(Object.fromEntries(Object.entries(pending).slice(-MAX_PENDING)));
|
|
9981
|
-
url2.searchParams.set(STATE_PARAM, state);
|
|
9982
|
-
return url2.toString();
|
|
9983
|
-
}
|
|
9984
|
-
function takeLinkState(search) {
|
|
9985
|
-
const state = new URLSearchParams(search).get(STATE_PARAM);
|
|
9986
|
-
const pending = readPending(Date.now());
|
|
9987
|
-
if (!state || !Object.prototype.hasOwnProperty.call(pending, state))
|
|
9988
|
-
return null;
|
|
9989
|
-
const entry = pending[state];
|
|
9990
|
-
delete pending[state];
|
|
9991
|
-
writePending(pending);
|
|
9992
|
-
return entry;
|
|
9993
|
-
}
|
|
9994
|
-
function withoutLinkState(search) {
|
|
9995
|
-
const params = new URLSearchParams(search);
|
|
9996
|
-
params.delete(STATE_PARAM);
|
|
9997
|
-
const rest = params.toString();
|
|
9998
|
-
return rest ? `?${rest}` : "";
|
|
9999
|
-
}
|
|
10000
|
-
|
|
10001
10021
|
// src/cloud/link-redirect.ts
|
|
10002
10022
|
var DEFAULT_CLOUD_WEB_URL = "https://cloud.calimero.network";
|
|
10003
10023
|
function cloudLinkUrl(options) {
|
|
@@ -10054,7 +10074,8 @@ async function completeCloudLink(options) {
|
|
|
10054
10074
|
var DEVICE_PARAM = "enrol-device";
|
|
10055
10075
|
var KEM_PARAM = "enrol-kem";
|
|
10056
10076
|
var CALLBACK_PARAM = "callback-url";
|
|
10057
|
-
var
|
|
10077
|
+
var STATE_PARAM3 = "state";
|
|
10078
|
+
var PENDING_KEY2 = "calimero.device.enrol.pending";
|
|
10058
10079
|
function deviceEnrolmentUrl(options) {
|
|
10059
10080
|
assertHex(options.devicePublicKey, "devicePublicKey");
|
|
10060
10081
|
assertHex(options.kemPublicKey, "kemPublicKey");
|
|
@@ -10064,7 +10085,7 @@ function deviceEnrolmentUrl(options) {
|
|
|
10064
10085
|
url2.searchParams.set(DEVICE_PARAM, options.devicePublicKey);
|
|
10065
10086
|
url2.searchParams.set(KEM_PARAM, options.kemPublicKey);
|
|
10066
10087
|
url2.searchParams.set(CALLBACK_PARAM, options.returnTo);
|
|
10067
|
-
|
|
10088
|
+
url2.searchParams.set(STATE_PARAM3, beginState(PENDING_KEY2, {}));
|
|
10068
10089
|
return url2.toString();
|
|
10069
10090
|
}
|
|
10070
10091
|
function beginDeviceEnrolment(options) {
|
|
@@ -10075,6 +10096,7 @@ function readEnrolmentCallback(location2 = window.location) {
|
|
|
10075
10096
|
const params = new URLSearchParams(location2.hash.replace(/^#/, ""));
|
|
10076
10097
|
const error = params.get("error");
|
|
10077
10098
|
if (error) {
|
|
10099
|
+
takeState(PENDING_KEY2, params.get(STATE_PARAM3));
|
|
10078
10100
|
stripFragment2();
|
|
10079
10101
|
throw new Error(
|
|
10080
10102
|
error === "denied" || error === "cancelled" ? "the device was not approved at the wallet" : `the wallet refused this enrolment: ${error}`
|
|
@@ -10093,9 +10115,9 @@ function stripFragment2() {
|
|
|
10093
10115
|
history.replaceState(null, "", location.pathname + location.search);
|
|
10094
10116
|
}
|
|
10095
10117
|
async function completeDeviceEnrolment(options) {
|
|
10096
|
-
if (
|
|
10118
|
+
if (!takeState(PENDING_KEY2, options.state)) {
|
|
10097
10119
|
throw new Error(
|
|
10098
|
-
"this enrolment answers a request this app did not make
|
|
10120
|
+
"this enrolment answers a request this app did not make - start the enrolment again from here"
|
|
10099
10121
|
);
|
|
10100
10122
|
}
|
|
10101
10123
|
const certificate = await verifyDeviceCredential(options.credential);
|
|
@@ -12488,8 +12510,8 @@ var MeroJs = class {
|
|
|
12488
12510
|
/**
|
|
12489
12511
|
* Parse an auth callback URL hash fragment (static utility)
|
|
12490
12512
|
*/
|
|
12491
|
-
static parseAuthCallback(url2) {
|
|
12492
|
-
return parseAuthCallback(url2);
|
|
12513
|
+
static parseAuthCallback(url2, options) {
|
|
12514
|
+
return parseAuthCallback(url2, options);
|
|
12493
12515
|
}
|
|
12494
12516
|
/**
|
|
12495
12517
|
* Build an auth login URL (static utility)
|