@human-gateway/sdk 0.0.1 → 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +629 -8
- package/dist/chunk-3SSCLKQD.js +2 -0
- package/dist/chunk-3SSCLKQD.js.map +1 -0
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +19 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/server.cjs +2 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +15 -0
- package/dist/server.d.ts +15 -0
- package/dist/server.js +2 -0
- package/dist/server.js.map +1 -0
- package/dist/types-D8bnQbLL.d.cts +82 -0
- package/dist/types-D8bnQbLL.d.ts +82 -0
- package/package.json +46 -16
- package/index.js +0 -5
package/README.md
CHANGED
|
@@ -1,21 +1,642 @@
|
|
|
1
1
|
# Human Gateway SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Human Gateway SDK lets partners add privacy-first human verification and human authentication to their apps without handling identity, biometrics, World ID internals, nullifiers, or proof verification logic.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Human Gateway is designed around two identifiers:
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```txt
|
|
8
|
+
projectId -> identifies your Human Gateway project
|
|
9
|
+
actionKey -> identifies the specific verify/auth flow inside that project
|
|
10
|
+
```
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
For production integrations, pass an `actionKey` explicitly.
|
|
10
13
|
|
|
11
|
-
|
|
14
|
+
---
|
|
12
15
|
|
|
13
|
-
##
|
|
16
|
+
## Installation
|
|
14
17
|
|
|
15
18
|
```bash
|
|
16
19
|
npm install @human-gateway/sdk
|
|
17
20
|
```
|
|
18
21
|
|
|
19
|
-
|
|
22
|
+
> The SDK is currently in alpha. Package publication should be handled as a controlled release step. For local development, use the package from the Human Gateway monorepo.
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Quickstart: Verify a human
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { HumanGateway } from "@human-gateway/sdk";
|
|
30
|
+
|
|
31
|
+
const hg = new HumanGateway({
|
|
32
|
+
projectId: "project_xxx",
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const result = await hg.verify({
|
|
36
|
+
actionKey: "hg_verify_action_key_xxx",
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
if (result.verified_human) {
|
|
40
|
+
// Hide verify button
|
|
41
|
+
// Show verified badge
|
|
42
|
+
// Optionally wait for the signed backend callback before persisting state
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Example verification result:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"success": true,
|
|
51
|
+
"verified_human": true,
|
|
52
|
+
"unique_for_partner": true,
|
|
53
|
+
"already_verified": false,
|
|
54
|
+
"project_id": "project_xxx"
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Quickstart: Sign in a verified human
|
|
61
|
+
|
|
62
|
+
```ts
|
|
63
|
+
import { HumanGateway } from "@human-gateway/sdk";
|
|
64
|
+
|
|
65
|
+
const hg = new HumanGateway({
|
|
66
|
+
projectId: "project_xxx",
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
const result = await hg.auth({
|
|
70
|
+
actionKey: "hg_auth_action_key_xxx",
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (result.success && result.verified_human) {
|
|
74
|
+
// Update your UI
|
|
75
|
+
// Store the returned partner-scoped session only according to your own app flow
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Example auth result:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"success": true,
|
|
84
|
+
"event": "auth.completed",
|
|
85
|
+
"verified_human": true,
|
|
86
|
+
"partner_user_id": "partner_user_xxx",
|
|
87
|
+
"auth_session_id": "auth_session_xxx",
|
|
88
|
+
"project_id": "project_xxx",
|
|
89
|
+
"expires_at": "2026-06-25T00:00:00.000Z"
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Project vs Action
|
|
96
|
+
|
|
97
|
+
A Human Gateway project represents one partner integration.
|
|
98
|
+
|
|
99
|
+
An action represents a specific flow inside that project.
|
|
100
|
+
|
|
101
|
+
Example:
|
|
102
|
+
|
|
103
|
+
```txt
|
|
104
|
+
Project: My SaaS App
|
|
105
|
+
|
|
106
|
+
Actions:
|
|
107
|
+
- Verify signup
|
|
108
|
+
- Auth login
|
|
109
|
+
- Verify voting
|
|
110
|
+
- Auth dashboard access
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Use the same `projectId` for the project and pass the correct `actionKey` for the flow you want to run.
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
await hg.verify({
|
|
117
|
+
actionKey: "hg_verify_signup_xxx",
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
await hg.auth({
|
|
121
|
+
actionKey: "hg_auth_login_xxx",
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
If `actionKey` is omitted, Human Gateway may use a fallback active action for compatibility. Explicit `actionKey` usage is recommended for production integrations.
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## What Human Gateway does
|
|
130
|
+
|
|
131
|
+
Human Gateway verifies that a real human completed a World ID proof inside a specific project/action context.
|
|
132
|
+
|
|
133
|
+
Human Gateway does **not** expose:
|
|
134
|
+
|
|
135
|
+
* personal identity
|
|
136
|
+
* emails
|
|
137
|
+
* names
|
|
138
|
+
* biometrics
|
|
139
|
+
* World ID nullifiers
|
|
140
|
+
* raw World ID proof data
|
|
141
|
+
* internal Human Gateway user records
|
|
142
|
+
|
|
143
|
+
The partner receives only scoped results needed to update product behavior.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Frontend options
|
|
148
|
+
|
|
149
|
+
```ts
|
|
150
|
+
const result = await hg.verify({
|
|
151
|
+
actionKey: "hg_verify_action_key_xxx",
|
|
152
|
+
onOpen: () => {
|
|
153
|
+
console.log("Verification popup opened");
|
|
154
|
+
},
|
|
155
|
+
onSuccess: (result) => {
|
|
156
|
+
console.log("Verification completed:", result);
|
|
157
|
+
},
|
|
158
|
+
onError: (error) => {
|
|
159
|
+
console.error("Verification failed:", error.code);
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
```ts
|
|
165
|
+
const result = await hg.auth({
|
|
166
|
+
actionKey: "hg_auth_action_key_xxx",
|
|
167
|
+
onOpen: () => {
|
|
168
|
+
console.log("Auth popup opened");
|
|
169
|
+
},
|
|
170
|
+
onSuccess: (result) => {
|
|
171
|
+
console.log("Auth completed:", result);
|
|
172
|
+
},
|
|
173
|
+
onError: (error) => {
|
|
174
|
+
console.error("Auth failed:", error.code);
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## SDK configuration
|
|
182
|
+
|
|
183
|
+
```ts
|
|
184
|
+
const hg = new HumanGateway({
|
|
185
|
+
projectId: "project_xxx",
|
|
186
|
+
environment: "production",
|
|
187
|
+
mode: "auto",
|
|
188
|
+
timeoutMs: 300000,
|
|
189
|
+
});
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Available options:
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
type HumanGatewayOptions = {
|
|
196
|
+
projectId: string;
|
|
197
|
+
environment?: "production" | "staging" | "development";
|
|
198
|
+
mode?: "auto" | "popup" | "modal" | "redirect";
|
|
199
|
+
baseUrl?: string;
|
|
200
|
+
timeoutMs?: number;
|
|
201
|
+
};
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Alpha behavior:
|
|
205
|
+
|
|
206
|
+
* `popup` is supported.
|
|
207
|
+
* `auto` currently uses popup behavior.
|
|
208
|
+
* `modal` is planned.
|
|
209
|
+
* `redirect` is planned.
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
## Verify options
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
type HumanGatewayVerifyOptions = {
|
|
217
|
+
actionKey?: string;
|
|
218
|
+
onOpen?: () => void;
|
|
219
|
+
onClose?: () => void;
|
|
220
|
+
onSuccess?: (result: HumanGatewayResult) => void;
|
|
221
|
+
onError?: (error: HumanGatewayError) => void;
|
|
222
|
+
};
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Verify result:
|
|
226
|
+
|
|
227
|
+
```ts
|
|
228
|
+
type HumanGatewayResult = {
|
|
229
|
+
success: boolean;
|
|
230
|
+
verified_human: boolean;
|
|
231
|
+
unique_for_partner: boolean;
|
|
232
|
+
already_verified: boolean;
|
|
233
|
+
project_id: string;
|
|
234
|
+
};
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Auth options
|
|
240
|
+
|
|
241
|
+
```ts
|
|
242
|
+
type HumanGatewayAuthOptions = {
|
|
243
|
+
actionKey?: string;
|
|
244
|
+
onOpen?: () => void;
|
|
245
|
+
onClose?: () => void;
|
|
246
|
+
onSuccess?: (result: HumanGatewayAuthResult) => void;
|
|
247
|
+
onError?: (error: HumanGatewayError) => void;
|
|
248
|
+
};
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Auth result:
|
|
252
|
+
|
|
253
|
+
```ts
|
|
254
|
+
type HumanGatewayAuthResult = {
|
|
255
|
+
success: boolean;
|
|
256
|
+
event?: "auth.completed";
|
|
257
|
+
verified_human: boolean;
|
|
258
|
+
partner_user_id: string;
|
|
259
|
+
auth_session_id: string;
|
|
260
|
+
project_id: string;
|
|
261
|
+
expires_at: string;
|
|
262
|
+
};
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Popup behavior
|
|
268
|
+
|
|
269
|
+
The SDK opens a Human Gateway hosted flow in a centered browser popup.
|
|
270
|
+
|
|
271
|
+
This is expected behavior:
|
|
272
|
+
|
|
273
|
+
* The popup may show the browser address bar.
|
|
274
|
+
* The popup may be resizable or maximizable depending on the browser.
|
|
275
|
+
* The popup attempts to close itself after a successful flow.
|
|
276
|
+
* Some browsers may prevent programmatic closing; in that case, the user can close it manually.
|
|
277
|
+
|
|
278
|
+
The visible address bar is intentional and useful: it lets users confirm they are interacting with a legitimate Human Gateway domain.
|
|
279
|
+
|
|
280
|
+
### User gesture requirement
|
|
281
|
+
|
|
282
|
+
Call `hg.verify()` or `hg.auth()` directly from a user action such as a button click.
|
|
283
|
+
|
|
284
|
+
Modern browsers may block popups if they are opened after a long asynchronous operation, delayed promise, timer, or background task. For the best success rate, start the Human Gateway flow immediately inside the user interaction handler.
|
|
285
|
+
|
|
286
|
+
Recommended:
|
|
287
|
+
|
|
288
|
+
```ts
|
|
289
|
+
button.addEventListener("click", async () => {
|
|
290
|
+
const result = await hg.verify({
|
|
291
|
+
actionKey: "hg_verify_action_key_xxx",
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
console.log(result);
|
|
295
|
+
});
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
Avoid delaying the popup:
|
|
299
|
+
|
|
300
|
+
```ts
|
|
301
|
+
button.addEventListener("click", async () => {
|
|
302
|
+
await doLongAsyncWork();
|
|
303
|
+
|
|
304
|
+
const result = await hg.verify({
|
|
305
|
+
actionKey: "hg_verify_action_key_xxx",
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
console.log(result);
|
|
309
|
+
});
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## Frontend result vs backend callback
|
|
315
|
+
|
|
316
|
+
The frontend SDK result is useful for immediate UI updates.
|
|
317
|
+
|
|
318
|
+
The signed backend callback should be treated as the durable source of truth.
|
|
319
|
+
|
|
320
|
+
```txt
|
|
321
|
+
Frontend result -> update UI
|
|
322
|
+
Signed callback -> persist verified/auth state in partner backend
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
A malicious user can manipulate frontend state. They cannot forge a valid Human Gateway callback without the callback secret.
|
|
326
|
+
|
|
327
|
+
---
|
|
328
|
+
|
|
329
|
+
## Backend callback verification
|
|
330
|
+
|
|
331
|
+
Human Gateway sends signed callbacks to the partner backend.
|
|
332
|
+
|
|
333
|
+
Server-side helpers are exported from `@human-gateway/sdk/server`.
|
|
334
|
+
|
|
335
|
+
You do not need to create a `HumanGateway` instance on your backend. The server helpers are pure functions designed to validate callback requests using the raw request body, signed headers, and your project callback secret.
|
|
336
|
+
|
|
337
|
+
Callback headers:
|
|
338
|
+
|
|
339
|
+
```txt
|
|
340
|
+
x-hg-event-id
|
|
341
|
+
x-hg-event
|
|
342
|
+
x-hg-project-id
|
|
343
|
+
x-hg-timestamp
|
|
344
|
+
x-hg-signature
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Example callback payload:
|
|
348
|
+
|
|
349
|
+
```json
|
|
350
|
+
{
|
|
351
|
+
"event_id": "callback_event_xxx",
|
|
352
|
+
"event": "verification.completed",
|
|
353
|
+
"success": true,
|
|
354
|
+
"verified_human": true,
|
|
355
|
+
"unique_for_partner": false,
|
|
356
|
+
"already_verified": true,
|
|
357
|
+
"project_id": "project_xxx",
|
|
358
|
+
"created_at": "2026-06-25T00:00:00.000Z"
|
|
359
|
+
}
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Recommended callback verification
|
|
365
|
+
|
|
366
|
+
Use `verifyCallback` when you want Human Gateway to validate the signature, timestamp, required headers, JSON payload, event id, event type, and project id consistency.
|
|
367
|
+
|
|
368
|
+
```ts
|
|
369
|
+
import { verifyCallback } from "@human-gateway/sdk/server";
|
|
370
|
+
|
|
371
|
+
export async function POST(request: Request) {
|
|
372
|
+
const body = await request.text();
|
|
373
|
+
|
|
374
|
+
try {
|
|
375
|
+
const callback = verifyCallback({
|
|
376
|
+
body,
|
|
377
|
+
headers: request.headers,
|
|
378
|
+
// Use the callback secret configured for this project in Partner Console.
|
|
379
|
+
// You can generate or rotate it from the project callback settings.
|
|
380
|
+
secret: process.env.HG_CALLBACK_SECRET!,
|
|
381
|
+
expectedProjectId: "project_xxx",
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
if (callback.event === "verification.completed") {
|
|
385
|
+
const payload = callback.payload;
|
|
386
|
+
|
|
387
|
+
if (payload.verified_human === true) {
|
|
388
|
+
// Persist verified state in your backend
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
if (callback.event === "auth.completed") {
|
|
393
|
+
const payload = callback.payload;
|
|
394
|
+
|
|
395
|
+
if (payload.verified_human === true) {
|
|
396
|
+
// Persist or reconcile auth state in your backend
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return Response.json({ success: true });
|
|
401
|
+
} catch {
|
|
402
|
+
return new Response("Invalid Human Gateway callback", {
|
|
403
|
+
status: 401,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Low-level signature verification
|
|
412
|
+
|
|
413
|
+
Use `verifyCallbackSignature` only if you want to verify the signature yourself and handle payload/header validation manually.
|
|
414
|
+
|
|
415
|
+
```ts
|
|
416
|
+
import { verifyCallbackSignature } from "@human-gateway/sdk/server";
|
|
417
|
+
|
|
418
|
+
export async function POST(request: Request) {
|
|
419
|
+
const rawBody = await request.text();
|
|
420
|
+
|
|
421
|
+
const isValid = verifyCallbackSignature({
|
|
422
|
+
rawBody,
|
|
423
|
+
timestamp: request.headers.get("x-hg-timestamp"),
|
|
424
|
+
signature: request.headers.get("x-hg-signature"),
|
|
425
|
+
// Use the callback secret configured for this project in Partner Console.
|
|
426
|
+
// You can generate or rotate it from the project callback settings.
|
|
427
|
+
secret: process.env.HG_CALLBACK_SECRET!,
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
if (!isValid) {
|
|
431
|
+
return new Response("Invalid Human Gateway signature", {
|
|
432
|
+
status: 401,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const payload = JSON.parse(rawBody);
|
|
437
|
+
|
|
438
|
+
return Response.json({
|
|
439
|
+
success: true,
|
|
440
|
+
event: payload.event,
|
|
441
|
+
});
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## Callback verification errors
|
|
448
|
+
|
|
449
|
+
```ts
|
|
450
|
+
type HumanGatewayCallbackErrorCode =
|
|
451
|
+
| "callback_missing_body"
|
|
452
|
+
| "callback_missing_secret"
|
|
453
|
+
| "callback_missing_header"
|
|
454
|
+
| "callback_invalid_timestamp"
|
|
455
|
+
| "callback_expired_timestamp"
|
|
456
|
+
| "callback_invalid_signature_format"
|
|
457
|
+
| "callback_invalid_signature"
|
|
458
|
+
| "callback_invalid_json"
|
|
459
|
+
| "callback_invalid_payload"
|
|
460
|
+
| "callback_event_id_mismatch"
|
|
461
|
+
| "callback_event_type_mismatch"
|
|
462
|
+
| "callback_project_id_mismatch";
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
Example:
|
|
466
|
+
|
|
467
|
+
```ts
|
|
468
|
+
import {
|
|
469
|
+
HumanGatewayCallbackError,
|
|
470
|
+
verifyCallback,
|
|
471
|
+
} from "@human-gateway/sdk/server";
|
|
472
|
+
|
|
473
|
+
try {
|
|
474
|
+
const callback = verifyCallback({
|
|
475
|
+
body,
|
|
476
|
+
headers,
|
|
477
|
+
secret: process.env.HG_CALLBACK_SECRET!,
|
|
478
|
+
});
|
|
479
|
+
} catch (error) {
|
|
480
|
+
if (error instanceof HumanGatewayCallbackError) {
|
|
481
|
+
console.error("Invalid Human Gateway callback:", error.code);
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
```
|
|
485
|
+
|
|
486
|
+
---
|
|
487
|
+
|
|
488
|
+
## SDK error codes
|
|
489
|
+
|
|
490
|
+
```ts
|
|
491
|
+
type HumanGatewayErrorCode =
|
|
492
|
+
| "popup_blocked"
|
|
493
|
+
| "user_closed"
|
|
494
|
+
| "timeout"
|
|
495
|
+
| "invalid_message"
|
|
496
|
+
| "invalid_origin"
|
|
497
|
+
| "verification_failed"
|
|
498
|
+
| "auth_failed"
|
|
499
|
+
| "unknown_error";
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Common handling:
|
|
503
|
+
|
|
504
|
+
```ts
|
|
505
|
+
import { HumanGateway, HumanGatewayError } from "@human-gateway/sdk";
|
|
506
|
+
|
|
507
|
+
const hg = new HumanGateway({
|
|
508
|
+
projectId: "project_xxx",
|
|
509
|
+
});
|
|
510
|
+
|
|
511
|
+
try {
|
|
512
|
+
const result = await hg.verify({
|
|
513
|
+
actionKey: "hg_verify_action_key_xxx",
|
|
514
|
+
});
|
|
515
|
+
} catch (error) {
|
|
516
|
+
if (error instanceof HumanGatewayError) {
|
|
517
|
+
if (error.code === "user_closed") {
|
|
518
|
+
// User cancelled the flow
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
if (error.code === "popup_blocked") {
|
|
522
|
+
// Ask the user to allow popups
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
if (error.code === "verification_failed") {
|
|
526
|
+
// The hosted verification flow did not complete successfully
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## Local development
|
|
535
|
+
|
|
536
|
+
```ts
|
|
537
|
+
const hg = new HumanGateway({
|
|
538
|
+
projectId: "project_1a7f21ff5e261645",
|
|
539
|
+
environment: "development",
|
|
540
|
+
baseUrl: "http://localhost:3000",
|
|
541
|
+
});
|
|
542
|
+
|
|
543
|
+
await hg.verify({
|
|
544
|
+
actionKey: "hg_verify_action_key_xxx",
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
await hg.auth({
|
|
548
|
+
actionKey: "hg_auth_action_key_xxx",
|
|
549
|
+
});
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## Privacy-first guarantees
|
|
555
|
+
|
|
556
|
+
Human Gateway does not identify the user.
|
|
557
|
+
|
|
558
|
+
It verifies humanity inside a project/action context.
|
|
559
|
+
|
|
560
|
+
The partner may receive:
|
|
561
|
+
|
|
562
|
+
```txt
|
|
563
|
+
success
|
|
564
|
+
verified_human
|
|
565
|
+
unique_for_partner
|
|
566
|
+
already_verified
|
|
567
|
+
partner_user_id
|
|
568
|
+
auth_session_id
|
|
569
|
+
project_id
|
|
570
|
+
expires_at
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
The partner does not receive:
|
|
574
|
+
|
|
575
|
+
```txt
|
|
576
|
+
World ID nullifier
|
|
577
|
+
biometric data
|
|
578
|
+
personal identity
|
|
579
|
+
World proof internals
|
|
580
|
+
Human Gateway internal user object
|
|
581
|
+
raw World ID proof data
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## Recommended partner verification flow
|
|
587
|
+
|
|
588
|
+
```txt
|
|
589
|
+
1. User clicks "Verify with Human Gateway"
|
|
590
|
+
2. SDK opens Human Gateway popup
|
|
591
|
+
3. User completes World ID proof
|
|
592
|
+
4. Partner frontend receives UX result
|
|
593
|
+
5. Human Gateway sends signed callback to partner backend
|
|
594
|
+
6. Partner backend verifies callback
|
|
595
|
+
7. Partner persists verified status
|
|
596
|
+
8. Partner hides verification button
|
|
597
|
+
```
|
|
598
|
+
|
|
599
|
+
---
|
|
600
|
+
|
|
601
|
+
## Recommended partner auth flow
|
|
602
|
+
|
|
603
|
+
```txt
|
|
604
|
+
1. User clicks "Sign in with Human Gateway"
|
|
605
|
+
2. SDK opens Human Gateway Auth popup
|
|
606
|
+
3. User completes World ID proof
|
|
607
|
+
4. Human Gateway creates a partner-scoped auth session
|
|
608
|
+
5. Partner frontend receives UX result
|
|
609
|
+
6. Human Gateway sends signed callback to partner backend
|
|
610
|
+
7. Partner backend verifies callback
|
|
611
|
+
8. Partner grants or reconciles app access according to its own session model
|
|
612
|
+
```
|
|
613
|
+
|
|
614
|
+
---
|
|
615
|
+
|
|
616
|
+
## Current alpha status
|
|
617
|
+
|
|
618
|
+
Implemented:
|
|
619
|
+
|
|
620
|
+
* popup verification flow
|
|
621
|
+
* popup auth flow
|
|
622
|
+
* action-specific `hg.verify({ actionKey })`
|
|
623
|
+
* action-specific `hg.auth({ actionKey })`
|
|
624
|
+
* fallback behavior without `actionKey`
|
|
625
|
+
* postMessage result delivery
|
|
626
|
+
* timeout handling
|
|
627
|
+
* user close detection
|
|
628
|
+
* duplicate verify/auth call prevention
|
|
629
|
+
* signed callback verification helper
|
|
630
|
+
* full callback validation helper
|
|
631
|
+
* ESM/CJS builds
|
|
632
|
+
* TypeScript types
|
|
633
|
+
* prepack build protection
|
|
634
|
+
* prepublish typecheck/build protection
|
|
635
|
+
|
|
636
|
+
Planned:
|
|
20
637
|
|
|
21
|
-
|
|
638
|
+
* iframe modal mode
|
|
639
|
+
* redirect fallback
|
|
640
|
+
* React helper
|
|
641
|
+
* expanded usage/session events
|
|
642
|
+
* public package release
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["export type HumanGatewayEnvironment =\r\n | \"production\"\r\n | \"staging\"\r\n | \"development\";\r\n\r\nexport type HumanGatewayMode =\r\n | \"auto\"\r\n | \"popup\"\r\n | \"modal\"\r\n | \"redirect\";\r\n\r\nexport type HumanGatewayOptions = {\r\n projectId: string;\r\n environment?: HumanGatewayEnvironment;\r\n mode?: HumanGatewayMode;\r\n baseUrl?: string;\r\n timeoutMs?: number;\r\n};\r\n\r\nexport type HumanGatewayVerifyOptions = {\r\n actionKey?: string;\r\n onOpen?: () => void;\r\n onClose?: () => void;\r\n onSuccess?: (result: HumanGatewayResult) => void;\r\n onError?: (error: HumanGatewayError) => void;\r\n};\r\n\r\nexport type HumanGatewayAuthOptions = {\r\n actionKey?: string;\r\n onOpen?: () => void;\r\n onClose?: () => void;\r\n onSuccess?: (result: HumanGatewayAuthResult) => void;\r\n onError?: (error: HumanGatewayError) => void;\r\n};\r\n\r\nexport type HumanGatewayResult = {\r\n success: boolean;\r\n verified_human: boolean;\r\n unique_for_partner: boolean;\r\n already_verified: boolean;\r\n project_id: string;\r\n};\r\n\r\nexport type HumanGatewayAuthResult = {\r\n success: boolean;\r\n event?: \"auth.completed\";\r\n verified_human: boolean;\r\n partner_user_id: string;\r\n auth_session_id: string;\r\n project_id: string;\r\n expires_at: string;\r\n};\r\n\r\nexport type HumanGatewayMessage = {\r\n source: \"human-gateway\";\r\n type: \"human_gateway.verification.completed\";\r\n payload: HumanGatewayResult;\r\n};\r\n\r\nexport type HumanGatewayAuthMessage = {\r\n source: \"human-gateway\";\r\n type: \"human_gateway.auth.completed\";\r\n payload: HumanGatewayAuthResult;\r\n};\r\n\r\nexport type HumanGatewayErrorCode =\r\n | \"popup_blocked\"\r\n | \"user_closed\"\r\n | \"timeout\"\r\n | \"invalid_message\"\r\n | \"invalid_origin\"\r\n | \"verification_failed\"\r\n | \"auth_failed\"\r\n | \"unknown_error\";\r\n\r\nexport class HumanGatewayError extends Error {\r\n code: HumanGatewayErrorCode;\r\n\r\n constructor(code: HumanGatewayErrorCode, message: string) {\r\n super(message);\r\n this.name = \"HumanGatewayError\";\r\n this.code = code;\r\n }\r\n}\r\n\r\nexport type HumanGatewayCallbackEventName =\r\n | \"verification.completed\"\r\n | \"auth.completed\"\r\n | \"callback.test\"\r\n | (string & {});\r\n\r\nexport type HumanGatewayCallbackPayload = Record<string, unknown> & {\r\n event_id?: unknown;\r\n event?: unknown;\r\n project_id?: unknown;\r\n};\r\n\r\nexport type HumanGatewayCallbackHeaders =\r\n | Headers\r\n | Record<string, string | string[] | null | undefined>;\r\n\r\nexport type VerifyCallbackInput = {\r\n body: string;\r\n headers: HumanGatewayCallbackHeaders;\r\n secret: string;\r\n toleranceMs?: number;\r\n expectedProjectId?: string;\r\n};\r\n\r\nexport type VerifiedHumanGatewayCallback = {\r\n event_id: string;\r\n event: HumanGatewayCallbackEventName;\r\n project_id: string;\r\n timestamp: number;\r\n payload: HumanGatewayCallbackPayload;\r\n};\r\n\r\nexport type HumanGatewayCallbackErrorCode =\r\n | \"callback_missing_body\"\r\n | \"callback_missing_secret\"\r\n | \"callback_missing_header\"\r\n | \"callback_invalid_timestamp\"\r\n | \"callback_expired_timestamp\"\r\n | \"callback_invalid_signature_format\"\r\n | \"callback_invalid_signature\"\r\n | \"callback_invalid_json\"\r\n | \"callback_invalid_payload\"\r\n | \"callback_event_id_mismatch\"\r\n | \"callback_event_type_mismatch\"\r\n | \"callback_project_id_mismatch\";\r\n\r\nexport class HumanGatewayCallbackError extends Error {\r\n code: HumanGatewayCallbackErrorCode;\r\n\r\n constructor(code: HumanGatewayCallbackErrorCode, message: string) {\r\n super(message);\r\n this.name = \"HumanGatewayCallbackError\";\r\n this.code = code;\r\n }\r\n}"],"mappings":"AA2EO,IAAMA,EAAN,cAAgC,KAAM,CAGzC,YAAYC,EAA6BC,EAAiB,CACtD,MAAMA,CAAO,EACb,KAAK,KAAO,oBACZ,KAAK,KAAOD,CAChB,CACJ,EAgDaE,EAAN,cAAwC,KAAM,CAGjD,YAAYF,EAAqCC,EAAiB,CAC9D,MAAMA,CAAO,EACb,KAAK,KAAO,4BACZ,KAAK,KAAOD,CAChB,CACJ","names":["HumanGatewayError","code","message","HumanGatewayCallbackError"]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var g=Object.defineProperty;var _=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var k=Object.prototype.hasOwnProperty;var M=(t,e)=>{for(var a in e)g(t,a,{get:e[a],enumerable:!0})},x=(t,e,a,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of b(e))!k.call(t,o)&&o!==a&&g(t,o,{get:()=>e[o],enumerable:!(r=_(e,o))||r.enumerable});return t};var E=t=>x(g({},"__esModule",{value:!0}),t);var V={};M(V,{HumanGateway:()=>w,HumanGatewayError:()=>n});module.exports=E(V);var n=class extends Error{constructor(e,a){super(a),this.name="HumanGatewayError",this.code=e}};function R(t=480,e=720){let a=typeof window<"u"?Math.min(t,Math.floor(window.innerWidth*.92)):t,r=typeof window<"u"?Math.min(e,Math.floor(window.innerHeight*.88)):e,o=typeof window<"u"?Math.max(0,window.screenX+(window.outerWidth-a)/2):0,s=typeof window<"u"?Math.max(0,window.screenY+(window.outerHeight-r)/2):0;return[`width=${a}`,`height=${r}`,`left=${o}`,`top=${s}`,"resizable=yes","scrollbars=yes","status=no","toolbar=no","menubar=no"].join(",")}function H({url:t,width:e,height:a}){if(typeof window>"u")throw new n("unknown_error","HumanGateway popup verification requires a browser environment.");let r=window.open(t,"human_gateway_verification",R(e,a));if(!r)throw new n("popup_blocked","The verification popup was blocked by the browser.");return r.focus(),r}function j(t){if(typeof t!="object"||t===null)return!1;let e=t;return e.source==="human-gateway"&&e.type==="human_gateway.verification.completed"&&typeof e.payload=="object"&&e.payload!==null}function I(t){if(typeof t!="object"||t===null)return!1;let e=t;return e.source==="human-gateway"&&e.type==="human_gateway.auth.completed"&&typeof e.payload=="object"&&e.payload!==null}function v({popup:t,expectedOrigin:e,expectedProjectId:a,timeoutMs:r,onClose:o}){return new Promise((s,p)=>{let l=!1,m=()=>{window.removeEventListener("message",d),window.clearTimeout(h),window.clearInterval(f)},y=i=>{l||(l=!0,m(),s(i))},u=i=>{l||(l=!0,m(),p(i))},d=i=>{if(i.origin!==e)return;if(!j(i.data)){u(new n("invalid_message","Received an invalid Human Gateway verification message."));return}let c=i.data.payload;if(c.project_id!==a){u(new n("invalid_message","Received a verification result for a different project."));return}if(!c.success||!c.verified_human){u(new n("verification_failed","Human Gateway verification did not complete successfully."));return}y(c)},h=window.setTimeout(()=>{u(new n("timeout","Human Gateway verification timed out."))},r),f=window.setInterval(()=>{t.closed&&(o?.(),u(new n("user_closed","The verification window was closed before completion.")))},500);window.addEventListener("message",d)})}function G({popup:t,expectedOrigin:e,expectedProjectId:a,timeoutMs:r,onClose:o}){return new Promise((s,p)=>{let l=!1,m=()=>{window.removeEventListener("message",d),window.clearTimeout(h),window.clearInterval(f)},y=i=>{l||(l=!0,m(),s(i))},u=i=>{l||(l=!0,m(),p(i))},d=i=>{if(i.origin!==e)return;if(!I(i.data)){u(new n("invalid_message","Received an invalid Human Gateway auth message."));return}let c=i.data.payload;if(c.project_id!==a){u(new n("invalid_message","Received an auth result for a different project."));return}if(!c.success||!c.verified_human||!c.partner_user_id||!c.auth_session_id){u(new n("auth_failed","Human Gateway auth did not complete successfully."));return}y(c)},h=window.setTimeout(()=>{u(new n("timeout","Human Gateway auth timed out."))},r),f=window.setInterval(()=>{t.closed&&(o?.(),u(new n("user_closed","The auth window was closed before completion.")))},500);window.addEventListener("message",d)})}var A=300*1e3;function P(t){return t==="development"?"http://localhost:3000":t==="staging"?"https://staging.humangateway.dev":"https://humangateway.dev"}function C(t){let e=new URL(`/verify/${t.projectId}`,t.baseUrl);return e.searchParams.set("sdk","1"),e.searchParams.set("origin",window.location.origin),e.searchParams.set("mode","popup"),t.actionKey&&e.searchParams.set("actionKey",t.actionKey),e.toString()}function U(t){let e=new URL(`/auth/${t.projectId}`,t.baseUrl);return e.searchParams.set("sdk","1"),e.searchParams.set("origin",window.location.origin),e.searchParams.set("mode","popup"),t.actionKey&&e.searchParams.set("actionKey",t.actionKey),e.toString()}var w=class{constructor(e){this.activeVerification=null;this.activeAuth=null;if(!e.projectId)throw new n("unknown_error","HumanGateway requires a projectId.");this.projectId=e.projectId,this.environment=e.environment??"production",this.mode=e.mode??"auto",this.baseUrl=e.baseUrl??P(this.environment),this.timeoutMs=e.timeoutMs??A}async verify(e={}){return this.activeVerification?this.activeVerification:(this.activeVerification=this.runVerification(e).finally(()=>{this.activeVerification=null}),this.activeVerification)}async auth(e={}){return this.activeAuth?this.activeAuth:(this.activeAuth=this.runAuth(e).finally(()=>{this.activeAuth=null}),this.activeAuth)}async runVerification(e){try{if(typeof window>"u")throw new n("unknown_error","HumanGateway.verify() requires a browser environment.");if(this.mode==="redirect")throw new n("unknown_error","Redirect mode is not implemented in this SDK alpha.");let a=C({baseUrl:this.baseUrl,projectId:this.projectId,...e.actionKey?{actionKey:e.actionKey}:{}}),r=new URL(this.baseUrl).origin,o=H({url:a});e.onOpen?.();let s=await v({popup:o,expectedOrigin:r,expectedProjectId:this.projectId,timeoutMs:this.timeoutMs,...e.onClose?{onClose:e.onClose}:{}});e.onSuccess?.(s);try{o.close()}catch{}return s}catch(a){let r=a instanceof n?a:new n("unknown_error",a instanceof Error?a.message:"Unknown Human Gateway SDK error.");throw e.onError?.(r),r}}async runAuth(e){try{if(typeof window>"u")throw new n("unknown_error","HumanGateway.auth() requires a browser environment.");if(this.mode==="redirect")throw new n("unknown_error","Redirect mode is not implemented in this SDK alpha.");let a=U({baseUrl:this.baseUrl,projectId:this.projectId,...e.actionKey?{actionKey:e.actionKey}:{}}),r=new URL(this.baseUrl).origin,o=H({url:a});e.onOpen?.();let s=await G({popup:o,expectedOrigin:r,expectedProjectId:this.projectId,timeoutMs:this.timeoutMs,...e.onClose?{onClose:e.onClose}:{}});e.onSuccess?.(s);try{o.close()}catch{}return s}catch(a){let r=a instanceof n?a:new n("unknown_error",a instanceof Error?a.message:"Unknown Human Gateway SDK auth error.");throw e.onError?.(r),r}}};0&&(module.exports={HumanGateway,HumanGatewayError});
|
|
2
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/popup.ts","../src/post-message.ts","../src/client.ts"],"sourcesContent":["export { HumanGateway } from \"./client\";\r\nexport type {\r\n HumanGatewayAuthMessage,\r\n HumanGatewayAuthOptions,\r\n HumanGatewayAuthResult,\r\n HumanGatewayEnvironment,\r\n HumanGatewayErrorCode,\r\n HumanGatewayMessage,\r\n HumanGatewayMode,\r\n HumanGatewayOptions,\r\n HumanGatewayResult,\r\n HumanGatewayVerifyOptions,\r\n} from \"./types\";\r\nexport { HumanGatewayError } from \"./types\";","export type HumanGatewayEnvironment =\r\n | \"production\"\r\n | \"staging\"\r\n | \"development\";\r\n\r\nexport type HumanGatewayMode =\r\n | \"auto\"\r\n | \"popup\"\r\n | \"modal\"\r\n | \"redirect\";\r\n\r\nexport type HumanGatewayOptions = {\r\n projectId: string;\r\n environment?: HumanGatewayEnvironment;\r\n mode?: HumanGatewayMode;\r\n baseUrl?: string;\r\n timeoutMs?: number;\r\n};\r\n\r\nexport type HumanGatewayVerifyOptions = {\r\n actionKey?: string;\r\n onOpen?: () => void;\r\n onClose?: () => void;\r\n onSuccess?: (result: HumanGatewayResult) => void;\r\n onError?: (error: HumanGatewayError) => void;\r\n};\r\n\r\nexport type HumanGatewayAuthOptions = {\r\n actionKey?: string;\r\n onOpen?: () => void;\r\n onClose?: () => void;\r\n onSuccess?: (result: HumanGatewayAuthResult) => void;\r\n onError?: (error: HumanGatewayError) => void;\r\n};\r\n\r\nexport type HumanGatewayResult = {\r\n success: boolean;\r\n verified_human: boolean;\r\n unique_for_partner: boolean;\r\n already_verified: boolean;\r\n project_id: string;\r\n};\r\n\r\nexport type HumanGatewayAuthResult = {\r\n success: boolean;\r\n event?: \"auth.completed\";\r\n verified_human: boolean;\r\n partner_user_id: string;\r\n auth_session_id: string;\r\n project_id: string;\r\n expires_at: string;\r\n};\r\n\r\nexport type HumanGatewayMessage = {\r\n source: \"human-gateway\";\r\n type: \"human_gateway.verification.completed\";\r\n payload: HumanGatewayResult;\r\n};\r\n\r\nexport type HumanGatewayAuthMessage = {\r\n source: \"human-gateway\";\r\n type: \"human_gateway.auth.completed\";\r\n payload: HumanGatewayAuthResult;\r\n};\r\n\r\nexport type HumanGatewayErrorCode =\r\n | \"popup_blocked\"\r\n | \"user_closed\"\r\n | \"timeout\"\r\n | \"invalid_message\"\r\n | \"invalid_origin\"\r\n | \"verification_failed\"\r\n | \"auth_failed\"\r\n | \"unknown_error\";\r\n\r\nexport class HumanGatewayError extends Error {\r\n code: HumanGatewayErrorCode;\r\n\r\n constructor(code: HumanGatewayErrorCode, message: string) {\r\n super(message);\r\n this.name = \"HumanGatewayError\";\r\n this.code = code;\r\n }\r\n}\r\n\r\nexport type HumanGatewayCallbackEventName =\r\n | \"verification.completed\"\r\n | \"auth.completed\"\r\n | \"callback.test\"\r\n | (string & {});\r\n\r\nexport type HumanGatewayCallbackPayload = Record<string, unknown> & {\r\n event_id?: unknown;\r\n event?: unknown;\r\n project_id?: unknown;\r\n};\r\n\r\nexport type HumanGatewayCallbackHeaders =\r\n | Headers\r\n | Record<string, string | string[] | null | undefined>;\r\n\r\nexport type VerifyCallbackInput = {\r\n body: string;\r\n headers: HumanGatewayCallbackHeaders;\r\n secret: string;\r\n toleranceMs?: number;\r\n expectedProjectId?: string;\r\n};\r\n\r\nexport type VerifiedHumanGatewayCallback = {\r\n event_id: string;\r\n event: HumanGatewayCallbackEventName;\r\n project_id: string;\r\n timestamp: number;\r\n payload: HumanGatewayCallbackPayload;\r\n};\r\n\r\nexport type HumanGatewayCallbackErrorCode =\r\n | \"callback_missing_body\"\r\n | \"callback_missing_secret\"\r\n | \"callback_missing_header\"\r\n | \"callback_invalid_timestamp\"\r\n | \"callback_expired_timestamp\"\r\n | \"callback_invalid_signature_format\"\r\n | \"callback_invalid_signature\"\r\n | \"callback_invalid_json\"\r\n | \"callback_invalid_payload\"\r\n | \"callback_event_id_mismatch\"\r\n | \"callback_event_type_mismatch\"\r\n | \"callback_project_id_mismatch\";\r\n\r\nexport class HumanGatewayCallbackError extends Error {\r\n code: HumanGatewayCallbackErrorCode;\r\n\r\n constructor(code: HumanGatewayCallbackErrorCode, message: string) {\r\n super(message);\r\n this.name = \"HumanGatewayCallbackError\";\r\n this.code = code;\r\n }\r\n}","import { HumanGatewayError } from \"./types\";\r\n\r\ntype OpenPopupInput = {\r\n url: string;\r\n width?: number;\r\n height?: number;\r\n};\r\n\r\nexport function getPopupFeatures(width = 480, height = 720): string {\r\n const safeWidth =\r\n typeof window !== \"undefined\"\r\n ? Math.min(width, Math.floor(window.innerWidth * 0.92))\r\n : width;\r\n\r\n const safeHeight =\r\n typeof window !== \"undefined\"\r\n ? Math.min(height, Math.floor(window.innerHeight * 0.88))\r\n : height;\r\n\r\n const left =\r\n typeof window !== \"undefined\"\r\n ? Math.max(0, window.screenX + (window.outerWidth - safeWidth) / 2)\r\n : 0;\r\n\r\n const top =\r\n typeof window !== \"undefined\"\r\n ? Math.max(0, window.screenY + (window.outerHeight - safeHeight) / 2)\r\n : 0;\r\n\r\n return [\r\n `width=${safeWidth}`,\r\n `height=${safeHeight}`,\r\n `left=${left}`,\r\n `top=${top}`,\r\n \"resizable=yes\",\r\n \"scrollbars=yes\",\r\n \"status=no\",\r\n \"toolbar=no\",\r\n \"menubar=no\",\r\n ].join(\",\");\r\n}\r\n\r\nexport function openVerificationPopup({\r\n url,\r\n width,\r\n height,\r\n}: OpenPopupInput): Window {\r\n if (typeof window === \"undefined\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"HumanGateway popup verification requires a browser environment.\"\r\n );\r\n }\r\n\r\n const popup = window.open(\r\n url,\r\n \"human_gateway_verification\",\r\n getPopupFeatures(width, height)\r\n );\r\n\r\n if (!popup) {\r\n throw new HumanGatewayError(\r\n \"popup_blocked\",\r\n \"The verification popup was blocked by the browser.\"\r\n );\r\n }\r\n\r\n popup.focus();\r\n\r\n return popup;\r\n}","import {\r\n HumanGatewayAuthMessage,\r\n HumanGatewayAuthResult,\r\n HumanGatewayError,\r\n HumanGatewayMessage,\r\n HumanGatewayResult,\r\n} from \"./types\";\r\n\r\ntype WaitForMessageInput = {\r\n popup: Window;\r\n expectedOrigin: string;\r\n expectedProjectId: string;\r\n timeoutMs: number;\r\n onClose?: () => void;\r\n};\r\n\r\nfunction isHumanGatewayVerificationMessage(\r\n value: unknown\r\n): value is HumanGatewayMessage {\r\n if (typeof value !== \"object\" || value === null) {\r\n return false;\r\n }\r\n\r\n const message = value as Partial<HumanGatewayMessage>;\r\n\r\n return (\r\n message.source === \"human-gateway\" &&\r\n message.type === \"human_gateway.verification.completed\" &&\r\n typeof message.payload === \"object\" &&\r\n message.payload !== null\r\n );\r\n}\r\n\r\nfunction isHumanGatewayAuthMessage(\r\n value: unknown\r\n): value is HumanGatewayAuthMessage {\r\n if (typeof value !== \"object\" || value === null) {\r\n return false;\r\n }\r\n\r\n const message = value as Partial<HumanGatewayAuthMessage>;\r\n\r\n return (\r\n message.source === \"human-gateway\" &&\r\n message.type === \"human_gateway.auth.completed\" &&\r\n typeof message.payload === \"object\" &&\r\n message.payload !== null\r\n );\r\n}\r\n\r\nexport function waitForVerificationMessage({\r\n popup,\r\n expectedOrigin,\r\n expectedProjectId,\r\n timeoutMs,\r\n onClose,\r\n}: WaitForMessageInput): Promise<HumanGatewayResult> {\r\n return new Promise((resolve, reject) => {\r\n let settled = false;\r\n\r\n const cleanup = () => {\r\n window.removeEventListener(\"message\", onMessage);\r\n window.clearTimeout(timeoutId);\r\n window.clearInterval(closeCheckId);\r\n };\r\n\r\n const settleResolve = (result: HumanGatewayResult) => {\r\n if (settled) return;\r\n\r\n settled = true;\r\n cleanup();\r\n resolve(result);\r\n };\r\n\r\n const settleReject = (error: HumanGatewayError) => {\r\n if (settled) return;\r\n\r\n settled = true;\r\n cleanup();\r\n reject(error);\r\n };\r\n\r\n const onMessage = (event: MessageEvent) => {\r\n if (event.origin !== expectedOrigin) {\r\n return;\r\n }\r\n\r\n if (!isHumanGatewayVerificationMessage(event.data)) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"invalid_message\",\r\n \"Received an invalid Human Gateway verification message.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n const result = event.data.payload;\r\n\r\n if (result.project_id !== expectedProjectId) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"invalid_message\",\r\n \"Received a verification result for a different project.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n if (!result.success || !result.verified_human) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"verification_failed\",\r\n \"Human Gateway verification did not complete successfully.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n settleResolve(result);\r\n };\r\n\r\n const timeoutId = window.setTimeout(() => {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"timeout\",\r\n \"Human Gateway verification timed out.\"\r\n )\r\n );\r\n }, timeoutMs);\r\n\r\n const closeCheckId = window.setInterval(() => {\r\n if (popup.closed) {\r\n onClose?.();\r\n\r\n settleReject(\r\n new HumanGatewayError(\r\n \"user_closed\",\r\n \"The verification window was closed before completion.\"\r\n )\r\n );\r\n }\r\n }, 500);\r\n\r\n window.addEventListener(\"message\", onMessage);\r\n });\r\n}\r\n\r\nexport function waitForAuthMessage({\r\n popup,\r\n expectedOrigin,\r\n expectedProjectId,\r\n timeoutMs,\r\n onClose,\r\n}: WaitForMessageInput): Promise<HumanGatewayAuthResult> {\r\n return new Promise((resolve, reject) => {\r\n let settled = false;\r\n\r\n const cleanup = () => {\r\n window.removeEventListener(\"message\", onMessage);\r\n window.clearTimeout(timeoutId);\r\n window.clearInterval(closeCheckId);\r\n };\r\n\r\n const settleResolve = (result: HumanGatewayAuthResult) => {\r\n if (settled) return;\r\n\r\n settled = true;\r\n cleanup();\r\n resolve(result);\r\n };\r\n\r\n const settleReject = (error: HumanGatewayError) => {\r\n if (settled) return;\r\n\r\n settled = true;\r\n cleanup();\r\n reject(error);\r\n };\r\n\r\n const onMessage = (event: MessageEvent) => {\r\n if (event.origin !== expectedOrigin) {\r\n return;\r\n }\r\n\r\n if (!isHumanGatewayAuthMessage(event.data)) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"invalid_message\",\r\n \"Received an invalid Human Gateway auth message.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n const result = event.data.payload;\r\n\r\n if (result.project_id !== expectedProjectId) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"invalid_message\",\r\n \"Received an auth result for a different project.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n if (\r\n !result.success ||\r\n !result.verified_human ||\r\n !result.partner_user_id ||\r\n !result.auth_session_id\r\n ) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"auth_failed\",\r\n \"Human Gateway auth did not complete successfully.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n settleResolve(result);\r\n };\r\n\r\n const timeoutId = window.setTimeout(() => {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"timeout\",\r\n \"Human Gateway auth timed out.\"\r\n )\r\n );\r\n }, timeoutMs);\r\n\r\n const closeCheckId = window.setInterval(() => {\r\n if (popup.closed) {\r\n onClose?.();\r\n\r\n settleReject(\r\n new HumanGatewayError(\r\n \"user_closed\",\r\n \"The auth window was closed before completion.\"\r\n )\r\n );\r\n }\r\n }, 500);\r\n\r\n window.addEventListener(\"message\", onMessage);\r\n });\r\n}","import { openVerificationPopup } from \"./popup\";\r\nimport {\r\n waitForAuthMessage,\r\n waitForVerificationMessage,\r\n} from \"./post-message\";\r\nimport {\r\n HumanGatewayAuthOptions,\r\n HumanGatewayAuthResult,\r\n HumanGatewayError,\r\n HumanGatewayOptions,\r\n HumanGatewayResult,\r\n HumanGatewayVerifyOptions,\r\n} from \"./types\";\r\n\r\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\r\n\r\nfunction getDefaultBaseUrl(environment: HumanGatewayOptions[\"environment\"]) {\r\n if (environment === \"development\") {\r\n return \"http://localhost:3000\";\r\n }\r\n\r\n if (environment === \"staging\") {\r\n return \"https://staging.humangateway.dev\";\r\n }\r\n\r\n return \"https://humangateway.dev\";\r\n}\r\n\r\nfunction buildVerificationUrl(input: {\r\n baseUrl: string;\r\n projectId: string;\r\n actionKey?: string;\r\n}): string {\r\n const url = new URL(`/verify/${input.projectId}`, input.baseUrl);\r\n\r\n url.searchParams.set(\"sdk\", \"1\");\r\n url.searchParams.set(\"origin\", window.location.origin);\r\n url.searchParams.set(\"mode\", \"popup\");\r\n\r\n if (input.actionKey) {\r\n url.searchParams.set(\"actionKey\", input.actionKey);\r\n }\r\n\r\n return url.toString();\r\n}\r\n\r\nfunction buildAuthUrl(input: {\r\n baseUrl: string;\r\n projectId: string;\r\n actionKey?: string;\r\n}): string {\r\n const url = new URL(`/auth/${input.projectId}`, input.baseUrl);\r\n\r\n url.searchParams.set(\"sdk\", \"1\");\r\n url.searchParams.set(\"origin\", window.location.origin);\r\n url.searchParams.set(\"mode\", \"popup\");\r\n\r\n if (input.actionKey) {\r\n url.searchParams.set(\"actionKey\", input.actionKey);\r\n }\r\n\r\n return url.toString();\r\n}\r\n\r\nexport class HumanGateway {\r\n private readonly projectId: string;\r\n private readonly environment: NonNullable<HumanGatewayOptions[\"environment\"]>;\r\n private readonly mode: NonNullable<HumanGatewayOptions[\"mode\"]>;\r\n private readonly baseUrl: string;\r\n private readonly timeoutMs: number;\r\n private activeVerification: Promise<HumanGatewayResult> | null = null;\r\n private activeAuth: Promise<HumanGatewayAuthResult> | null = null;\r\n\r\n constructor(options: HumanGatewayOptions) {\r\n if (!options.projectId) {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"HumanGateway requires a projectId.\"\r\n );\r\n }\r\n\r\n this.projectId = options.projectId;\r\n this.environment = options.environment ?? \"production\";\r\n this.mode = options.mode ?? \"auto\";\r\n this.baseUrl = options.baseUrl ?? getDefaultBaseUrl(this.environment);\r\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\r\n }\r\n\r\n async verify(\r\n verifyOptions: HumanGatewayVerifyOptions = {}\r\n ): Promise<HumanGatewayResult> {\r\n if (this.activeVerification) {\r\n return this.activeVerification;\r\n }\r\n\r\n this.activeVerification = this.runVerification(verifyOptions).finally(() => {\r\n this.activeVerification = null;\r\n });\r\n\r\n return this.activeVerification;\r\n }\r\n\r\n async auth(\r\n authOptions: HumanGatewayAuthOptions = {}\r\n ): Promise<HumanGatewayAuthResult> {\r\n if (this.activeAuth) {\r\n return this.activeAuth;\r\n }\r\n\r\n this.activeAuth = this.runAuth(authOptions).finally(() => {\r\n this.activeAuth = null;\r\n });\r\n\r\n return this.activeAuth;\r\n }\r\n\r\n private async runVerification(\r\n verifyOptions: HumanGatewayVerifyOptions\r\n ): Promise<HumanGatewayResult> {\r\n try {\r\n if (typeof window === \"undefined\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"HumanGateway.verify() requires a browser environment.\"\r\n );\r\n }\r\n\r\n if (this.mode === \"redirect\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"Redirect mode is not implemented in this SDK alpha.\"\r\n );\r\n }\r\n\r\n const verificationUrl = buildVerificationUrl({\r\n baseUrl: this.baseUrl,\r\n projectId: this.projectId,\r\n ...(verifyOptions.actionKey\r\n ? { actionKey: verifyOptions.actionKey }\r\n : {}),\r\n });\r\n\r\n const expectedOrigin = new URL(this.baseUrl).origin;\r\n\r\n const popup = openVerificationPopup({\r\n url: verificationUrl,\r\n });\r\n\r\n verifyOptions.onOpen?.();\r\n\r\n const result = await waitForVerificationMessage({\r\n popup,\r\n expectedOrigin,\r\n expectedProjectId: this.projectId,\r\n timeoutMs: this.timeoutMs,\r\n ...(verifyOptions.onClose\r\n ? { onClose: verifyOptions.onClose }\r\n : {}),\r\n });\r\n\r\n verifyOptions.onSuccess?.(result);\r\n\r\n try {\r\n popup.close();\r\n } catch {\r\n // Ignore close errors. Some browsers may block programmatic close.\r\n }\r\n\r\n return result;\r\n } catch (error) {\r\n const normalizedError =\r\n error instanceof HumanGatewayError\r\n ? error\r\n : new HumanGatewayError(\r\n \"unknown_error\",\r\n error instanceof Error\r\n ? error.message\r\n : \"Unknown Human Gateway SDK error.\"\r\n );\r\n\r\n verifyOptions.onError?.(normalizedError);\r\n\r\n throw normalizedError;\r\n }\r\n }\r\n\r\n private async runAuth(\r\n authOptions: HumanGatewayAuthOptions\r\n ): Promise<HumanGatewayAuthResult> {\r\n try {\r\n if (typeof window === \"undefined\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"HumanGateway.auth() requires a browser environment.\"\r\n );\r\n }\r\n\r\n if (this.mode === \"redirect\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"Redirect mode is not implemented in this SDK alpha.\"\r\n );\r\n }\r\n\r\n const authUrl = buildAuthUrl({\r\n baseUrl: this.baseUrl,\r\n projectId: this.projectId,\r\n ...(authOptions.actionKey ? { actionKey: authOptions.actionKey } : {}),\r\n });\r\n\r\n const expectedOrigin = new URL(this.baseUrl).origin;\r\n\r\n const popup = openVerificationPopup({\r\n url: authUrl,\r\n });\r\n\r\n authOptions.onOpen?.();\r\n\r\n const result = await waitForAuthMessage({\r\n popup,\r\n expectedOrigin,\r\n expectedProjectId: this.projectId,\r\n timeoutMs: this.timeoutMs,\r\n ...(authOptions.onClose\r\n ? { onClose: authOptions.onClose }\r\n : {}),\r\n });\r\n\r\n authOptions.onSuccess?.(result);\r\n\r\n try {\r\n popup.close();\r\n } catch {\r\n // Ignore close errors. Some browsers may block programmatic close.\r\n }\r\n\r\n return result;\r\n } catch (error) {\r\n const normalizedError =\r\n error instanceof HumanGatewayError\r\n ? error\r\n : new HumanGatewayError(\r\n \"unknown_error\",\r\n error instanceof Error\r\n ? error.message\r\n : \"Unknown Human Gateway SDK auth error.\"\r\n );\r\n\r\n authOptions.onError?.(normalizedError);\r\n\r\n throw normalizedError;\r\n }\r\n }\r\n}"],"mappings":"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","names":["src_exports","__export","HumanGateway","HumanGatewayError","__toCommonJS","HumanGatewayError","code","message","getPopupFeatures","width","height","safeWidth","safeHeight","left","top","openVerificationPopup","url","HumanGatewayError","popup","isHumanGatewayVerificationMessage","value","message","isHumanGatewayAuthMessage","waitForVerificationMessage","popup","expectedOrigin","expectedProjectId","timeoutMs","onClose","resolve","reject","settled","cleanup","onMessage","timeoutId","closeCheckId","settleResolve","result","settleReject","error","event","HumanGatewayError","waitForAuthMessage","DEFAULT_TIMEOUT_MS","getDefaultBaseUrl","environment","buildVerificationUrl","input","url","buildAuthUrl","HumanGateway","options","HumanGatewayError","verifyOptions","authOptions","verificationUrl","expectedOrigin","popup","openVerificationPopup","result","waitForVerificationMessage","error","normalizedError","authUrl","waitForAuthMessage"]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { m as HumanGatewayOptions, o as HumanGatewayVerifyOptions, n as HumanGatewayResult, a as HumanGatewayAuthOptions, b as HumanGatewayAuthResult } from './types-D8bnQbLL.cjs';
|
|
2
|
+
export { H as HumanGatewayAuthMessage, h as HumanGatewayEnvironment, i as HumanGatewayError, j as HumanGatewayErrorCode, k as HumanGatewayMessage, l as HumanGatewayMode } from './types-D8bnQbLL.cjs';
|
|
3
|
+
|
|
4
|
+
declare class HumanGateway {
|
|
5
|
+
private readonly projectId;
|
|
6
|
+
private readonly environment;
|
|
7
|
+
private readonly mode;
|
|
8
|
+
private readonly baseUrl;
|
|
9
|
+
private readonly timeoutMs;
|
|
10
|
+
private activeVerification;
|
|
11
|
+
private activeAuth;
|
|
12
|
+
constructor(options: HumanGatewayOptions);
|
|
13
|
+
verify(verifyOptions?: HumanGatewayVerifyOptions): Promise<HumanGatewayResult>;
|
|
14
|
+
auth(authOptions?: HumanGatewayAuthOptions): Promise<HumanGatewayAuthResult>;
|
|
15
|
+
private runVerification;
|
|
16
|
+
private runAuth;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { HumanGateway, HumanGatewayAuthOptions, HumanGatewayAuthResult, HumanGatewayOptions, HumanGatewayResult, HumanGatewayVerifyOptions };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { m as HumanGatewayOptions, o as HumanGatewayVerifyOptions, n as HumanGatewayResult, a as HumanGatewayAuthOptions, b as HumanGatewayAuthResult } from './types-D8bnQbLL.js';
|
|
2
|
+
export { H as HumanGatewayAuthMessage, h as HumanGatewayEnvironment, i as HumanGatewayError, j as HumanGatewayErrorCode, k as HumanGatewayMessage, l as HumanGatewayMode } from './types-D8bnQbLL.js';
|
|
3
|
+
|
|
4
|
+
declare class HumanGateway {
|
|
5
|
+
private readonly projectId;
|
|
6
|
+
private readonly environment;
|
|
7
|
+
private readonly mode;
|
|
8
|
+
private readonly baseUrl;
|
|
9
|
+
private readonly timeoutMs;
|
|
10
|
+
private activeVerification;
|
|
11
|
+
private activeAuth;
|
|
12
|
+
constructor(options: HumanGatewayOptions);
|
|
13
|
+
verify(verifyOptions?: HumanGatewayVerifyOptions): Promise<HumanGatewayResult>;
|
|
14
|
+
auth(authOptions?: HumanGatewayAuthOptions): Promise<HumanGatewayAuthResult>;
|
|
15
|
+
private runVerification;
|
|
16
|
+
private runAuth;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { HumanGateway, HumanGatewayAuthOptions, HumanGatewayAuthResult, HumanGatewayOptions, HumanGatewayResult, HumanGatewayVerifyOptions };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{a}from"./chunk-3SSCLKQD.js";function G(t=480,e=720){let n=typeof window<"u"?Math.min(t,Math.floor(window.innerWidth*.92)):t,r=typeof window<"u"?Math.min(e,Math.floor(window.innerHeight*.88)):e,i=typeof window<"u"?Math.max(0,window.screenX+(window.outerWidth-n)/2):0,s=typeof window<"u"?Math.max(0,window.screenY+(window.outerHeight-r)/2):0;return[`width=${n}`,`height=${r}`,`left=${i}`,`top=${s}`,"resizable=yes","scrollbars=yes","status=no","toolbar=no","menubar=no"].join(",")}function f({url:t,width:e,height:n}){if(typeof window>"u")throw new a("unknown_error","HumanGateway popup verification requires a browser environment.");let r=window.open(t,"human_gateway_verification",G(e,n));if(!r)throw new a("popup_blocked","The verification popup was blocked by the browser.");return r.focus(),r}function b(t){if(typeof t!="object"||t===null)return!1;let e=t;return e.source==="human-gateway"&&e.type==="human_gateway.verification.completed"&&typeof e.payload=="object"&&e.payload!==null}function M(t){if(typeof t!="object"||t===null)return!1;let e=t;return e.source==="human-gateway"&&e.type==="human_gateway.auth.completed"&&typeof e.payload=="object"&&e.payload!==null}function H({popup:t,expectedOrigin:e,expectedProjectId:n,timeoutMs:r,onClose:i}){return new Promise((s,d)=>{let w=!1,m=()=>{window.removeEventListener("message",l),window.clearTimeout(y),window.clearInterval(h)},p=o=>{w||(w=!0,m(),s(o))},u=o=>{w||(w=!0,m(),d(o))},l=o=>{if(o.origin!==e)return;if(!b(o.data)){u(new a("invalid_message","Received an invalid Human Gateway verification message."));return}let c=o.data.payload;if(c.project_id!==n){u(new a("invalid_message","Received a verification result for a different project."));return}if(!c.success||!c.verified_human){u(new a("verification_failed","Human Gateway verification did not complete successfully."));return}p(c)},y=window.setTimeout(()=>{u(new a("timeout","Human Gateway verification timed out."))},r),h=window.setInterval(()=>{t.closed&&(i?.(),u(new a("user_closed","The verification window was closed before completion.")))},500);window.addEventListener("message",l)})}function v({popup:t,expectedOrigin:e,expectedProjectId:n,timeoutMs:r,onClose:i}){return new Promise((s,d)=>{let w=!1,m=()=>{window.removeEventListener("message",l),window.clearTimeout(y),window.clearInterval(h)},p=o=>{w||(w=!0,m(),s(o))},u=o=>{w||(w=!0,m(),d(o))},l=o=>{if(o.origin!==e)return;if(!M(o.data)){u(new a("invalid_message","Received an invalid Human Gateway auth message."));return}let c=o.data.payload;if(c.project_id!==n){u(new a("invalid_message","Received an auth result for a different project."));return}if(!c.success||!c.verified_human||!c.partner_user_id||!c.auth_session_id){u(new a("auth_failed","Human Gateway auth did not complete successfully."));return}p(c)},y=window.setTimeout(()=>{u(new a("timeout","Human Gateway auth timed out."))},r),h=window.setInterval(()=>{t.closed&&(i?.(),u(new a("user_closed","The auth window was closed before completion.")))},500);window.addEventListener("message",l)})}var I=300*1e3;function _(t){return t==="development"?"http://localhost:3000":t==="staging"?"https://staging.humangateway.dev":"https://humangateway.dev"}function R(t){let e=new URL(`/verify/${t.projectId}`,t.baseUrl);return e.searchParams.set("sdk","1"),e.searchParams.set("origin",window.location.origin),e.searchParams.set("mode","popup"),t.actionKey&&e.searchParams.set("actionKey",t.actionKey),e.toString()}function j(t){let e=new URL(`/auth/${t.projectId}`,t.baseUrl);return e.searchParams.set("sdk","1"),e.searchParams.set("origin",window.location.origin),e.searchParams.set("mode","popup"),t.actionKey&&e.searchParams.set("actionKey",t.actionKey),e.toString()}var g=class{constructor(e){this.activeVerification=null;this.activeAuth=null;if(!e.projectId)throw new a("unknown_error","HumanGateway requires a projectId.");this.projectId=e.projectId,this.environment=e.environment??"production",this.mode=e.mode??"auto",this.baseUrl=e.baseUrl??_(this.environment),this.timeoutMs=e.timeoutMs??I}async verify(e={}){return this.activeVerification?this.activeVerification:(this.activeVerification=this.runVerification(e).finally(()=>{this.activeVerification=null}),this.activeVerification)}async auth(e={}){return this.activeAuth?this.activeAuth:(this.activeAuth=this.runAuth(e).finally(()=>{this.activeAuth=null}),this.activeAuth)}async runVerification(e){try{if(typeof window>"u")throw new a("unknown_error","HumanGateway.verify() requires a browser environment.");if(this.mode==="redirect")throw new a("unknown_error","Redirect mode is not implemented in this SDK alpha.");let n=R({baseUrl:this.baseUrl,projectId:this.projectId,...e.actionKey?{actionKey:e.actionKey}:{}}),r=new URL(this.baseUrl).origin,i=f({url:n});e.onOpen?.();let s=await H({popup:i,expectedOrigin:r,expectedProjectId:this.projectId,timeoutMs:this.timeoutMs,...e.onClose?{onClose:e.onClose}:{}});e.onSuccess?.(s);try{i.close()}catch{}return s}catch(n){let r=n instanceof a?n:new a("unknown_error",n instanceof Error?n.message:"Unknown Human Gateway SDK error.");throw e.onError?.(r),r}}async runAuth(e){try{if(typeof window>"u")throw new a("unknown_error","HumanGateway.auth() requires a browser environment.");if(this.mode==="redirect")throw new a("unknown_error","Redirect mode is not implemented in this SDK alpha.");let n=j({baseUrl:this.baseUrl,projectId:this.projectId,...e.actionKey?{actionKey:e.actionKey}:{}}),r=new URL(this.baseUrl).origin,i=f({url:n});e.onOpen?.();let s=await v({popup:i,expectedOrigin:r,expectedProjectId:this.projectId,timeoutMs:this.timeoutMs,...e.onClose?{onClose:e.onClose}:{}});e.onSuccess?.(s);try{i.close()}catch{}return s}catch(n){let r=n instanceof a?n:new a("unknown_error",n instanceof Error?n.message:"Unknown Human Gateway SDK auth error.");throw e.onError?.(r),r}}};export{g as HumanGateway,a as HumanGatewayError};
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/popup.ts","../src/post-message.ts","../src/client.ts"],"sourcesContent":["import { HumanGatewayError } from \"./types\";\r\n\r\ntype OpenPopupInput = {\r\n url: string;\r\n width?: number;\r\n height?: number;\r\n};\r\n\r\nexport function getPopupFeatures(width = 480, height = 720): string {\r\n const safeWidth =\r\n typeof window !== \"undefined\"\r\n ? Math.min(width, Math.floor(window.innerWidth * 0.92))\r\n : width;\r\n\r\n const safeHeight =\r\n typeof window !== \"undefined\"\r\n ? Math.min(height, Math.floor(window.innerHeight * 0.88))\r\n : height;\r\n\r\n const left =\r\n typeof window !== \"undefined\"\r\n ? Math.max(0, window.screenX + (window.outerWidth - safeWidth) / 2)\r\n : 0;\r\n\r\n const top =\r\n typeof window !== \"undefined\"\r\n ? Math.max(0, window.screenY + (window.outerHeight - safeHeight) / 2)\r\n : 0;\r\n\r\n return [\r\n `width=${safeWidth}`,\r\n `height=${safeHeight}`,\r\n `left=${left}`,\r\n `top=${top}`,\r\n \"resizable=yes\",\r\n \"scrollbars=yes\",\r\n \"status=no\",\r\n \"toolbar=no\",\r\n \"menubar=no\",\r\n ].join(\",\");\r\n}\r\n\r\nexport function openVerificationPopup({\r\n url,\r\n width,\r\n height,\r\n}: OpenPopupInput): Window {\r\n if (typeof window === \"undefined\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"HumanGateway popup verification requires a browser environment.\"\r\n );\r\n }\r\n\r\n const popup = window.open(\r\n url,\r\n \"human_gateway_verification\",\r\n getPopupFeatures(width, height)\r\n );\r\n\r\n if (!popup) {\r\n throw new HumanGatewayError(\r\n \"popup_blocked\",\r\n \"The verification popup was blocked by the browser.\"\r\n );\r\n }\r\n\r\n popup.focus();\r\n\r\n return popup;\r\n}","import {\r\n HumanGatewayAuthMessage,\r\n HumanGatewayAuthResult,\r\n HumanGatewayError,\r\n HumanGatewayMessage,\r\n HumanGatewayResult,\r\n} from \"./types\";\r\n\r\ntype WaitForMessageInput = {\r\n popup: Window;\r\n expectedOrigin: string;\r\n expectedProjectId: string;\r\n timeoutMs: number;\r\n onClose?: () => void;\r\n};\r\n\r\nfunction isHumanGatewayVerificationMessage(\r\n value: unknown\r\n): value is HumanGatewayMessage {\r\n if (typeof value !== \"object\" || value === null) {\r\n return false;\r\n }\r\n\r\n const message = value as Partial<HumanGatewayMessage>;\r\n\r\n return (\r\n message.source === \"human-gateway\" &&\r\n message.type === \"human_gateway.verification.completed\" &&\r\n typeof message.payload === \"object\" &&\r\n message.payload !== null\r\n );\r\n}\r\n\r\nfunction isHumanGatewayAuthMessage(\r\n value: unknown\r\n): value is HumanGatewayAuthMessage {\r\n if (typeof value !== \"object\" || value === null) {\r\n return false;\r\n }\r\n\r\n const message = value as Partial<HumanGatewayAuthMessage>;\r\n\r\n return (\r\n message.source === \"human-gateway\" &&\r\n message.type === \"human_gateway.auth.completed\" &&\r\n typeof message.payload === \"object\" &&\r\n message.payload !== null\r\n );\r\n}\r\n\r\nexport function waitForVerificationMessage({\r\n popup,\r\n expectedOrigin,\r\n expectedProjectId,\r\n timeoutMs,\r\n onClose,\r\n}: WaitForMessageInput): Promise<HumanGatewayResult> {\r\n return new Promise((resolve, reject) => {\r\n let settled = false;\r\n\r\n const cleanup = () => {\r\n window.removeEventListener(\"message\", onMessage);\r\n window.clearTimeout(timeoutId);\r\n window.clearInterval(closeCheckId);\r\n };\r\n\r\n const settleResolve = (result: HumanGatewayResult) => {\r\n if (settled) return;\r\n\r\n settled = true;\r\n cleanup();\r\n resolve(result);\r\n };\r\n\r\n const settleReject = (error: HumanGatewayError) => {\r\n if (settled) return;\r\n\r\n settled = true;\r\n cleanup();\r\n reject(error);\r\n };\r\n\r\n const onMessage = (event: MessageEvent) => {\r\n if (event.origin !== expectedOrigin) {\r\n return;\r\n }\r\n\r\n if (!isHumanGatewayVerificationMessage(event.data)) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"invalid_message\",\r\n \"Received an invalid Human Gateway verification message.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n const result = event.data.payload;\r\n\r\n if (result.project_id !== expectedProjectId) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"invalid_message\",\r\n \"Received a verification result for a different project.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n if (!result.success || !result.verified_human) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"verification_failed\",\r\n \"Human Gateway verification did not complete successfully.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n settleResolve(result);\r\n };\r\n\r\n const timeoutId = window.setTimeout(() => {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"timeout\",\r\n \"Human Gateway verification timed out.\"\r\n )\r\n );\r\n }, timeoutMs);\r\n\r\n const closeCheckId = window.setInterval(() => {\r\n if (popup.closed) {\r\n onClose?.();\r\n\r\n settleReject(\r\n new HumanGatewayError(\r\n \"user_closed\",\r\n \"The verification window was closed before completion.\"\r\n )\r\n );\r\n }\r\n }, 500);\r\n\r\n window.addEventListener(\"message\", onMessage);\r\n });\r\n}\r\n\r\nexport function waitForAuthMessage({\r\n popup,\r\n expectedOrigin,\r\n expectedProjectId,\r\n timeoutMs,\r\n onClose,\r\n}: WaitForMessageInput): Promise<HumanGatewayAuthResult> {\r\n return new Promise((resolve, reject) => {\r\n let settled = false;\r\n\r\n const cleanup = () => {\r\n window.removeEventListener(\"message\", onMessage);\r\n window.clearTimeout(timeoutId);\r\n window.clearInterval(closeCheckId);\r\n };\r\n\r\n const settleResolve = (result: HumanGatewayAuthResult) => {\r\n if (settled) return;\r\n\r\n settled = true;\r\n cleanup();\r\n resolve(result);\r\n };\r\n\r\n const settleReject = (error: HumanGatewayError) => {\r\n if (settled) return;\r\n\r\n settled = true;\r\n cleanup();\r\n reject(error);\r\n };\r\n\r\n const onMessage = (event: MessageEvent) => {\r\n if (event.origin !== expectedOrigin) {\r\n return;\r\n }\r\n\r\n if (!isHumanGatewayAuthMessage(event.data)) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"invalid_message\",\r\n \"Received an invalid Human Gateway auth message.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n const result = event.data.payload;\r\n\r\n if (result.project_id !== expectedProjectId) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"invalid_message\",\r\n \"Received an auth result for a different project.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n if (\r\n !result.success ||\r\n !result.verified_human ||\r\n !result.partner_user_id ||\r\n !result.auth_session_id\r\n ) {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"auth_failed\",\r\n \"Human Gateway auth did not complete successfully.\"\r\n )\r\n );\r\n return;\r\n }\r\n\r\n settleResolve(result);\r\n };\r\n\r\n const timeoutId = window.setTimeout(() => {\r\n settleReject(\r\n new HumanGatewayError(\r\n \"timeout\",\r\n \"Human Gateway auth timed out.\"\r\n )\r\n );\r\n }, timeoutMs);\r\n\r\n const closeCheckId = window.setInterval(() => {\r\n if (popup.closed) {\r\n onClose?.();\r\n\r\n settleReject(\r\n new HumanGatewayError(\r\n \"user_closed\",\r\n \"The auth window was closed before completion.\"\r\n )\r\n );\r\n }\r\n }, 500);\r\n\r\n window.addEventListener(\"message\", onMessage);\r\n });\r\n}","import { openVerificationPopup } from \"./popup\";\r\nimport {\r\n waitForAuthMessage,\r\n waitForVerificationMessage,\r\n} from \"./post-message\";\r\nimport {\r\n HumanGatewayAuthOptions,\r\n HumanGatewayAuthResult,\r\n HumanGatewayError,\r\n HumanGatewayOptions,\r\n HumanGatewayResult,\r\n HumanGatewayVerifyOptions,\r\n} from \"./types\";\r\n\r\nconst DEFAULT_TIMEOUT_MS = 5 * 60 * 1000;\r\n\r\nfunction getDefaultBaseUrl(environment: HumanGatewayOptions[\"environment\"]) {\r\n if (environment === \"development\") {\r\n return \"http://localhost:3000\";\r\n }\r\n\r\n if (environment === \"staging\") {\r\n return \"https://staging.humangateway.dev\";\r\n }\r\n\r\n return \"https://humangateway.dev\";\r\n}\r\n\r\nfunction buildVerificationUrl(input: {\r\n baseUrl: string;\r\n projectId: string;\r\n actionKey?: string;\r\n}): string {\r\n const url = new URL(`/verify/${input.projectId}`, input.baseUrl);\r\n\r\n url.searchParams.set(\"sdk\", \"1\");\r\n url.searchParams.set(\"origin\", window.location.origin);\r\n url.searchParams.set(\"mode\", \"popup\");\r\n\r\n if (input.actionKey) {\r\n url.searchParams.set(\"actionKey\", input.actionKey);\r\n }\r\n\r\n return url.toString();\r\n}\r\n\r\nfunction buildAuthUrl(input: {\r\n baseUrl: string;\r\n projectId: string;\r\n actionKey?: string;\r\n}): string {\r\n const url = new URL(`/auth/${input.projectId}`, input.baseUrl);\r\n\r\n url.searchParams.set(\"sdk\", \"1\");\r\n url.searchParams.set(\"origin\", window.location.origin);\r\n url.searchParams.set(\"mode\", \"popup\");\r\n\r\n if (input.actionKey) {\r\n url.searchParams.set(\"actionKey\", input.actionKey);\r\n }\r\n\r\n return url.toString();\r\n}\r\n\r\nexport class HumanGateway {\r\n private readonly projectId: string;\r\n private readonly environment: NonNullable<HumanGatewayOptions[\"environment\"]>;\r\n private readonly mode: NonNullable<HumanGatewayOptions[\"mode\"]>;\r\n private readonly baseUrl: string;\r\n private readonly timeoutMs: number;\r\n private activeVerification: Promise<HumanGatewayResult> | null = null;\r\n private activeAuth: Promise<HumanGatewayAuthResult> | null = null;\r\n\r\n constructor(options: HumanGatewayOptions) {\r\n if (!options.projectId) {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"HumanGateway requires a projectId.\"\r\n );\r\n }\r\n\r\n this.projectId = options.projectId;\r\n this.environment = options.environment ?? \"production\";\r\n this.mode = options.mode ?? \"auto\";\r\n this.baseUrl = options.baseUrl ?? getDefaultBaseUrl(this.environment);\r\n this.timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\r\n }\r\n\r\n async verify(\r\n verifyOptions: HumanGatewayVerifyOptions = {}\r\n ): Promise<HumanGatewayResult> {\r\n if (this.activeVerification) {\r\n return this.activeVerification;\r\n }\r\n\r\n this.activeVerification = this.runVerification(verifyOptions).finally(() => {\r\n this.activeVerification = null;\r\n });\r\n\r\n return this.activeVerification;\r\n }\r\n\r\n async auth(\r\n authOptions: HumanGatewayAuthOptions = {}\r\n ): Promise<HumanGatewayAuthResult> {\r\n if (this.activeAuth) {\r\n return this.activeAuth;\r\n }\r\n\r\n this.activeAuth = this.runAuth(authOptions).finally(() => {\r\n this.activeAuth = null;\r\n });\r\n\r\n return this.activeAuth;\r\n }\r\n\r\n private async runVerification(\r\n verifyOptions: HumanGatewayVerifyOptions\r\n ): Promise<HumanGatewayResult> {\r\n try {\r\n if (typeof window === \"undefined\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"HumanGateway.verify() requires a browser environment.\"\r\n );\r\n }\r\n\r\n if (this.mode === \"redirect\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"Redirect mode is not implemented in this SDK alpha.\"\r\n );\r\n }\r\n\r\n const verificationUrl = buildVerificationUrl({\r\n baseUrl: this.baseUrl,\r\n projectId: this.projectId,\r\n ...(verifyOptions.actionKey\r\n ? { actionKey: verifyOptions.actionKey }\r\n : {}),\r\n });\r\n\r\n const expectedOrigin = new URL(this.baseUrl).origin;\r\n\r\n const popup = openVerificationPopup({\r\n url: verificationUrl,\r\n });\r\n\r\n verifyOptions.onOpen?.();\r\n\r\n const result = await waitForVerificationMessage({\r\n popup,\r\n expectedOrigin,\r\n expectedProjectId: this.projectId,\r\n timeoutMs: this.timeoutMs,\r\n ...(verifyOptions.onClose\r\n ? { onClose: verifyOptions.onClose }\r\n : {}),\r\n });\r\n\r\n verifyOptions.onSuccess?.(result);\r\n\r\n try {\r\n popup.close();\r\n } catch {\r\n // Ignore close errors. Some browsers may block programmatic close.\r\n }\r\n\r\n return result;\r\n } catch (error) {\r\n const normalizedError =\r\n error instanceof HumanGatewayError\r\n ? error\r\n : new HumanGatewayError(\r\n \"unknown_error\",\r\n error instanceof Error\r\n ? error.message\r\n : \"Unknown Human Gateway SDK error.\"\r\n );\r\n\r\n verifyOptions.onError?.(normalizedError);\r\n\r\n throw normalizedError;\r\n }\r\n }\r\n\r\n private async runAuth(\r\n authOptions: HumanGatewayAuthOptions\r\n ): Promise<HumanGatewayAuthResult> {\r\n try {\r\n if (typeof window === \"undefined\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"HumanGateway.auth() requires a browser environment.\"\r\n );\r\n }\r\n\r\n if (this.mode === \"redirect\") {\r\n throw new HumanGatewayError(\r\n \"unknown_error\",\r\n \"Redirect mode is not implemented in this SDK alpha.\"\r\n );\r\n }\r\n\r\n const authUrl = buildAuthUrl({\r\n baseUrl: this.baseUrl,\r\n projectId: this.projectId,\r\n ...(authOptions.actionKey ? { actionKey: authOptions.actionKey } : {}),\r\n });\r\n\r\n const expectedOrigin = new URL(this.baseUrl).origin;\r\n\r\n const popup = openVerificationPopup({\r\n url: authUrl,\r\n });\r\n\r\n authOptions.onOpen?.();\r\n\r\n const result = await waitForAuthMessage({\r\n popup,\r\n expectedOrigin,\r\n expectedProjectId: this.projectId,\r\n timeoutMs: this.timeoutMs,\r\n ...(authOptions.onClose\r\n ? { onClose: authOptions.onClose }\r\n : {}),\r\n });\r\n\r\n authOptions.onSuccess?.(result);\r\n\r\n try {\r\n popup.close();\r\n } catch {\r\n // Ignore close errors. Some browsers may block programmatic close.\r\n }\r\n\r\n return result;\r\n } catch (error) {\r\n const normalizedError =\r\n error instanceof HumanGatewayError\r\n ? error\r\n : new HumanGatewayError(\r\n \"unknown_error\",\r\n error instanceof Error\r\n ? error.message\r\n : \"Unknown Human Gateway SDK auth error.\"\r\n );\r\n\r\n authOptions.onError?.(normalizedError);\r\n\r\n throw normalizedError;\r\n }\r\n }\r\n}"],"mappings":"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","names":["getPopupFeatures","width","height","safeWidth","safeHeight","left","top","openVerificationPopup","url","HumanGatewayError","popup","isHumanGatewayVerificationMessage","value","message","isHumanGatewayAuthMessage","waitForVerificationMessage","popup","expectedOrigin","expectedProjectId","timeoutMs","onClose","resolve","reject","settled","cleanup","onMessage","timeoutId","closeCheckId","settleResolve","result","settleReject","error","event","HumanGatewayError","waitForAuthMessage","DEFAULT_TIMEOUT_MS","getDefaultBaseUrl","environment","buildVerificationUrl","input","url","buildAuthUrl","HumanGateway","options","HumanGatewayError","verifyOptions","authOptions","verificationUrl","expectedOrigin","popup","openVerificationPopup","result","waitForVerificationMessage","error","normalizedError","authUrl","waitForAuthMessage"]}
|
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";var b=Object.defineProperty;var G=Object.getOwnPropertyDescriptor;var C=Object.getOwnPropertyNames;var E=Object.prototype.hasOwnProperty;var x=(e,a)=>{for(var t in a)b(e,t,{get:a[t],enumerable:!0})},j=(e,a,t,i)=>{if(a&&typeof a=="object"||typeof a=="function")for(let r of C(a))!E.call(e,r)&&r!==t&&b(e,r,{get:()=>a[r],enumerable:!(i=G(a,r))||i.enumerable});return e};var A=e=>j(b({},"__esModule",{value:!0}),e);var q={};x(q,{HumanGatewayCallbackError:()=>n,verifyCallback:()=>v,verifyCallbackSignature:()=>m});module.exports=A(q);var g=require("buffer"),d=require("crypto"),N=300*1e3;function m({rawBody:e,timestamp:a,signature:t,secret:i,toleranceMs:r=N}){if(!e||!a||!t||!i)return!1;let l=Number(a);if(!Number.isFinite(l)||Math.abs(Date.now()-l)>r||!/^[a-f0-9]{64}$/i.test(t))return!1;let y=(0,d.createHmac)("sha256",i).update(`${a}.${e}`).digest("hex"),o=g.Buffer.from(y,"hex"),c=g.Buffer.from(t,"hex");return o.length!==c.length?!1:(0,d.timingSafeEqual)(o,c)}var n=class extends Error{constructor(a,t){super(t),this.name="HumanGatewayCallbackError",this.code=a}};var S=300*1e3,I="x-hg-event-id",R="x-hg-event",M="x-hg-project-id",V="x-hg-timestamp",P="x-hg-signature";function O(e,a){let t=e;if(typeof t.get=="function")return t.get(a);let i=a.toLowerCase();for(let[r,l]of Object.entries(e))if(r.toLowerCase()===i)return Array.isArray(l)?l[0]??null:l??null;return null}function s(e,a){let t=O(e,a);if(!t)throw new n("callback_missing_header",`Missing required Human Gateway callback header: ${a}.`);return t}function T(e){let a=Number(e.timestamp);if(!Number.isFinite(a))throw new n("callback_invalid_timestamp","Human Gateway callback timestamp is invalid.");if(Math.abs(Date.now()-a)>e.toleranceMs)throw new n("callback_expired_timestamp","Human Gateway callback timestamp is outside the allowed tolerance.");return a}function D(e){let a;try{a=JSON.parse(e)}catch{throw new n("callback_invalid_json","Human Gateway callback body is not valid JSON.")}if(typeof a!="object"||a===null||Array.isArray(a))throw new n("callback_invalid_payload","Human Gateway callback payload must be a JSON object.");return a}function w(e){let a=e.payload[e.field];if(typeof a!="string"||!a)throw new n("callback_invalid_payload",`Human Gateway callback payload is missing a valid ${e.field}.`);return a}function p(e){if(e.actual!==e.expected)throw new n(e.code,e.message)}function v({body:e,headers:a,secret:t,toleranceMs:i=S,expectedProjectId:r}){if(!e)throw new n("callback_missing_body","Human Gateway callback raw body is required.");if(!t)throw new n("callback_missing_secret","Human Gateway callback secret is required.");let l=s(a,I),f=s(a,R),y=s(a,M),o=s(a,V),c=s(a,P);if(!/^[a-f0-9]{64}$/i.test(c))throw new n("callback_invalid_signature_format","Human Gateway callback signature format is invalid.");let h=T({timestamp:o,toleranceMs:i});if(!m({rawBody:e,timestamp:o,signature:c,secret:t,toleranceMs:i}))throw new n("callback_invalid_signature","Human Gateway callback signature is invalid.");let u=D(e),k=w({payload:u,field:"event_id"}),H=w({payload:u,field:"event"}),_=w({payload:u,field:"project_id"});return p({actual:k,expected:l,code:"callback_event_id_mismatch",message:"Human Gateway callback event_id does not match the signed header."}),p({actual:H,expected:f,code:"callback_event_type_mismatch",message:"Human Gateway callback event type does not match the signed header."}),p({actual:_,expected:y,code:"callback_project_id_mismatch",message:"Human Gateway callback project_id does not match the signed header."}),r&&p({actual:_,expected:r,code:"callback_project_id_mismatch",message:"Human Gateway callback project_id does not match the expected project."}),{event_id:k,event:H,project_id:_,timestamp:h,payload:u}}0&&(module.exports={HumanGatewayCallbackError,verifyCallback,verifyCallbackSignature});
|
|
2
|
+
//# sourceMappingURL=server.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server.ts","../src/verify-callback-signature.ts","../src/types.ts","../src/verify-callback.ts"],"sourcesContent":["export {\r\n verifyCallbackSignature,\r\n type VerifyCallbackSignatureInput,\r\n} from \"./verify-callback-signature\";\r\n\r\nexport { verifyCallback } from \"./verify-callback\";\r\n\r\nexport type {\r\n HumanGatewayCallbackErrorCode,\r\n HumanGatewayCallbackEventName,\r\n HumanGatewayCallbackHeaders,\r\n HumanGatewayCallbackPayload,\r\n VerifiedHumanGatewayCallback,\r\n VerifyCallbackInput,\r\n} from \"./types\";\r\n\r\nexport { HumanGatewayCallbackError } from \"./types\";","import { Buffer } from \"node:buffer\";\r\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\r\n\r\nexport type VerifyCallbackSignatureInput = {\r\n rawBody: string;\r\n timestamp: string | null | undefined;\r\n signature: string | null | undefined;\r\n secret: string;\r\n toleranceMs?: number;\r\n};\r\n\r\nconst DEFAULT_TOLERANCE_MS = 5 * 60 * 1000;\r\n\r\nexport function verifyCallbackSignature({\r\n rawBody,\r\n timestamp,\r\n signature,\r\n secret,\r\n toleranceMs = DEFAULT_TOLERANCE_MS,\r\n}: VerifyCallbackSignatureInput): boolean {\r\n if (!rawBody || !timestamp || !signature || !secret) {\r\n return false;\r\n }\r\n\r\n const timestampNumber = Number(timestamp);\r\n\r\n if (!Number.isFinite(timestampNumber)) {\r\n return false;\r\n }\r\n\r\n const age = Math.abs(Date.now() - timestampNumber);\r\n\r\n if (age > toleranceMs) {\r\n return false;\r\n }\r\n\r\n if (!/^[a-f0-9]{64}$/i.test(signature)) {\r\n return false;\r\n }\r\n\r\n const expectedSignature = createHmac(\"sha256\", secret)\r\n .update(`${timestamp}.${rawBody}`)\r\n .digest(\"hex\");\r\n\r\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\r\n const receivedBuffer = Buffer.from(signature, \"hex\");\r\n\r\n if (expectedBuffer.length !== receivedBuffer.length) {\r\n return false;\r\n }\r\n\r\n return timingSafeEqual(expectedBuffer, receivedBuffer);\r\n}","export type HumanGatewayEnvironment =\r\n | \"production\"\r\n | \"staging\"\r\n | \"development\";\r\n\r\nexport type HumanGatewayMode =\r\n | \"auto\"\r\n | \"popup\"\r\n | \"modal\"\r\n | \"redirect\";\r\n\r\nexport type HumanGatewayOptions = {\r\n projectId: string;\r\n environment?: HumanGatewayEnvironment;\r\n mode?: HumanGatewayMode;\r\n baseUrl?: string;\r\n timeoutMs?: number;\r\n};\r\n\r\nexport type HumanGatewayVerifyOptions = {\r\n actionKey?: string;\r\n onOpen?: () => void;\r\n onClose?: () => void;\r\n onSuccess?: (result: HumanGatewayResult) => void;\r\n onError?: (error: HumanGatewayError) => void;\r\n};\r\n\r\nexport type HumanGatewayAuthOptions = {\r\n actionKey?: string;\r\n onOpen?: () => void;\r\n onClose?: () => void;\r\n onSuccess?: (result: HumanGatewayAuthResult) => void;\r\n onError?: (error: HumanGatewayError) => void;\r\n};\r\n\r\nexport type HumanGatewayResult = {\r\n success: boolean;\r\n verified_human: boolean;\r\n unique_for_partner: boolean;\r\n already_verified: boolean;\r\n project_id: string;\r\n};\r\n\r\nexport type HumanGatewayAuthResult = {\r\n success: boolean;\r\n event?: \"auth.completed\";\r\n verified_human: boolean;\r\n partner_user_id: string;\r\n auth_session_id: string;\r\n project_id: string;\r\n expires_at: string;\r\n};\r\n\r\nexport type HumanGatewayMessage = {\r\n source: \"human-gateway\";\r\n type: \"human_gateway.verification.completed\";\r\n payload: HumanGatewayResult;\r\n};\r\n\r\nexport type HumanGatewayAuthMessage = {\r\n source: \"human-gateway\";\r\n type: \"human_gateway.auth.completed\";\r\n payload: HumanGatewayAuthResult;\r\n};\r\n\r\nexport type HumanGatewayErrorCode =\r\n | \"popup_blocked\"\r\n | \"user_closed\"\r\n | \"timeout\"\r\n | \"invalid_message\"\r\n | \"invalid_origin\"\r\n | \"verification_failed\"\r\n | \"auth_failed\"\r\n | \"unknown_error\";\r\n\r\nexport class HumanGatewayError extends Error {\r\n code: HumanGatewayErrorCode;\r\n\r\n constructor(code: HumanGatewayErrorCode, message: string) {\r\n super(message);\r\n this.name = \"HumanGatewayError\";\r\n this.code = code;\r\n }\r\n}\r\n\r\nexport type HumanGatewayCallbackEventName =\r\n | \"verification.completed\"\r\n | \"auth.completed\"\r\n | \"callback.test\"\r\n | (string & {});\r\n\r\nexport type HumanGatewayCallbackPayload = Record<string, unknown> & {\r\n event_id?: unknown;\r\n event?: unknown;\r\n project_id?: unknown;\r\n};\r\n\r\nexport type HumanGatewayCallbackHeaders =\r\n | Headers\r\n | Record<string, string | string[] | null | undefined>;\r\n\r\nexport type VerifyCallbackInput = {\r\n body: string;\r\n headers: HumanGatewayCallbackHeaders;\r\n secret: string;\r\n toleranceMs?: number;\r\n expectedProjectId?: string;\r\n};\r\n\r\nexport type VerifiedHumanGatewayCallback = {\r\n event_id: string;\r\n event: HumanGatewayCallbackEventName;\r\n project_id: string;\r\n timestamp: number;\r\n payload: HumanGatewayCallbackPayload;\r\n};\r\n\r\nexport type HumanGatewayCallbackErrorCode =\r\n | \"callback_missing_body\"\r\n | \"callback_missing_secret\"\r\n | \"callback_missing_header\"\r\n | \"callback_invalid_timestamp\"\r\n | \"callback_expired_timestamp\"\r\n | \"callback_invalid_signature_format\"\r\n | \"callback_invalid_signature\"\r\n | \"callback_invalid_json\"\r\n | \"callback_invalid_payload\"\r\n | \"callback_event_id_mismatch\"\r\n | \"callback_event_type_mismatch\"\r\n | \"callback_project_id_mismatch\";\r\n\r\nexport class HumanGatewayCallbackError extends Error {\r\n code: HumanGatewayCallbackErrorCode;\r\n\r\n constructor(code: HumanGatewayCallbackErrorCode, message: string) {\r\n super(message);\r\n this.name = \"HumanGatewayCallbackError\";\r\n this.code = code;\r\n }\r\n}","import { verifyCallbackSignature } from \"./verify-callback-signature\";\r\nimport {\r\n HumanGatewayCallbackError,\r\n HumanGatewayCallbackHeaders,\r\n HumanGatewayCallbackPayload,\r\n VerifiedHumanGatewayCallback,\r\n VerifyCallbackInput,\r\n} from \"./types\";\r\n\r\nconst DEFAULT_TOLERANCE_MS = 5 * 60 * 1000;\r\n\r\nconst HEADER_EVENT_ID = \"x-hg-event-id\";\r\nconst HEADER_EVENT = \"x-hg-event\";\r\nconst HEADER_PROJECT_ID = \"x-hg-project-id\";\r\nconst HEADER_TIMESTAMP = \"x-hg-timestamp\";\r\nconst HEADER_SIGNATURE = \"x-hg-signature\";\r\n\r\nfunction getHeader(\r\n headers: HumanGatewayCallbackHeaders,\r\n name: string\r\n): string | null {\r\n const maybeHeaders = headers as {\r\n get?: (headerName: string) => string | null;\r\n };\r\n\r\n if (typeof maybeHeaders.get === \"function\") {\r\n return maybeHeaders.get(name);\r\n }\r\n\r\n const normalizedName = name.toLowerCase();\r\n\r\n for (const [key, value] of Object.entries(headers)) {\r\n if (key.toLowerCase() !== normalizedName) {\r\n continue;\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return value[0] ?? null;\r\n }\r\n\r\n return value ?? null;\r\n }\r\n\r\n return null;\r\n}\r\n\r\nfunction requireHeader(\r\n headers: HumanGatewayCallbackHeaders,\r\n name: string\r\n): string {\r\n const value = getHeader(headers, name);\r\n\r\n if (!value) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_missing_header\",\r\n `Missing required Human Gateway callback header: ${name}.`\r\n );\r\n }\r\n\r\n return value;\r\n}\r\n\r\nfunction parseTimestamp(input: {\r\n timestamp: string;\r\n toleranceMs: number;\r\n}): number {\r\n const timestampNumber = Number(input.timestamp);\r\n\r\n if (!Number.isFinite(timestampNumber)) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_timestamp\",\r\n \"Human Gateway callback timestamp is invalid.\"\r\n );\r\n }\r\n\r\n const age = Math.abs(Date.now() - timestampNumber);\r\n\r\n if (age > input.toleranceMs) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_expired_timestamp\",\r\n \"Human Gateway callback timestamp is outside the allowed tolerance.\"\r\n );\r\n }\r\n\r\n return timestampNumber;\r\n}\r\n\r\nfunction parsePayload(body: string): HumanGatewayCallbackPayload {\r\n let parsed: unknown;\r\n\r\n try {\r\n parsed = JSON.parse(body);\r\n } catch {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_json\",\r\n \"Human Gateway callback body is not valid JSON.\"\r\n );\r\n }\r\n\r\n if (\r\n typeof parsed !== \"object\" ||\r\n parsed === null ||\r\n Array.isArray(parsed)\r\n ) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_payload\",\r\n \"Human Gateway callback payload must be a JSON object.\"\r\n );\r\n }\r\n\r\n return parsed as HumanGatewayCallbackPayload;\r\n}\r\n\r\nfunction requireStringPayloadField(input: {\r\n payload: HumanGatewayCallbackPayload;\r\n field: \"event_id\" | \"event\" | \"project_id\";\r\n}): string {\r\n const value = input.payload[input.field];\r\n\r\n if (typeof value !== \"string\" || !value) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_payload\",\r\n `Human Gateway callback payload is missing a valid ${input.field}.`\r\n );\r\n }\r\n\r\n return value;\r\n}\r\n\r\nfunction assertMatches(input: {\r\n actual: string;\r\n expected: string;\r\n code:\r\n | \"callback_event_id_mismatch\"\r\n | \"callback_event_type_mismatch\"\r\n | \"callback_project_id_mismatch\";\r\n message: string;\r\n}): void {\r\n if (input.actual !== input.expected) {\r\n throw new HumanGatewayCallbackError(input.code, input.message);\r\n }\r\n}\r\n\r\nexport function verifyCallback({\r\n body,\r\n headers,\r\n secret,\r\n toleranceMs = DEFAULT_TOLERANCE_MS,\r\n expectedProjectId,\r\n}: VerifyCallbackInput): VerifiedHumanGatewayCallback {\r\n if (!body) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_missing_body\",\r\n \"Human Gateway callback raw body is required.\"\r\n );\r\n }\r\n\r\n if (!secret) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_missing_secret\",\r\n \"Human Gateway callback secret is required.\"\r\n );\r\n }\r\n\r\n const headerEventId = requireHeader(headers, HEADER_EVENT_ID);\r\n const headerEvent = requireHeader(headers, HEADER_EVENT);\r\n const headerProjectId = requireHeader(headers, HEADER_PROJECT_ID);\r\n const headerTimestamp = requireHeader(headers, HEADER_TIMESTAMP);\r\n const headerSignature = requireHeader(headers, HEADER_SIGNATURE);\r\n\r\n if (!/^[a-f0-9]{64}$/i.test(headerSignature)) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_signature_format\",\r\n \"Human Gateway callback signature format is invalid.\"\r\n );\r\n }\r\n\r\n const timestamp = parseTimestamp({\r\n timestamp: headerTimestamp,\r\n toleranceMs,\r\n });\r\n\r\n const signatureIsValid = verifyCallbackSignature({\r\n rawBody: body,\r\n timestamp: headerTimestamp,\r\n signature: headerSignature,\r\n secret,\r\n toleranceMs,\r\n });\r\n\r\n if (!signatureIsValid) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_signature\",\r\n \"Human Gateway callback signature is invalid.\"\r\n );\r\n }\r\n\r\n const payload = parsePayload(body);\r\n\r\n const payloadEventId = requireStringPayloadField({\r\n payload,\r\n field: \"event_id\",\r\n });\r\n\r\n const payloadEvent = requireStringPayloadField({\r\n payload,\r\n field: \"event\",\r\n });\r\n\r\n const payloadProjectId = requireStringPayloadField({\r\n payload,\r\n field: \"project_id\",\r\n });\r\n\r\n assertMatches({\r\n actual: payloadEventId,\r\n expected: headerEventId,\r\n code: \"callback_event_id_mismatch\",\r\n message:\r\n \"Human Gateway callback event_id does not match the signed header.\",\r\n });\r\n\r\n assertMatches({\r\n actual: payloadEvent,\r\n expected: headerEvent,\r\n code: \"callback_event_type_mismatch\",\r\n message:\r\n \"Human Gateway callback event type does not match the signed header.\",\r\n });\r\n\r\n assertMatches({\r\n actual: payloadProjectId,\r\n expected: headerProjectId,\r\n code: \"callback_project_id_mismatch\",\r\n message:\r\n \"Human Gateway callback project_id does not match the signed header.\",\r\n });\r\n\r\n if (expectedProjectId) {\r\n assertMatches({\r\n actual: payloadProjectId,\r\n expected: expectedProjectId,\r\n code: \"callback_project_id_mismatch\",\r\n message:\r\n \"Human Gateway callback project_id does not match the expected project.\",\r\n });\r\n }\r\n\r\n return {\r\n event_id: payloadEventId,\r\n event: payloadEvent,\r\n project_id: payloadProjectId,\r\n timestamp,\r\n payload,\r\n };\r\n}"],"mappings":"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","names":["server_exports","__export","HumanGatewayCallbackError","verifyCallback","verifyCallbackSignature","__toCommonJS","import_node_buffer","import_node_crypto","DEFAULT_TOLERANCE_MS","verifyCallbackSignature","rawBody","timestamp","signature","secret","toleranceMs","timestampNumber","expectedSignature","expectedBuffer","receivedBuffer","HumanGatewayCallbackError","code","message","DEFAULT_TOLERANCE_MS","HEADER_EVENT_ID","HEADER_EVENT","HEADER_PROJECT_ID","HEADER_TIMESTAMP","HEADER_SIGNATURE","getHeader","headers","name","maybeHeaders","normalizedName","key","value","requireHeader","HumanGatewayCallbackError","parseTimestamp","input","timestampNumber","parsePayload","body","parsed","requireStringPayloadField","assertMatches","verifyCallback","secret","toleranceMs","expectedProjectId","headerEventId","headerEvent","headerProjectId","headerTimestamp","headerSignature","timestamp","verifyCallbackSignature","payload","payloadEventId","payloadEvent","payloadProjectId"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { p as VerifyCallbackInput, V as VerifiedHumanGatewayCallback } from './types-D8bnQbLL.cjs';
|
|
2
|
+
export { c as HumanGatewayCallbackError, d as HumanGatewayCallbackErrorCode, e as HumanGatewayCallbackEventName, f as HumanGatewayCallbackHeaders, g as HumanGatewayCallbackPayload } from './types-D8bnQbLL.cjs';
|
|
3
|
+
|
|
4
|
+
type VerifyCallbackSignatureInput = {
|
|
5
|
+
rawBody: string;
|
|
6
|
+
timestamp: string | null | undefined;
|
|
7
|
+
signature: string | null | undefined;
|
|
8
|
+
secret: string;
|
|
9
|
+
toleranceMs?: number;
|
|
10
|
+
};
|
|
11
|
+
declare function verifyCallbackSignature({ rawBody, timestamp, signature, secret, toleranceMs, }: VerifyCallbackSignatureInput): boolean;
|
|
12
|
+
|
|
13
|
+
declare function verifyCallback({ body, headers, secret, toleranceMs, expectedProjectId, }: VerifyCallbackInput): VerifiedHumanGatewayCallback;
|
|
14
|
+
|
|
15
|
+
export { VerifiedHumanGatewayCallback, VerifyCallbackInput, type VerifyCallbackSignatureInput, verifyCallback, verifyCallbackSignature };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { p as VerifyCallbackInput, V as VerifiedHumanGatewayCallback } from './types-D8bnQbLL.js';
|
|
2
|
+
export { c as HumanGatewayCallbackError, d as HumanGatewayCallbackErrorCode, e as HumanGatewayCallbackEventName, f as HumanGatewayCallbackHeaders, g as HumanGatewayCallbackPayload } from './types-D8bnQbLL.js';
|
|
3
|
+
|
|
4
|
+
type VerifyCallbackSignatureInput = {
|
|
5
|
+
rawBody: string;
|
|
6
|
+
timestamp: string | null | undefined;
|
|
7
|
+
signature: string | null | undefined;
|
|
8
|
+
secret: string;
|
|
9
|
+
toleranceMs?: number;
|
|
10
|
+
};
|
|
11
|
+
declare function verifyCallbackSignature({ rawBody, timestamp, signature, secret, toleranceMs, }: VerifyCallbackSignatureInput): boolean;
|
|
12
|
+
|
|
13
|
+
declare function verifyCallback({ body, headers, secret, toleranceMs, expectedProjectId, }: VerifyCallbackInput): VerifiedHumanGatewayCallback;
|
|
14
|
+
|
|
15
|
+
export { VerifiedHumanGatewayCallback, VerifyCallbackInput, type VerifyCallbackSignatureInput, verifyCallback, verifyCallbackSignature };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{b as n}from"./chunk-3SSCLKQD.js";import{Buffer as k}from"buffer";import{createHmac as h,timingSafeEqual as H}from"crypto";var v=300*1e3;function y({rawBody:e,timestamp:a,signature:t,secret:r,toleranceMs:i=v}){if(!e||!a||!t||!r)return!1;let l=Number(a);if(!Number.isFinite(l)||Math.abs(Date.now()-l)>i||!/^[a-f0-9]{64}$/i.test(t))return!1;let u=h("sha256",r).update(`${a}.${e}`).digest("hex"),c=k.from(u,"hex"),o=k.from(t,"hex");return c.length!==o.length?!1:H(c,o)}var C=300*1e3,E="x-hg-event-id",G="x-hg-event",x="x-hg-project-id",N="x-hg-timestamp",S="x-hg-signature";function j(e,a){let t=e;if(typeof t.get=="function")return t.get(a);let r=a.toLowerCase();for(let[i,l]of Object.entries(e))if(i.toLowerCase()===r)return Array.isArray(l)?l[0]??null:l??null;return null}function s(e,a){let t=j(e,a);if(!t)throw new n("callback_missing_header",`Missing required Human Gateway callback header: ${a}.`);return t}function A(e){let a=Number(e.timestamp);if(!Number.isFinite(a))throw new n("callback_invalid_timestamp","Human Gateway callback timestamp is invalid.");if(Math.abs(Date.now()-a)>e.toleranceMs)throw new n("callback_expired_timestamp","Human Gateway callback timestamp is outside the allowed tolerance.");return a}function I(e){let a;try{a=JSON.parse(e)}catch{throw new n("callback_invalid_json","Human Gateway callback body is not valid JSON.")}if(typeof a!="object"||a===null||Array.isArray(a))throw new n("callback_invalid_payload","Human Gateway callback payload must be a JSON object.");return a}function b(e){let a=e.payload[e.field];if(typeof a!="string"||!a)throw new n("callback_invalid_payload",`Human Gateway callback payload is missing a valid ${e.field}.`);return a}function d(e){if(e.actual!==e.expected)throw new n(e.code,e.message)}function V({body:e,headers:a,secret:t,toleranceMs:r=C,expectedProjectId:i}){if(!e)throw new n("callback_missing_body","Human Gateway callback raw body is required.");if(!t)throw new n("callback_missing_secret","Human Gateway callback secret is required.");let l=s(a,E),p=s(a,G),u=s(a,x),c=s(a,N),o=s(a,S);if(!/^[a-f0-9]{64}$/i.test(o))throw new n("callback_invalid_signature_format","Human Gateway callback signature format is invalid.");let w=A({timestamp:c,toleranceMs:r});if(!y({rawBody:e,timestamp:c,signature:o,secret:t,toleranceMs:r}))throw new n("callback_invalid_signature","Human Gateway callback signature is invalid.");let m=I(e),g=b({payload:m,field:"event_id"}),_=b({payload:m,field:"event"}),f=b({payload:m,field:"project_id"});return d({actual:g,expected:l,code:"callback_event_id_mismatch",message:"Human Gateway callback event_id does not match the signed header."}),d({actual:_,expected:p,code:"callback_event_type_mismatch",message:"Human Gateway callback event type does not match the signed header."}),d({actual:f,expected:u,code:"callback_project_id_mismatch",message:"Human Gateway callback project_id does not match the signed header."}),i&&d({actual:f,expected:i,code:"callback_project_id_mismatch",message:"Human Gateway callback project_id does not match the expected project."}),{event_id:g,event:_,project_id:f,timestamp:w,payload:m}}export{n as HumanGatewayCallbackError,V as verifyCallback,y as verifyCallbackSignature};
|
|
2
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/verify-callback-signature.ts","../src/verify-callback.ts"],"sourcesContent":["import { Buffer } from \"node:buffer\";\r\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\r\n\r\nexport type VerifyCallbackSignatureInput = {\r\n rawBody: string;\r\n timestamp: string | null | undefined;\r\n signature: string | null | undefined;\r\n secret: string;\r\n toleranceMs?: number;\r\n};\r\n\r\nconst DEFAULT_TOLERANCE_MS = 5 * 60 * 1000;\r\n\r\nexport function verifyCallbackSignature({\r\n rawBody,\r\n timestamp,\r\n signature,\r\n secret,\r\n toleranceMs = DEFAULT_TOLERANCE_MS,\r\n}: VerifyCallbackSignatureInput): boolean {\r\n if (!rawBody || !timestamp || !signature || !secret) {\r\n return false;\r\n }\r\n\r\n const timestampNumber = Number(timestamp);\r\n\r\n if (!Number.isFinite(timestampNumber)) {\r\n return false;\r\n }\r\n\r\n const age = Math.abs(Date.now() - timestampNumber);\r\n\r\n if (age > toleranceMs) {\r\n return false;\r\n }\r\n\r\n if (!/^[a-f0-9]{64}$/i.test(signature)) {\r\n return false;\r\n }\r\n\r\n const expectedSignature = createHmac(\"sha256\", secret)\r\n .update(`${timestamp}.${rawBody}`)\r\n .digest(\"hex\");\r\n\r\n const expectedBuffer = Buffer.from(expectedSignature, \"hex\");\r\n const receivedBuffer = Buffer.from(signature, \"hex\");\r\n\r\n if (expectedBuffer.length !== receivedBuffer.length) {\r\n return false;\r\n }\r\n\r\n return timingSafeEqual(expectedBuffer, receivedBuffer);\r\n}","import { verifyCallbackSignature } from \"./verify-callback-signature\";\r\nimport {\r\n HumanGatewayCallbackError,\r\n HumanGatewayCallbackHeaders,\r\n HumanGatewayCallbackPayload,\r\n VerifiedHumanGatewayCallback,\r\n VerifyCallbackInput,\r\n} from \"./types\";\r\n\r\nconst DEFAULT_TOLERANCE_MS = 5 * 60 * 1000;\r\n\r\nconst HEADER_EVENT_ID = \"x-hg-event-id\";\r\nconst HEADER_EVENT = \"x-hg-event\";\r\nconst HEADER_PROJECT_ID = \"x-hg-project-id\";\r\nconst HEADER_TIMESTAMP = \"x-hg-timestamp\";\r\nconst HEADER_SIGNATURE = \"x-hg-signature\";\r\n\r\nfunction getHeader(\r\n headers: HumanGatewayCallbackHeaders,\r\n name: string\r\n): string | null {\r\n const maybeHeaders = headers as {\r\n get?: (headerName: string) => string | null;\r\n };\r\n\r\n if (typeof maybeHeaders.get === \"function\") {\r\n return maybeHeaders.get(name);\r\n }\r\n\r\n const normalizedName = name.toLowerCase();\r\n\r\n for (const [key, value] of Object.entries(headers)) {\r\n if (key.toLowerCase() !== normalizedName) {\r\n continue;\r\n }\r\n\r\n if (Array.isArray(value)) {\r\n return value[0] ?? null;\r\n }\r\n\r\n return value ?? null;\r\n }\r\n\r\n return null;\r\n}\r\n\r\nfunction requireHeader(\r\n headers: HumanGatewayCallbackHeaders,\r\n name: string\r\n): string {\r\n const value = getHeader(headers, name);\r\n\r\n if (!value) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_missing_header\",\r\n `Missing required Human Gateway callback header: ${name}.`\r\n );\r\n }\r\n\r\n return value;\r\n}\r\n\r\nfunction parseTimestamp(input: {\r\n timestamp: string;\r\n toleranceMs: number;\r\n}): number {\r\n const timestampNumber = Number(input.timestamp);\r\n\r\n if (!Number.isFinite(timestampNumber)) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_timestamp\",\r\n \"Human Gateway callback timestamp is invalid.\"\r\n );\r\n }\r\n\r\n const age = Math.abs(Date.now() - timestampNumber);\r\n\r\n if (age > input.toleranceMs) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_expired_timestamp\",\r\n \"Human Gateway callback timestamp is outside the allowed tolerance.\"\r\n );\r\n }\r\n\r\n return timestampNumber;\r\n}\r\n\r\nfunction parsePayload(body: string): HumanGatewayCallbackPayload {\r\n let parsed: unknown;\r\n\r\n try {\r\n parsed = JSON.parse(body);\r\n } catch {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_json\",\r\n \"Human Gateway callback body is not valid JSON.\"\r\n );\r\n }\r\n\r\n if (\r\n typeof parsed !== \"object\" ||\r\n parsed === null ||\r\n Array.isArray(parsed)\r\n ) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_payload\",\r\n \"Human Gateway callback payload must be a JSON object.\"\r\n );\r\n }\r\n\r\n return parsed as HumanGatewayCallbackPayload;\r\n}\r\n\r\nfunction requireStringPayloadField(input: {\r\n payload: HumanGatewayCallbackPayload;\r\n field: \"event_id\" | \"event\" | \"project_id\";\r\n}): string {\r\n const value = input.payload[input.field];\r\n\r\n if (typeof value !== \"string\" || !value) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_payload\",\r\n `Human Gateway callback payload is missing a valid ${input.field}.`\r\n );\r\n }\r\n\r\n return value;\r\n}\r\n\r\nfunction assertMatches(input: {\r\n actual: string;\r\n expected: string;\r\n code:\r\n | \"callback_event_id_mismatch\"\r\n | \"callback_event_type_mismatch\"\r\n | \"callback_project_id_mismatch\";\r\n message: string;\r\n}): void {\r\n if (input.actual !== input.expected) {\r\n throw new HumanGatewayCallbackError(input.code, input.message);\r\n }\r\n}\r\n\r\nexport function verifyCallback({\r\n body,\r\n headers,\r\n secret,\r\n toleranceMs = DEFAULT_TOLERANCE_MS,\r\n expectedProjectId,\r\n}: VerifyCallbackInput): VerifiedHumanGatewayCallback {\r\n if (!body) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_missing_body\",\r\n \"Human Gateway callback raw body is required.\"\r\n );\r\n }\r\n\r\n if (!secret) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_missing_secret\",\r\n \"Human Gateway callback secret is required.\"\r\n );\r\n }\r\n\r\n const headerEventId = requireHeader(headers, HEADER_EVENT_ID);\r\n const headerEvent = requireHeader(headers, HEADER_EVENT);\r\n const headerProjectId = requireHeader(headers, HEADER_PROJECT_ID);\r\n const headerTimestamp = requireHeader(headers, HEADER_TIMESTAMP);\r\n const headerSignature = requireHeader(headers, HEADER_SIGNATURE);\r\n\r\n if (!/^[a-f0-9]{64}$/i.test(headerSignature)) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_signature_format\",\r\n \"Human Gateway callback signature format is invalid.\"\r\n );\r\n }\r\n\r\n const timestamp = parseTimestamp({\r\n timestamp: headerTimestamp,\r\n toleranceMs,\r\n });\r\n\r\n const signatureIsValid = verifyCallbackSignature({\r\n rawBody: body,\r\n timestamp: headerTimestamp,\r\n signature: headerSignature,\r\n secret,\r\n toleranceMs,\r\n });\r\n\r\n if (!signatureIsValid) {\r\n throw new HumanGatewayCallbackError(\r\n \"callback_invalid_signature\",\r\n \"Human Gateway callback signature is invalid.\"\r\n );\r\n }\r\n\r\n const payload = parsePayload(body);\r\n\r\n const payloadEventId = requireStringPayloadField({\r\n payload,\r\n field: \"event_id\",\r\n });\r\n\r\n const payloadEvent = requireStringPayloadField({\r\n payload,\r\n field: \"event\",\r\n });\r\n\r\n const payloadProjectId = requireStringPayloadField({\r\n payload,\r\n field: \"project_id\",\r\n });\r\n\r\n assertMatches({\r\n actual: payloadEventId,\r\n expected: headerEventId,\r\n code: \"callback_event_id_mismatch\",\r\n message:\r\n \"Human Gateway callback event_id does not match the signed header.\",\r\n });\r\n\r\n assertMatches({\r\n actual: payloadEvent,\r\n expected: headerEvent,\r\n code: \"callback_event_type_mismatch\",\r\n message:\r\n \"Human Gateway callback event type does not match the signed header.\",\r\n });\r\n\r\n assertMatches({\r\n actual: payloadProjectId,\r\n expected: headerProjectId,\r\n code: \"callback_project_id_mismatch\",\r\n message:\r\n \"Human Gateway callback project_id does not match the signed header.\",\r\n });\r\n\r\n if (expectedProjectId) {\r\n assertMatches({\r\n actual: payloadProjectId,\r\n expected: expectedProjectId,\r\n code: \"callback_project_id_mismatch\",\r\n message:\r\n \"Human Gateway callback project_id does not match the expected project.\",\r\n });\r\n }\r\n\r\n return {\r\n event_id: payloadEventId,\r\n event: payloadEvent,\r\n project_id: payloadProjectId,\r\n timestamp,\r\n payload,\r\n };\r\n}"],"mappings":"wCAAA,OAAS,UAAAA,MAAc,SACvB,OAAS,cAAAC,EAAY,mBAAAC,MAAuB,SAU5C,IAAMC,EAAuB,IAAS,IAE/B,SAASC,EAAwB,CACpC,QAAAC,EACA,UAAAC,EACA,UAAAC,EACA,OAAAC,EACA,YAAAC,EAAcN,CAClB,EAA0C,CACtC,GAAI,CAACE,GAAW,CAACC,GAAa,CAACC,GAAa,CAACC,EACzC,MAAO,GAGX,IAAME,EAAkB,OAAOJ,CAAS,EAYxC,GAVI,CAAC,OAAO,SAASI,CAAe,GAIxB,KAAK,IAAI,KAAK,IAAI,EAAIA,CAAe,EAEvCD,GAIN,CAAC,kBAAkB,KAAKF,CAAS,EACjC,MAAO,GAGX,IAAMI,EAAoBV,EAAW,SAAUO,CAAM,EAChD,OAAO,GAAGF,CAAS,IAAID,CAAO,EAAE,EAChC,OAAO,KAAK,EAEXO,EAAiBZ,EAAO,KAAKW,EAAmB,KAAK,EACrDE,EAAiBb,EAAO,KAAKO,EAAW,KAAK,EAEnD,OAAIK,EAAe,SAAWC,EAAe,OAClC,GAGJX,EAAgBU,EAAgBC,CAAc,CACzD,CC3CA,IAAMC,EAAuB,IAAS,IAEhCC,EAAkB,gBAClBC,EAAe,aACfC,EAAoB,kBACpBC,EAAmB,iBACnBC,EAAmB,iBAEzB,SAASC,EACLC,EACAC,EACa,CACb,IAAMC,EAAeF,EAIrB,GAAI,OAAOE,EAAa,KAAQ,WAC5B,OAAOA,EAAa,IAAID,CAAI,EAGhC,IAAME,EAAiBF,EAAK,YAAY,EAExC,OAAW,CAACG,EAAKC,CAAK,IAAK,OAAO,QAAQL,CAAO,EAC7C,GAAII,EAAI,YAAY,IAAMD,EAI1B,OAAI,MAAM,QAAQE,CAAK,EACZA,EAAM,CAAC,GAAK,KAGhBA,GAAS,KAGpB,OAAO,IACX,CAEA,SAASC,EACLN,EACAC,EACM,CACN,IAAMI,EAAQN,EAAUC,EAASC,CAAI,EAErC,GAAI,CAACI,EACD,MAAM,IAAIE,EACN,0BACA,mDAAmDN,CAAI,GAC3D,EAGJ,OAAOI,CACX,CAEA,SAASG,EAAeC,EAGb,CACP,IAAMC,EAAkB,OAAOD,EAAM,SAAS,EAE9C,GAAI,CAAC,OAAO,SAASC,CAAe,EAChC,MAAM,IAAIH,EACN,6BACA,8CACJ,EAKJ,GAFY,KAAK,IAAI,KAAK,IAAI,EAAIG,CAAe,EAEvCD,EAAM,YACZ,MAAM,IAAIF,EACN,6BACA,oEACJ,EAGJ,OAAOG,CACX,CAEA,SAASC,EAAaC,EAA2C,CAC7D,IAAIC,EAEJ,GAAI,CACAA,EAAS,KAAK,MAAMD,CAAI,CAC5B,MAAQ,CACJ,MAAM,IAAIL,EACN,wBACA,gDACJ,CACJ,CAEA,GACI,OAAOM,GAAW,UAClBA,IAAW,MACX,MAAM,QAAQA,CAAM,EAEpB,MAAM,IAAIN,EACN,2BACA,uDACJ,EAGJ,OAAOM,CACX,CAEA,SAASC,EAA0BL,EAGxB,CACP,IAAMJ,EAAQI,EAAM,QAAQA,EAAM,KAAK,EAEvC,GAAI,OAAOJ,GAAU,UAAY,CAACA,EAC9B,MAAM,IAAIE,EACN,2BACA,qDAAqDE,EAAM,KAAK,GACpE,EAGJ,OAAOJ,CACX,CAEA,SAASU,EAAcN,EAQd,CACL,GAAIA,EAAM,SAAWA,EAAM,SACvB,MAAM,IAAIF,EAA0BE,EAAM,KAAMA,EAAM,OAAO,CAErE,CAEO,SAASO,EAAe,CAC3B,KAAAJ,EACA,QAAAZ,EACA,OAAAiB,EACA,YAAAC,EAAczB,EACd,kBAAA0B,CACJ,EAAsD,CAClD,GAAI,CAACP,EACD,MAAM,IAAIL,EACN,wBACA,8CACJ,EAGJ,GAAI,CAACU,EACD,MAAM,IAAIV,EACN,0BACA,4CACJ,EAGJ,IAAMa,EAAgBd,EAAcN,EAASN,CAAe,EACtD2B,EAAcf,EAAcN,EAASL,CAAY,EACjD2B,EAAkBhB,EAAcN,EAASJ,CAAiB,EAC1D2B,EAAkBjB,EAAcN,EAASH,CAAgB,EACzD2B,EAAkBlB,EAAcN,EAASF,CAAgB,EAE/D,GAAI,CAAC,kBAAkB,KAAK0B,CAAe,EACvC,MAAM,IAAIjB,EACN,oCACA,qDACJ,EAGJ,IAAMkB,EAAYjB,EAAe,CAC7B,UAAWe,EACX,YAAAL,CACJ,CAAC,EAUD,GAAI,CARqBQ,EAAwB,CAC7C,QAASd,EACT,UAAWW,EACX,UAAWC,EACX,OAAAP,EACA,YAAAC,CACJ,CAAC,EAGG,MAAM,IAAIX,EACN,6BACA,8CACJ,EAGJ,IAAMoB,EAAUhB,EAAaC,CAAI,EAE3BgB,EAAiBd,EAA0B,CAC7C,QAAAa,EACA,MAAO,UACX,CAAC,EAEKE,EAAef,EAA0B,CAC3C,QAAAa,EACA,MAAO,OACX,CAAC,EAEKG,EAAmBhB,EAA0B,CAC/C,QAAAa,EACA,MAAO,YACX,CAAC,EAED,OAAAZ,EAAc,CACV,OAAQa,EACR,SAAUR,EACV,KAAM,6BACN,QACI,mEACR,CAAC,EAEDL,EAAc,CACV,OAAQc,EACR,SAAUR,EACV,KAAM,+BACN,QACI,qEACR,CAAC,EAEDN,EAAc,CACV,OAAQe,EACR,SAAUR,EACV,KAAM,+BACN,QACI,qEACR,CAAC,EAEGH,GACAJ,EAAc,CACV,OAAQe,EACR,SAAUX,EACV,KAAM,+BACN,QACI,wEACR,CAAC,EAGE,CACH,SAAUS,EACV,MAAOC,EACP,WAAYC,EACZ,UAAAL,EACA,QAAAE,CACJ,CACJ","names":["Buffer","createHmac","timingSafeEqual","DEFAULT_TOLERANCE_MS","verifyCallbackSignature","rawBody","timestamp","signature","secret","toleranceMs","timestampNumber","expectedSignature","expectedBuffer","receivedBuffer","DEFAULT_TOLERANCE_MS","HEADER_EVENT_ID","HEADER_EVENT","HEADER_PROJECT_ID","HEADER_TIMESTAMP","HEADER_SIGNATURE","getHeader","headers","name","maybeHeaders","normalizedName","key","value","requireHeader","HumanGatewayCallbackError","parseTimestamp","input","timestampNumber","parsePayload","body","parsed","requireStringPayloadField","assertMatches","verifyCallback","secret","toleranceMs","expectedProjectId","headerEventId","headerEvent","headerProjectId","headerTimestamp","headerSignature","timestamp","verifyCallbackSignature","payload","payloadEventId","payloadEvent","payloadProjectId"]}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
type HumanGatewayEnvironment = "production" | "staging" | "development";
|
|
2
|
+
type HumanGatewayMode = "auto" | "popup" | "modal" | "redirect";
|
|
3
|
+
type HumanGatewayOptions = {
|
|
4
|
+
projectId: string;
|
|
5
|
+
environment?: HumanGatewayEnvironment;
|
|
6
|
+
mode?: HumanGatewayMode;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
};
|
|
10
|
+
type HumanGatewayVerifyOptions = {
|
|
11
|
+
actionKey?: string;
|
|
12
|
+
onOpen?: () => void;
|
|
13
|
+
onClose?: () => void;
|
|
14
|
+
onSuccess?: (result: HumanGatewayResult) => void;
|
|
15
|
+
onError?: (error: HumanGatewayError) => void;
|
|
16
|
+
};
|
|
17
|
+
type HumanGatewayAuthOptions = {
|
|
18
|
+
actionKey?: string;
|
|
19
|
+
onOpen?: () => void;
|
|
20
|
+
onClose?: () => void;
|
|
21
|
+
onSuccess?: (result: HumanGatewayAuthResult) => void;
|
|
22
|
+
onError?: (error: HumanGatewayError) => void;
|
|
23
|
+
};
|
|
24
|
+
type HumanGatewayResult = {
|
|
25
|
+
success: boolean;
|
|
26
|
+
verified_human: boolean;
|
|
27
|
+
unique_for_partner: boolean;
|
|
28
|
+
already_verified: boolean;
|
|
29
|
+
project_id: string;
|
|
30
|
+
};
|
|
31
|
+
type HumanGatewayAuthResult = {
|
|
32
|
+
success: boolean;
|
|
33
|
+
event?: "auth.completed";
|
|
34
|
+
verified_human: boolean;
|
|
35
|
+
partner_user_id: string;
|
|
36
|
+
auth_session_id: string;
|
|
37
|
+
project_id: string;
|
|
38
|
+
expires_at: string;
|
|
39
|
+
};
|
|
40
|
+
type HumanGatewayMessage = {
|
|
41
|
+
source: "human-gateway";
|
|
42
|
+
type: "human_gateway.verification.completed";
|
|
43
|
+
payload: HumanGatewayResult;
|
|
44
|
+
};
|
|
45
|
+
type HumanGatewayAuthMessage = {
|
|
46
|
+
source: "human-gateway";
|
|
47
|
+
type: "human_gateway.auth.completed";
|
|
48
|
+
payload: HumanGatewayAuthResult;
|
|
49
|
+
};
|
|
50
|
+
type HumanGatewayErrorCode = "popup_blocked" | "user_closed" | "timeout" | "invalid_message" | "invalid_origin" | "verification_failed" | "auth_failed" | "unknown_error";
|
|
51
|
+
declare class HumanGatewayError extends Error {
|
|
52
|
+
code: HumanGatewayErrorCode;
|
|
53
|
+
constructor(code: HumanGatewayErrorCode, message: string);
|
|
54
|
+
}
|
|
55
|
+
type HumanGatewayCallbackEventName = "verification.completed" | "auth.completed" | "callback.test" | (string & {});
|
|
56
|
+
type HumanGatewayCallbackPayload = Record<string, unknown> & {
|
|
57
|
+
event_id?: unknown;
|
|
58
|
+
event?: unknown;
|
|
59
|
+
project_id?: unknown;
|
|
60
|
+
};
|
|
61
|
+
type HumanGatewayCallbackHeaders = Headers | Record<string, string | string[] | null | undefined>;
|
|
62
|
+
type VerifyCallbackInput = {
|
|
63
|
+
body: string;
|
|
64
|
+
headers: HumanGatewayCallbackHeaders;
|
|
65
|
+
secret: string;
|
|
66
|
+
toleranceMs?: number;
|
|
67
|
+
expectedProjectId?: string;
|
|
68
|
+
};
|
|
69
|
+
type VerifiedHumanGatewayCallback = {
|
|
70
|
+
event_id: string;
|
|
71
|
+
event: HumanGatewayCallbackEventName;
|
|
72
|
+
project_id: string;
|
|
73
|
+
timestamp: number;
|
|
74
|
+
payload: HumanGatewayCallbackPayload;
|
|
75
|
+
};
|
|
76
|
+
type HumanGatewayCallbackErrorCode = "callback_missing_body" | "callback_missing_secret" | "callback_missing_header" | "callback_invalid_timestamp" | "callback_expired_timestamp" | "callback_invalid_signature_format" | "callback_invalid_signature" | "callback_invalid_json" | "callback_invalid_payload" | "callback_event_id_mismatch" | "callback_event_type_mismatch" | "callback_project_id_mismatch";
|
|
77
|
+
declare class HumanGatewayCallbackError extends Error {
|
|
78
|
+
code: HumanGatewayCallbackErrorCode;
|
|
79
|
+
constructor(code: HumanGatewayCallbackErrorCode, message: string);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export { type HumanGatewayAuthMessage as H, type VerifiedHumanGatewayCallback as V, type HumanGatewayAuthOptions as a, type HumanGatewayAuthResult as b, HumanGatewayCallbackError as c, type HumanGatewayCallbackErrorCode as d, type HumanGatewayCallbackEventName as e, type HumanGatewayCallbackHeaders as f, type HumanGatewayCallbackPayload as g, type HumanGatewayEnvironment as h, HumanGatewayError as i, type HumanGatewayErrorCode as j, type HumanGatewayMessage as k, type HumanGatewayMode as l, type HumanGatewayOptions as m, type HumanGatewayResult as n, type HumanGatewayVerifyOptions as o, type VerifyCallbackInput as p };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
type HumanGatewayEnvironment = "production" | "staging" | "development";
|
|
2
|
+
type HumanGatewayMode = "auto" | "popup" | "modal" | "redirect";
|
|
3
|
+
type HumanGatewayOptions = {
|
|
4
|
+
projectId: string;
|
|
5
|
+
environment?: HumanGatewayEnvironment;
|
|
6
|
+
mode?: HumanGatewayMode;
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
timeoutMs?: number;
|
|
9
|
+
};
|
|
10
|
+
type HumanGatewayVerifyOptions = {
|
|
11
|
+
actionKey?: string;
|
|
12
|
+
onOpen?: () => void;
|
|
13
|
+
onClose?: () => void;
|
|
14
|
+
onSuccess?: (result: HumanGatewayResult) => void;
|
|
15
|
+
onError?: (error: HumanGatewayError) => void;
|
|
16
|
+
};
|
|
17
|
+
type HumanGatewayAuthOptions = {
|
|
18
|
+
actionKey?: string;
|
|
19
|
+
onOpen?: () => void;
|
|
20
|
+
onClose?: () => void;
|
|
21
|
+
onSuccess?: (result: HumanGatewayAuthResult) => void;
|
|
22
|
+
onError?: (error: HumanGatewayError) => void;
|
|
23
|
+
};
|
|
24
|
+
type HumanGatewayResult = {
|
|
25
|
+
success: boolean;
|
|
26
|
+
verified_human: boolean;
|
|
27
|
+
unique_for_partner: boolean;
|
|
28
|
+
already_verified: boolean;
|
|
29
|
+
project_id: string;
|
|
30
|
+
};
|
|
31
|
+
type HumanGatewayAuthResult = {
|
|
32
|
+
success: boolean;
|
|
33
|
+
event?: "auth.completed";
|
|
34
|
+
verified_human: boolean;
|
|
35
|
+
partner_user_id: string;
|
|
36
|
+
auth_session_id: string;
|
|
37
|
+
project_id: string;
|
|
38
|
+
expires_at: string;
|
|
39
|
+
};
|
|
40
|
+
type HumanGatewayMessage = {
|
|
41
|
+
source: "human-gateway";
|
|
42
|
+
type: "human_gateway.verification.completed";
|
|
43
|
+
payload: HumanGatewayResult;
|
|
44
|
+
};
|
|
45
|
+
type HumanGatewayAuthMessage = {
|
|
46
|
+
source: "human-gateway";
|
|
47
|
+
type: "human_gateway.auth.completed";
|
|
48
|
+
payload: HumanGatewayAuthResult;
|
|
49
|
+
};
|
|
50
|
+
type HumanGatewayErrorCode = "popup_blocked" | "user_closed" | "timeout" | "invalid_message" | "invalid_origin" | "verification_failed" | "auth_failed" | "unknown_error";
|
|
51
|
+
declare class HumanGatewayError extends Error {
|
|
52
|
+
code: HumanGatewayErrorCode;
|
|
53
|
+
constructor(code: HumanGatewayErrorCode, message: string);
|
|
54
|
+
}
|
|
55
|
+
type HumanGatewayCallbackEventName = "verification.completed" | "auth.completed" | "callback.test" | (string & {});
|
|
56
|
+
type HumanGatewayCallbackPayload = Record<string, unknown> & {
|
|
57
|
+
event_id?: unknown;
|
|
58
|
+
event?: unknown;
|
|
59
|
+
project_id?: unknown;
|
|
60
|
+
};
|
|
61
|
+
type HumanGatewayCallbackHeaders = Headers | Record<string, string | string[] | null | undefined>;
|
|
62
|
+
type VerifyCallbackInput = {
|
|
63
|
+
body: string;
|
|
64
|
+
headers: HumanGatewayCallbackHeaders;
|
|
65
|
+
secret: string;
|
|
66
|
+
toleranceMs?: number;
|
|
67
|
+
expectedProjectId?: string;
|
|
68
|
+
};
|
|
69
|
+
type VerifiedHumanGatewayCallback = {
|
|
70
|
+
event_id: string;
|
|
71
|
+
event: HumanGatewayCallbackEventName;
|
|
72
|
+
project_id: string;
|
|
73
|
+
timestamp: number;
|
|
74
|
+
payload: HumanGatewayCallbackPayload;
|
|
75
|
+
};
|
|
76
|
+
type HumanGatewayCallbackErrorCode = "callback_missing_body" | "callback_missing_secret" | "callback_missing_header" | "callback_invalid_timestamp" | "callback_expired_timestamp" | "callback_invalid_signature_format" | "callback_invalid_signature" | "callback_invalid_json" | "callback_invalid_payload" | "callback_event_id_mismatch" | "callback_event_type_mismatch" | "callback_project_id_mismatch";
|
|
77
|
+
declare class HumanGatewayCallbackError extends Error {
|
|
78
|
+
code: HumanGatewayCallbackErrorCode;
|
|
79
|
+
constructor(code: HumanGatewayCallbackErrorCode, message: string);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export { type HumanGatewayAuthMessage as H, type VerifiedHumanGatewayCallback as V, type HumanGatewayAuthOptions as a, type HumanGatewayAuthResult as b, HumanGatewayCallbackError as c, type HumanGatewayCallbackErrorCode as d, type HumanGatewayCallbackEventName as e, type HumanGatewayCallbackHeaders as f, type HumanGatewayCallbackPayload as g, type HumanGatewayEnvironment as h, HumanGatewayError as i, type HumanGatewayErrorCode as j, type HumanGatewayMessage as k, type HumanGatewayMode as l, type HumanGatewayOptions as m, type HumanGatewayResult as n, type HumanGatewayVerifyOptions as o, type VerifyCallbackInput as p };
|
package/package.json
CHANGED
|
@@ -1,16 +1,46 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@human-gateway/sdk",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@human-gateway/sdk",
|
|
3
|
+
"version": "0.1.0-alpha.0",
|
|
4
|
+
"description": "Human verification SDK for Human Gateway.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"require": "./dist/index.cjs"
|
|
14
|
+
},
|
|
15
|
+
"./server": {
|
|
16
|
+
"types": "./dist/server.d.ts",
|
|
17
|
+
"import": "./dist/server.js",
|
|
18
|
+
"require": "./dist/server.cjs"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"prepack": "npm run build",
|
|
29
|
+
"prepublishOnly": "npm run typecheck && npm run build"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"human-gateway",
|
|
33
|
+
"world-id",
|
|
34
|
+
"verification",
|
|
35
|
+
"identity",
|
|
36
|
+
"sdk"
|
|
37
|
+
],
|
|
38
|
+
"author": "Human Gateway",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"sideEffects": false,
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/node": "^25.9.1",
|
|
43
|
+
"tsup": "^8.5.1",
|
|
44
|
+
"typescript": "^5.9.3"
|
|
45
|
+
}
|
|
46
|
+
}
|