@orangecheck/me-client 0.32.2 → 0.32.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/README.md +3 -3
- package/dist/{identity-1VYMOhzV.d.mts → identity-6pjtyKYh.d.mts} +1 -1
- package/dist/{identity-1VYMOhzV.d.ts → identity-6pjtyKYh.d.ts} +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +74 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +74 -22
- package/dist/index.mjs.map +1 -1
- package/dist/integrator.js.map +1 -1
- package/dist/integrator.mjs.map +1 -1
- package/dist/server.d.mts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +72 -21
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +72 -21
- package/dist/server.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1035,6 +1035,7 @@ async function defaultLive() {
|
|
|
1035
1035
|
var federations = { list, live, get, defaultLive };
|
|
1036
1036
|
|
|
1037
1037
|
// src/scope.ts
|
|
1038
|
+
var CONSENT_ORIGIN = "https://ochk.app";
|
|
1038
1039
|
var VALID_SCOPES = [
|
|
1039
1040
|
"bitcoin_address",
|
|
1040
1041
|
"email",
|
|
@@ -1090,7 +1091,7 @@ function request(scopes2, options) {
|
|
|
1090
1091
|
if (typeof window === "undefined") {
|
|
1091
1092
|
throw new Error("oc.scope.request: must be called in a browser environment");
|
|
1092
1093
|
}
|
|
1093
|
-
const origin2 = options.origin ??
|
|
1094
|
+
const origin2 = options.origin ?? CONSENT_ORIGIN;
|
|
1094
1095
|
const url = new URL("/me/scope-grant", origin2);
|
|
1095
1096
|
url.searchParams.set("project_key", options.project_key);
|
|
1096
1097
|
url.searchParams.set("scopes", scopes2.join(","));
|
|
@@ -1232,33 +1233,85 @@ async function verifyEd255192(key, sig, msg) {
|
|
|
1232
1233
|
return false;
|
|
1233
1234
|
}
|
|
1234
1235
|
}
|
|
1236
|
+
var SIGNED_FIELDS = [
|
|
1237
|
+
"v",
|
|
1238
|
+
"kind",
|
|
1239
|
+
"did_oc",
|
|
1240
|
+
"event_count",
|
|
1241
|
+
"human_event_count",
|
|
1242
|
+
"lifetime_sats",
|
|
1243
|
+
"distinct_integrator_count",
|
|
1244
|
+
"oldest_event_at",
|
|
1245
|
+
"active_days",
|
|
1246
|
+
"computed_at",
|
|
1247
|
+
"expires_at"
|
|
1248
|
+
];
|
|
1249
|
+
var COUNTS = [
|
|
1250
|
+
"event_count",
|
|
1251
|
+
"human_event_count",
|
|
1252
|
+
"lifetime_sats",
|
|
1253
|
+
"distinct_integrator_count",
|
|
1254
|
+
"active_days"
|
|
1255
|
+
];
|
|
1256
|
+
function readSignedAttestation(canonical, id) {
|
|
1257
|
+
const text = new TextDecoder().decode(canonical);
|
|
1258
|
+
let parsed;
|
|
1259
|
+
try {
|
|
1260
|
+
parsed = JSON.parse(text);
|
|
1261
|
+
} catch {
|
|
1262
|
+
return null;
|
|
1263
|
+
}
|
|
1264
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
1265
|
+
const o = parsed;
|
|
1266
|
+
if (o.v !== 1 || o.kind !== "oc-me-activity" || typeof o.did_oc !== "string") return null;
|
|
1267
|
+
const countsOk = COUNTS.every((k) => {
|
|
1268
|
+
const n = o[k];
|
|
1269
|
+
return typeof n === "number" && Number.isSafeInteger(n) && n >= 0;
|
|
1270
|
+
});
|
|
1271
|
+
if (!countsOk) return null;
|
|
1272
|
+
if (o.oldest_event_at !== null && typeof o.oldest_event_at !== "string") return null;
|
|
1273
|
+
if (typeof o.computed_at !== "string" || typeof o.expires_at !== "string") return null;
|
|
1274
|
+
const ordered = Object.fromEntries(SIGNED_FIELDS.map((k) => [k, o[k]]));
|
|
1275
|
+
if (JSON.stringify(ordered) !== text) return null;
|
|
1276
|
+
return { id, ...ordered };
|
|
1277
|
+
}
|
|
1278
|
+
function sameAttestation(copy, signed) {
|
|
1279
|
+
const c = copy;
|
|
1280
|
+
const v = signed;
|
|
1281
|
+
return ["id", ...SIGNED_FIELDS].every((k) => c[k] === v[k]);
|
|
1282
|
+
}
|
|
1235
1283
|
async function verifyActivityAttestation(bundle, options = {}) {
|
|
1236
1284
|
const checks = [];
|
|
1237
|
-
const shapeOk = !!bundle && typeof bundle === "object" && typeof bundle.sig === "string" && typeof bundle.kid === "string" && typeof bundle.canonical_b64 === "string" &&
|
|
1285
|
+
const shapeOk = !!bundle && typeof bundle === "object" && typeof bundle.sig === "string" && typeof bundle.kid === "string" && typeof bundle.canonical_b64 === "string" && (bundle.attestation === void 0 || !!bundle.attestation && typeof bundle.attestation === "object");
|
|
1238
1286
|
checks.push({
|
|
1239
1287
|
ok: shapeOk,
|
|
1240
|
-
label: "bundle shape \xB7 sig / kid / canonical_b64
|
|
1288
|
+
label: "bundle shape \xB7 sig / kid / canonical_b64"
|
|
1241
1289
|
});
|
|
1242
1290
|
if (!shapeOk) {
|
|
1243
1291
|
return { ok: false, reason: "bundle shape invalid", checks };
|
|
1244
1292
|
}
|
|
1245
|
-
const a = bundle.attestation;
|
|
1246
1293
|
const canonical = base64ToBytes(bundle.canonical_b64);
|
|
1247
1294
|
checks.push({
|
|
1248
1295
|
ok: canonical !== null,
|
|
1249
1296
|
label: "canonical_b64 decodes",
|
|
1250
1297
|
detail: canonical ? `${canonical.length} bytes` : "invalid base64"
|
|
1251
1298
|
});
|
|
1252
|
-
if (!canonical) return { ok: false, reason: "canonical_b64 invalid base64", checks
|
|
1253
|
-
const
|
|
1254
|
-
const
|
|
1255
|
-
|
|
1299
|
+
if (!canonical) return { ok: false, reason: "canonical_b64 invalid base64", checks };
|
|
1300
|
+
const computedId = bytesToHex(await sha256(canonical));
|
|
1301
|
+
const signed = readSignedAttestation(canonical, computedId);
|
|
1302
|
+
checks.push({
|
|
1303
|
+
ok: signed !== null,
|
|
1304
|
+
label: "canonical_bytes are an oc-me-activity attestation in canonical form"
|
|
1305
|
+
});
|
|
1306
|
+
if (!signed) return { ok: false, reason: "canonical bytes are not an activity attestation", checks };
|
|
1307
|
+
const copy = bundle.attestation;
|
|
1308
|
+
const copyOk = copy === void 0 || sameAttestation(copy, signed);
|
|
1256
1309
|
checks.push({
|
|
1257
|
-
ok:
|
|
1258
|
-
label: "sha256(canonical_bytes)
|
|
1259
|
-
detail:
|
|
1310
|
+
ok: copyOk,
|
|
1311
|
+
label: "attestation === the signed bytes, id = sha256(canonical_bytes)",
|
|
1312
|
+
detail: copyOk ? computedId : "the readable copy differs from what was signed"
|
|
1260
1313
|
});
|
|
1261
|
-
if (!
|
|
1314
|
+
if (!copyOk) return { ok: false, reason: "attestation does not match the signed bytes", checks };
|
|
1262
1315
|
let key = null;
|
|
1263
1316
|
if (options.jwk) {
|
|
1264
1317
|
if (options.jwk.kid !== bundle.kid) {
|
|
@@ -1267,7 +1320,7 @@ async function verifyActivityAttestation(bundle, options = {}) {
|
|
|
1267
1320
|
label: "JWK with matching kid present",
|
|
1268
1321
|
detail: `provided jwk.kid=${options.jwk.kid} but bundle.kid=${bundle.kid}`
|
|
1269
1322
|
});
|
|
1270
|
-
return { ok: false, reason: "kid mismatch with provided jwk", checks
|
|
1323
|
+
return { ok: false, reason: "kid mismatch with provided jwk", checks };
|
|
1271
1324
|
}
|
|
1272
1325
|
try {
|
|
1273
1326
|
key = await importJWK(options.jwk, "EdDSA");
|
|
@@ -1278,7 +1331,7 @@ async function verifyActivityAttestation(bundle, options = {}) {
|
|
|
1278
1331
|
label: "JWK with matching kid present",
|
|
1279
1332
|
detail: `provided jwk failed import: ${err.message}`
|
|
1280
1333
|
});
|
|
1281
|
-
return { ok: false, reason: "provided jwk failed import", checks
|
|
1334
|
+
return { ok: false, reason: "provided jwk failed import", checks };
|
|
1282
1335
|
}
|
|
1283
1336
|
} else {
|
|
1284
1337
|
const issuer = options.issuer ?? DEFAULT_ISSUER2;
|
|
@@ -1297,7 +1350,7 @@ async function verifyActivityAttestation(bundle, options = {}) {
|
|
|
1297
1350
|
detail: key ? `kid ${bundle.kid}` : `no JWK with kid ${bundle.kid} at ${issuer}${ENVELOPE_JWKS_PATH}`
|
|
1298
1351
|
});
|
|
1299
1352
|
if (!key) {
|
|
1300
|
-
return { ok: false, reason: `kid ${bundle.kid} not in envelope JWKS`, checks
|
|
1353
|
+
return { ok: false, reason: `kid ${bundle.kid} not in envelope JWKS`, checks };
|
|
1301
1354
|
}
|
|
1302
1355
|
} catch (err) {
|
|
1303
1356
|
checks.push({
|
|
@@ -1308,8 +1361,7 @@ async function verifyActivityAttestation(bundle, options = {}) {
|
|
|
1308
1361
|
return {
|
|
1309
1362
|
ok: false,
|
|
1310
1363
|
reason: `envelope JWKS unavailable: ${err.message}`,
|
|
1311
|
-
checks
|
|
1312
|
-
attestation: a
|
|
1364
|
+
checks
|
|
1313
1365
|
};
|
|
1314
1366
|
}
|
|
1315
1367
|
}
|
|
@@ -1320,7 +1372,7 @@ async function verifyActivityAttestation(bundle, options = {}) {
|
|
|
1320
1372
|
label: "ed25519.verify(sig, canonical_bytes, jwk.public)",
|
|
1321
1373
|
detail: "malformed sig (expected hex)"
|
|
1322
1374
|
});
|
|
1323
|
-
return { ok: false, reason: "malformed sig", checks
|
|
1375
|
+
return { ok: false, reason: "malformed sig", checks };
|
|
1324
1376
|
}
|
|
1325
1377
|
const sigOk = await verifyEd255192(key, sigBytes, canonical);
|
|
1326
1378
|
checks.push({
|
|
@@ -1328,17 +1380,17 @@ async function verifyActivityAttestation(bundle, options = {}) {
|
|
|
1328
1380
|
label: "ed25519.verify(sig, canonical_bytes, jwk.public)",
|
|
1329
1381
|
detail: sigOk ? "signature valid" : "signature does not match"
|
|
1330
1382
|
});
|
|
1331
|
-
if (!sigOk) return { ok: false, reason: "signature does not match", checks
|
|
1383
|
+
if (!sigOk) return { ok: false, reason: "signature does not match", checks };
|
|
1332
1384
|
const now = options.now ?? /* @__PURE__ */ new Date();
|
|
1333
|
-
const expiresMs = Date.parse(
|
|
1385
|
+
const expiresMs = Date.parse(signed.expires_at);
|
|
1334
1386
|
const freshOk = Number.isFinite(expiresMs) && expiresMs > now.getTime();
|
|
1335
1387
|
checks.push({
|
|
1336
1388
|
ok: freshOk,
|
|
1337
1389
|
label: "now < attestation.expires_at",
|
|
1338
1390
|
detail: freshOk ? `expires ${new Date(expiresMs).toISOString()}` : "attestation has expired"
|
|
1339
1391
|
});
|
|
1340
|
-
if (!freshOk) return { ok: false, reason: "attestation has expired", checks
|
|
1341
|
-
return { ok: true, attestation:
|
|
1392
|
+
if (!freshOk) return { ok: false, reason: "attestation has expired", checks };
|
|
1393
|
+
return { ok: true, attestation: signed, checks };
|
|
1342
1394
|
}
|
|
1343
1395
|
async function refreshEnvelopeJwks(issuer = DEFAULT_ISSUER2) {
|
|
1344
1396
|
jwksCache2.delete(issuer);
|