@atlasauth/backend 0.27.0 → 0.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/README.md +19 -2
- package/dist/botid.js +3 -3
- package/dist/botid.js.map +1 -1
- package/dist/client/api-keys.d.ts +26 -3
- package/dist/client/api-keys.js.map +1 -1
- package/dist/client/app-events.d.ts +129 -0
- package/dist/client/app-events.js +80 -0
- package/dist/client/app-events.js.map +1 -0
- package/dist/client/import-export.d.ts +3 -0
- package/dist/client/import-export.js.map +1 -1
- package/dist/client/index.d.ts +75 -1
- package/dist/client/index.js +4 -0
- package/dist/client/index.js.map +1 -1
- package/dist/client/instance.d.ts +78 -0
- package/dist/client/instance.js +22 -0
- package/dist/client/instance.js.map +1 -1
- package/dist/client/messaging.d.ts +28 -8
- package/dist/client/messaging.js +5 -1
- package/dist/client/messaging.js.map +1 -1
- package/dist/client/privacy.d.ts +53 -0
- package/dist/client/privacy.js +10 -0
- package/dist/client/privacy.js.map +1 -1
- package/dist/client/referrals.d.ts +20 -1
- package/dist/client/referrals.js.map +1 -1
- package/dist/client/sessions.d.ts +31 -0
- package/dist/client/sessions.js +9 -0
- package/dist/client/sessions.js.map +1 -1
- package/dist/client/sign-in-tokens.d.ts +5 -1
- package/dist/client/sign-in-tokens.js +5 -1
- package/dist/client/sign-in-tokens.js.map +1 -1
- package/dist/client/test-mode.d.ts +17 -0
- package/dist/client/test-mode.js +8 -0
- package/dist/client/test-mode.js.map +1 -1
- package/dist/client/users.d.ts +30 -0
- package/dist/client/users.js.map +1 -1
- package/dist/client/webhooks.d.ts +2 -1
- package/dist/client/webhooks.js.map +1 -1
- package/dist/edge-crypto.d.ts +13 -0
- package/dist/edge-crypto.js +46 -0
- package/dist/edge-crypto.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/dist/key-mirror.d.ts +109 -0
- package/dist/key-mirror.js +209 -0
- package/dist/key-mirror.js.map +1 -0
- package/dist/policy-source.js +4 -4
- package/dist/policy-source.js.map +1 -1
- package/dist/referral-test-calls.js +8 -8
- package/dist/referral-test-calls.js.map +1 -1
- package/dist/webhooks.d.ts +31 -0
- package/dist/webhooks.js +59 -6
- package/dist/webhooks.js.map +1 -1
- package/package.json +1 -1
|
@@ -7,7 +7,7 @@ exports.referalliSignature = referalliSignature;
|
|
|
7
7
|
exports.referalliSignatureV2 = referalliSignatureV2;
|
|
8
8
|
exports.signReferalliCall = signReferalliCall;
|
|
9
9
|
exports.signReferralUpdatedEvent = signReferralUpdatedEvent;
|
|
10
|
-
const
|
|
10
|
+
const edge_crypto_1 = require("./edge-crypto");
|
|
11
11
|
const referrals_1 = require("./referrals");
|
|
12
12
|
function signed(url, method, headers, body) {
|
|
13
13
|
return {
|
|
@@ -23,14 +23,14 @@ const trimBase = (base) => base.replace(/\/+$/, '');
|
|
|
23
23
|
function referralEmailHash(email) {
|
|
24
24
|
if (!email)
|
|
25
25
|
return null;
|
|
26
|
-
return (0,
|
|
26
|
+
return (0, edge_crypto_1.createHash)('sha256').update(email.trim().toLowerCase()).digest('hex');
|
|
27
27
|
}
|
|
28
28
|
/** A call in the Atlas referral protocol, signed exactly as an Atlas instance signs it. */
|
|
29
29
|
function signAtlasReferralCall(options) {
|
|
30
|
-
const id = options.callId ?? `rfc_test_${(0,
|
|
30
|
+
const id = options.callId ?? `rfc_test_${(0, edge_crypto_1.randomBytes)(8).toString('hex')}`;
|
|
31
31
|
const timestamp = options.now ?? Date.now();
|
|
32
32
|
const body = JSON.stringify({ op: options.op, ...options.payload });
|
|
33
|
-
const signature = (0,
|
|
33
|
+
const signature = (0, edge_crypto_1.createHmac)('sha256', options.secret).update(`${id}.${timestamp}.${body}`).digest('base64');
|
|
34
34
|
const headers = {
|
|
35
35
|
'content-type': 'application/json',
|
|
36
36
|
'atlas-id': id,
|
|
@@ -50,7 +50,7 @@ exports.REFERALLI_API_VERSION = '2026-10-21';
|
|
|
50
50
|
* v2 together.
|
|
51
51
|
*/
|
|
52
52
|
function referalliSignature(secret, payload, unixSeconds) {
|
|
53
|
-
const mac = (0,
|
|
53
|
+
const mac = (0, edge_crypto_1.createHmac)('sha256', secret).update(`${unixSeconds}.${payload}`).digest('hex');
|
|
54
54
|
return `t=${unixSeconds},v1=${mac}`;
|
|
55
55
|
}
|
|
56
56
|
/**
|
|
@@ -60,7 +60,7 @@ function referalliSignature(secret, payload, unixSeconds) {
|
|
|
60
60
|
*/
|
|
61
61
|
function referalliSignatureV2(secret, parts, unixSeconds) {
|
|
62
62
|
const body = parts.method === 'GET' ? '' : parts.payload;
|
|
63
|
-
const v2 = (0,
|
|
63
|
+
const v2 = (0, edge_crypto_1.createHmac)('sha256', secret)
|
|
64
64
|
.update(`${unixSeconds}.${parts.method}.${parts.pathAndQuery}.${body}`)
|
|
65
65
|
.digest('hex');
|
|
66
66
|
return `${referalliSignature(secret, parts.payload, unixSeconds)},v2=${v2}`;
|
|
@@ -106,7 +106,7 @@ function signReferralUpdatedEvent(options) {
|
|
|
106
106
|
if (!event.customerRef && !event.referralId) {
|
|
107
107
|
throw new Error('signReferralUpdatedEvent: the event needs customerRef or referralId.');
|
|
108
108
|
}
|
|
109
|
-
const id = options.eventId ?? `rfe_${(0,
|
|
109
|
+
const id = options.eventId ?? `rfe_${(0, edge_crypto_1.randomBytes)(8).toString('hex')}`;
|
|
110
110
|
const timestamp = options.now ?? Date.now();
|
|
111
111
|
const occurred = options.occurredAt ?? timestamp;
|
|
112
112
|
const body = JSON.stringify({
|
|
@@ -114,7 +114,7 @@ function signReferralUpdatedEvent(options) {
|
|
|
114
114
|
occurredAt: typeof occurred === 'number' ? new Date(occurred).toISOString() : occurred,
|
|
115
115
|
...event,
|
|
116
116
|
});
|
|
117
|
-
const signature = (0,
|
|
117
|
+
const signature = (0, edge_crypto_1.createHmac)('sha256', options.secret).update(`${id}.${timestamp}.${body}`).digest('base64');
|
|
118
118
|
const headers = {
|
|
119
119
|
'content-type': 'application/json',
|
|
120
120
|
'atlas-id': id,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"referral-test-calls.js","sourceRoot":"","sources":["../src/referral-test-calls.ts"],"names":[],"mappings":";;;AAiDA,8CAGC;AAiBD,sDAeC;AA+BD,gDAGC;AAOD,oDAUC;AAGD,8CA0BC;AAsCD,4DAuBC;AAjOD
|
|
1
|
+
{"version":3,"file":"referral-test-calls.js","sourceRoot":"","sources":["../src/referral-test-calls.ts"],"names":[],"mappings":"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"}
|
package/dist/webhooks.d.ts
CHANGED
|
@@ -61,4 +61,35 @@ export interface VerifyWebhookInput {
|
|
|
61
61
|
* ```
|
|
62
62
|
*/
|
|
63
63
|
export declare function verifyWebhook<T = unknown>(input: VerifyWebhookInput): WebhookVerifyResult<T>;
|
|
64
|
+
/** Standard Webhooks header names, as application webhooks send them (lower-case). */
|
|
65
|
+
export declare const STANDARD_WEBHOOK_HEADERS: {
|
|
66
|
+
readonly id: "webhook-id";
|
|
67
|
+
readonly timestamp: "webhook-timestamp";
|
|
68
|
+
readonly signature: "webhook-signature";
|
|
69
|
+
};
|
|
70
|
+
export interface VerifyStandardWebhookInput {
|
|
71
|
+
/** The RAW request body as received — a string or Buffer, NOT a parsed object. */
|
|
72
|
+
body: string | Buffer;
|
|
73
|
+
headers: HeadersLike;
|
|
74
|
+
/** The endpoint's `whsec_…` secret. */
|
|
75
|
+
secret: string;
|
|
76
|
+
now?: Date;
|
|
77
|
+
/** Override the ±replay tolerance in seconds (default 300). */
|
|
78
|
+
toleranceSec?: number;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Verify an APPLICATION webhook (the events an app publishes to its customers'
|
|
82
|
+
* endpoints through Atlas): Standard Webhooks — `webhook-id`,
|
|
83
|
+
* `webhook-timestamp` (seconds), `webhook-signature: v1,<base64>` (one entry
|
|
84
|
+
* per secret during a rotation), HMAC-SHA256 over `<id>.<timestamp>.<rawBody>`
|
|
85
|
+
* keyed with the base64-decoded part of `whsec_<base64>`. Any Standard Webhooks
|
|
86
|
+
* library verifies the same deliveries; this one has no dependencies. Never
|
|
87
|
+
* throws: `{ verified, reason?, event?, deliveryId?, timestamp? }`, where
|
|
88
|
+
* `deliveryId` (the `webhook-id`) is stable across retries — dedupe on it.
|
|
89
|
+
*
|
|
90
|
+
* ```ts
|
|
91
|
+
* const { verified, event } = verifyStandardWebhook({ body: rawBody, headers: req.headers, secret: 'whsec_…' });
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
94
|
+
export declare function verifyStandardWebhook<T = unknown>(input: VerifyStandardWebhookInput): WebhookVerifyResult<T>;
|
|
64
95
|
export {};
|
package/dist/webhooks.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ATLAS_WEBHOOK_HEADERS = void 0;
|
|
3
|
+
exports.STANDARD_WEBHOOK_HEADERS = exports.ATLAS_WEBHOOK_HEADERS = void 0;
|
|
4
4
|
exports.verifyWebhook = verifyWebhook;
|
|
5
|
-
|
|
5
|
+
exports.verifyStandardWebhook = verifyStandardWebhook;
|
|
6
|
+
const edge_crypto_1 = require("./edge-crypto");
|
|
6
7
|
/**
|
|
7
8
|
* §12.2 — verify an inbound Atlas webhook, for the CUSTOMER consuming events.
|
|
8
9
|
*
|
|
@@ -99,19 +100,19 @@ function verifyWebhook(input) {
|
|
|
99
100
|
if (!Number.isFinite(timestamp) || Math.abs(now - timestamp) > tolerance) {
|
|
100
101
|
return { verified: false, reason: 'stale_timestamp' };
|
|
101
102
|
}
|
|
102
|
-
const expected = Buffer.from((0,
|
|
103
|
+
const expected = Buffer.from((0, edge_crypto_1.createHmac)('sha256', input.secret).update(`${id}.${timestamp}.${raw}`).digest('base64'));
|
|
103
104
|
// Compare every entry (no early exit), each in constant time.
|
|
104
105
|
let matched = false;
|
|
105
106
|
for (const candidate of provided) {
|
|
106
107
|
const a = Buffer.from(candidate);
|
|
107
|
-
if (a.length === expected.length && (0,
|
|
108
|
+
if (a.length === expected.length && (0, edge_crypto_1.timingSafeEqual)(a, expected))
|
|
108
109
|
matched = true;
|
|
109
110
|
}
|
|
110
111
|
if (input.url) {
|
|
111
|
-
const expectedV2 = Buffer.from((0,
|
|
112
|
+
const expectedV2 = Buffer.from((0, edge_crypto_1.createHmac)('sha256', input.secret).update(`${id}.${timestamp}.${input.url}.${raw}`).digest('base64'));
|
|
112
113
|
for (const candidate of providedV2) {
|
|
113
114
|
const a = Buffer.from(candidate);
|
|
114
|
-
if (a.length === expectedV2.length && (0,
|
|
115
|
+
if (a.length === expectedV2.length && (0, edge_crypto_1.timingSafeEqual)(a, expectedV2))
|
|
115
116
|
matched = true;
|
|
116
117
|
}
|
|
117
118
|
}
|
|
@@ -125,4 +126,56 @@ function verifyWebhook(input) {
|
|
|
125
126
|
return { verified: true, deliveryId: id, timestamp };
|
|
126
127
|
}
|
|
127
128
|
}
|
|
129
|
+
/** Standard Webhooks header names, as application webhooks send them (lower-case). */
|
|
130
|
+
exports.STANDARD_WEBHOOK_HEADERS = {
|
|
131
|
+
id: 'webhook-id',
|
|
132
|
+
timestamp: 'webhook-timestamp',
|
|
133
|
+
signature: 'webhook-signature',
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Verify an APPLICATION webhook (the events an app publishes to its customers'
|
|
137
|
+
* endpoints through Atlas): Standard Webhooks — `webhook-id`,
|
|
138
|
+
* `webhook-timestamp` (seconds), `webhook-signature: v1,<base64>` (one entry
|
|
139
|
+
* per secret during a rotation), HMAC-SHA256 over `<id>.<timestamp>.<rawBody>`
|
|
140
|
+
* keyed with the base64-decoded part of `whsec_<base64>`. Any Standard Webhooks
|
|
141
|
+
* library verifies the same deliveries; this one has no dependencies. Never
|
|
142
|
+
* throws: `{ verified, reason?, event?, deliveryId?, timestamp? }`, where
|
|
143
|
+
* `deliveryId` (the `webhook-id`) is stable across retries — dedupe on it.
|
|
144
|
+
*
|
|
145
|
+
* ```ts
|
|
146
|
+
* const { verified, event } = verifyStandardWebhook({ body: rawBody, headers: req.headers, secret: 'whsec_…' });
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
function verifyStandardWebhook(input) {
|
|
150
|
+
const raw = typeof input.body === 'string' ? input.body : input.body.toString('utf8');
|
|
151
|
+
const id = readHeader(input.headers, exports.STANDARD_WEBHOOK_HEADERS.id);
|
|
152
|
+
const timestampRaw = readHeader(input.headers, exports.STANDARD_WEBHOOK_HEADERS.timestamp);
|
|
153
|
+
const signature = readHeader(input.headers, exports.STANDARD_WEBHOOK_HEADERS.signature);
|
|
154
|
+
if (!id || !timestampRaw || !signature)
|
|
155
|
+
return { verified: false, reason: 'missing_headers' };
|
|
156
|
+
const provided = parseSignatures(signature);
|
|
157
|
+
if (provided.length === 0)
|
|
158
|
+
return { verified: false, reason: 'malformed_signature' };
|
|
159
|
+
const timestamp = /^\d+$/.test(timestampRaw) ? Number(timestampRaw) : NaN;
|
|
160
|
+
const nowSec = Math.floor((input.now ?? new Date()).getTime() / 1000);
|
|
161
|
+
if (!Number.isFinite(timestamp) || Math.abs(nowSec - timestamp) > (input.toleranceSec ?? REPLAY_TOLERANCE_MS / 1000)) {
|
|
162
|
+
return { verified: false, reason: 'stale_timestamp' };
|
|
163
|
+
}
|
|
164
|
+
const key = Buffer.from(input.secret.startsWith('whsec_') ? input.secret.slice('whsec_'.length) : input.secret, 'base64');
|
|
165
|
+
const expected = Buffer.from((0, edge_crypto_1.createHmac)('sha256', key).update(`${id}.${timestamp}.${raw}`).digest('base64'));
|
|
166
|
+
let matched = false;
|
|
167
|
+
for (const candidate of provided) {
|
|
168
|
+
const a = Buffer.from(candidate);
|
|
169
|
+
if (a.length === expected.length && (0, edge_crypto_1.timingSafeEqual)(a, expected))
|
|
170
|
+
matched = true;
|
|
171
|
+
}
|
|
172
|
+
if (!matched)
|
|
173
|
+
return { verified: false, reason: 'signature_mismatch' };
|
|
174
|
+
try {
|
|
175
|
+
return { verified: true, event: JSON.parse(raw), deliveryId: id, timestamp };
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return { verified: true, deliveryId: id, timestamp };
|
|
179
|
+
}
|
|
180
|
+
}
|
|
128
181
|
//# sourceMappingURL=webhooks.js.map
|
package/dist/webhooks.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":";;;AA8HA,sCA8CC;
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"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"}
|