@aep-foundation/core 0.1.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/dist/index.js ADDED
@@ -0,0 +1,829 @@
1
+ // src/constants.ts
2
+ var AEP_VERSION = "1.0";
3
+ var AEP_MEDIA_TYPE = "application/aep+json";
4
+ var AEP_PROBLEM_MEDIA_TYPE = "application/problem+json";
5
+ var AEP_AUTH_SCHEME = "AEP";
6
+ var AEP_WELL_KNOWN_PATH = "/.well-known/aep";
7
+ var DEFAULT_HTTP_ENDPOINT_BASE = "/aep/";
8
+ var AEP_COMMANDS = ["inspect", "enroll", "grant", "revoke", "status"];
9
+ var AEP_AUTHENTICATED_COMMANDS = ["enroll", "grant", "revoke", "status"];
10
+ var AEP_BINDINGS = ["http"];
11
+ var AEP_SIGNING_ALGORITHMS = ["EdDSA", "ES256"];
12
+ var AEP_IDENTITY_METHOD_DID_WEB = "did:web";
13
+ var AEP_GRANT_TYPE_OAUTH_BEARER = "oauth-bearer";
14
+ var AEP_GRANT_TYPE_API_KEY = "api-key";
15
+ var AEP_GRANT_TYPE_BASIC = "basic";
16
+ var AEP_BUILT_IN_GRANT_TYPES = [
17
+ AEP_GRANT_TYPE_OAUTH_BEARER,
18
+ AEP_GRANT_TYPE_API_KEY,
19
+ AEP_GRANT_TYPE_BASIC
20
+ ];
21
+
22
+ // src/did-web.ts
23
+ function didWebDocumentUrl(did) {
24
+ const prefix = "did:web:";
25
+ if (!did.startsWith(prefix)) {
26
+ throw new Error(`Unsupported DID method: ${did}`);
27
+ }
28
+ const [encodedHost, ...pathParts] = did.slice(prefix.length).split(":");
29
+ if (encodedHost === void 0 || encodedHost.length === 0) {
30
+ throw new Error(`Invalid did:web identifier: ${did}`);
31
+ }
32
+ const hostName = decodeURIComponent(encodedHost);
33
+ const protocol = hostName.startsWith("localhost") || hostName.startsWith("127.0.0.1") ? "http" : "https";
34
+ const documentPath = pathParts.length === 0 ? "/.well-known/did.json" : `/${pathParts.map(decodeURIComponent).join("/")}/did.json`;
35
+ return new URL(`${protocol}://${hostName}${documentPath}`);
36
+ }
37
+ async function resolveDidWebPublicKey(options) {
38
+ const fetchImpl = options.fetch ?? globalThis.fetch;
39
+ if (typeof fetchImpl !== "function") {
40
+ throw new TypeError("AEP did:web resolution requires a fetch implementation.");
41
+ }
42
+ const document = await fetchJson(didWebDocumentUrl(options.did), fetchImpl);
43
+ const methods = arrayField(document, "verificationMethod").filter(isRecord);
44
+ const method = options.kid === void 0 ? methods.find((candidate) => isRecord(candidate["publicKeyJwk"])) : methods.find(
45
+ (candidate) => candidate["id"] === options.kid && isRecord(candidate["publicKeyJwk"])
46
+ );
47
+ if (method === void 0 || !isRecord(method["publicKeyJwk"])) {
48
+ throw new Error(`No public JWK found for ${options.kid ?? options.did}.`);
49
+ }
50
+ return method["publicKeyJwk"];
51
+ }
52
+ async function fetchJson(url, fetchImpl) {
53
+ const response = await fetchImpl(url);
54
+ if (!response.ok) {
55
+ throw new Error(`Failed to fetch ${url.toString()}: ${response.status}`);
56
+ }
57
+ return response.json();
58
+ }
59
+ function arrayField(value, field) {
60
+ if (!isRecord(value)) {
61
+ return [];
62
+ }
63
+ const fieldValue = value[field];
64
+ return Array.isArray(fieldValue) ? fieldValue : [];
65
+ }
66
+ function isRecord(value) {
67
+ return typeof value === "object" && value !== null && !Array.isArray(value);
68
+ }
69
+
70
+ // src/errors.ts
71
+ var AepValidationError = class extends Error {
72
+ issues;
73
+ constructor(message, issues) {
74
+ super(message);
75
+ this.name = "AepValidationError";
76
+ this.issues = issues;
77
+ }
78
+ };
79
+ function createProblemDetails(input) {
80
+ const problem = {
81
+ type: input.type ?? `urn:aep:error:${input.code}`,
82
+ title: input.title,
83
+ status: input.status,
84
+ code: input.code
85
+ };
86
+ if (input.detail !== void 0) {
87
+ problem.detail = input.detail;
88
+ }
89
+ if (input.instance !== void 0) {
90
+ problem.instance = input.instance;
91
+ }
92
+ return problem;
93
+ }
94
+
95
+ // src/http.ts
96
+ var COMMAND_PATHS = {
97
+ enroll: "enroll",
98
+ grant: "grant",
99
+ revoke: "revoke",
100
+ status: "status"
101
+ };
102
+ function normalizeEndpointBase(endpointBase = DEFAULT_HTTP_ENDPOINT_BASE) {
103
+ if (!endpointBase.startsWith("/")) {
104
+ throw new TypeError("AEP endpoint_base must start with '/'.");
105
+ }
106
+ return endpointBase.endsWith("/") ? endpointBase : `${endpointBase}/`;
107
+ }
108
+ function commandPath(command, endpointBase = DEFAULT_HTTP_ENDPOINT_BASE) {
109
+ return `${normalizeEndpointBase(endpointBase)}${COMMAND_PATHS[command]}`;
110
+ }
111
+ function commandPathFromInspect(document, command) {
112
+ return commandPath(command, document.http.endpoint_base);
113
+ }
114
+
115
+ // src/inspect.ts
116
+ var VERSION_PATTERN = /^[0-9]+\.[0-9]+$/;
117
+ var ENDPOINT_BASE_PATTERN = /^\//;
118
+ var DID_PATTERN = /^did:/;
119
+ var IDENTITY_METHOD_PATTERN = /^[a-z0-9]+(?::[a-z0-9]+)*(?:-[a-z0-9]+)*$/;
120
+ var COMMANDS = new Set(AEP_COMMANDS);
121
+ var BINDINGS = new Set(AEP_BINDINGS);
122
+ function validateInspectDocument(value) {
123
+ const issues = [];
124
+ if (!isRecord2(value)) {
125
+ return {
126
+ ok: false,
127
+ issues: [{ path: "$", message: "Expected an object." }]
128
+ };
129
+ }
130
+ requireString(value, "aep_version", issues, VERSION_PATTERN);
131
+ validateBindings(value["bindings"], issues);
132
+ validateClaims(value["claims"], issues);
133
+ validateCommands(value["commands"], issues);
134
+ validateCore(value["core"], issues);
135
+ validateExtensions(value["extensions"], issues);
136
+ validateHttp(value["http"], issues);
137
+ validateIdentity(value["identity"], issues);
138
+ validateService(value["service"], issues);
139
+ if (issues.length > 0) {
140
+ return { ok: false, issues };
141
+ }
142
+ return { ok: true, value, issues: [] };
143
+ }
144
+ function isInspectDocument(value) {
145
+ return validateInspectDocument(value).ok;
146
+ }
147
+ function parseInspectDocument(value) {
148
+ const result2 = validateInspectDocument(value);
149
+ if (result2.ok) {
150
+ return result2.value;
151
+ }
152
+ throw new AepValidationError("Invalid AEP Inspect document.", result2.issues);
153
+ }
154
+ function validateBindings(value, issues) {
155
+ if (!requireRecord(value, "bindings", issues)) {
156
+ return;
157
+ }
158
+ requireStringArray(value["supported"], "$.bindings.supported", issues, {
159
+ minItems: 1,
160
+ allowedValues: BINDINGS
161
+ });
162
+ }
163
+ function validateClaims(value, issues) {
164
+ if (value === void 0) {
165
+ return;
166
+ }
167
+ if (!requireRecord(value, "claims", issues)) {
168
+ return;
169
+ }
170
+ optionalStringArray(value["required"], "$.claims.required", issues);
171
+ optionalStringArray(value["preferred"], "$.claims.preferred", issues);
172
+ optionalStringArray(value["optional"], "$.claims.optional", issues);
173
+ }
174
+ function validateCommands(value, issues) {
175
+ if (!requireRecord(value, "commands", issues)) {
176
+ return;
177
+ }
178
+ requireStringArray(value["supported"], "$.commands.supported", issues, {
179
+ minItems: 1,
180
+ allowedValues: COMMANDS
181
+ });
182
+ optionalStringArray(value["grant_types"], "$.commands.grant_types", issues);
183
+ }
184
+ function validateCore(value, issues) {
185
+ if (!requireRecord(value, "core", issues)) {
186
+ return;
187
+ }
188
+ if (value["signing_algorithms"] !== void 0) {
189
+ requireStringArray(value["signing_algorithms"], "$.core.signing_algorithms", issues, {
190
+ minItems: 1
191
+ });
192
+ }
193
+ }
194
+ function validateExtensions(value, issues) {
195
+ if (value === void 0) {
196
+ return;
197
+ }
198
+ if (!requireRecord(value, "extensions", issues)) {
199
+ return;
200
+ }
201
+ optionalStringArray(value["supported"], "$.extensions.supported", issues);
202
+ }
203
+ function validateHttp(value, issues) {
204
+ if (!requireRecord(value, "http", issues)) {
205
+ return;
206
+ }
207
+ requireString(value, "endpoint_base", issues, ENDPOINT_BASE_PATTERN, "$.http.endpoint_base");
208
+ }
209
+ function validateIdentity(value, issues) {
210
+ if (!requireRecord(value, "identity", issues)) {
211
+ return;
212
+ }
213
+ requireStringArray(value["methods"], "$.identity.methods", issues, {
214
+ minItems: 1,
215
+ itemPattern: IDENTITY_METHOD_PATTERN
216
+ });
217
+ }
218
+ function validateService(value, issues) {
219
+ if (!requireRecord(value, "service", issues)) {
220
+ return;
221
+ }
222
+ requireString(value, "did", issues, DID_PATTERN, "$.service.did");
223
+ }
224
+ function requireRecord(value, field, issues) {
225
+ if (!isRecord2(value)) {
226
+ issues.push({
227
+ path: `$.${field}`,
228
+ message: "Expected an object."
229
+ });
230
+ return false;
231
+ }
232
+ return true;
233
+ }
234
+ function requireString(record, field, issues, pattern, path = `$.${field}`) {
235
+ const value = record[field];
236
+ if (typeof value !== "string") {
237
+ issues.push({ path, message: "Expected a string." });
238
+ return;
239
+ }
240
+ if (pattern && !pattern.test(value)) {
241
+ issues.push({ path, message: `Expected string to match ${pattern.source}.` });
242
+ }
243
+ }
244
+ function optionalStringArray(value, path, issues, options = {}) {
245
+ if (value === void 0) {
246
+ return;
247
+ }
248
+ requireStringArray(value, path, issues, options);
249
+ }
250
+ function requireStringArray(value, path, issues, options = {}) {
251
+ if (!Array.isArray(value)) {
252
+ issues.push({ path, message: "Expected an array." });
253
+ return;
254
+ }
255
+ if (options.minItems !== void 0 && value.length < options.minItems) {
256
+ issues.push({ path, message: `Expected at least ${options.minItems} item(s).` });
257
+ }
258
+ value.forEach((item, index) => {
259
+ const itemPath = `${path}[${index}]`;
260
+ if (typeof item !== "string") {
261
+ issues.push({ path: itemPath, message: "Expected a string." });
262
+ return;
263
+ }
264
+ if (options.allowedValues && !options.allowedValues.has(item)) {
265
+ issues.push({ path: itemPath, message: "Expected a registered AEP value." });
266
+ }
267
+ if (options.itemPattern && !options.itemPattern.test(item)) {
268
+ issues.push({
269
+ path: itemPath,
270
+ message: `Expected string to match ${options.itemPattern.source}.`
271
+ });
272
+ }
273
+ });
274
+ }
275
+ function isRecord2(value) {
276
+ return typeof value === "object" && value !== null && !Array.isArray(value);
277
+ }
278
+
279
+ // src/jwt.ts
280
+ import { SignJWT, importJWK, importPKCS8, importSPKI, importX509, jwtVerify } from "jose";
281
+
282
+ // src/protocol.ts
283
+ var AUTHENTICATED_COMMANDS = new Set(AEP_AUTHENTICATED_COMMANDS);
284
+ var ENROLLMENT_STATUSES = /* @__PURE__ */ new Set(["active", "pending", "rejected"]);
285
+ var AGENT_STATUSES = /* @__PURE__ */ new Set([
286
+ "active",
287
+ "pending",
288
+ "rejected",
289
+ "suspended",
290
+ "terminated",
291
+ "unavailable"
292
+ ]);
293
+ var OWNER_ACTION_REQUIRED_VALUES = /* @__PURE__ */ new Set(["true", "false"]);
294
+ var PROBLEM_TYPE_PATTERN = /^urn:aep:error:/;
295
+ function validateEnrollRequest(value) {
296
+ if (!isRecord3(value)) {
297
+ return invalidRoot();
298
+ }
299
+ const issues = [];
300
+ requireString2(value, "agent_did", issues, { minLength: 1 });
301
+ optionalRecord(value["claims"], "$.claims", issues);
302
+ requireString2(value, "idempotency_key", issues, { minLength: 1 });
303
+ return result(value, issues);
304
+ }
305
+ function parseEnrollRequest(value) {
306
+ return parseWith(validateEnrollRequest(value), "Invalid AEP Enroll request.");
307
+ }
308
+ function validateEnrollResponse(value) {
309
+ if (!isRecord3(value)) {
310
+ return invalidRoot();
311
+ }
312
+ const issues = [];
313
+ requireString2(value, "status", issues, {
314
+ allowedValues: ENROLLMENT_STATUSES
315
+ });
316
+ optionalString(value["owner_action_required"], "$.owner_action_required", issues, {
317
+ allowedValues: OWNER_ACTION_REQUIRED_VALUES
318
+ });
319
+ optionalStringArray2(value["requirements_pending"], "$.requirements_pending", issues);
320
+ return result(value, issues);
321
+ }
322
+ function parseEnrollResponse(value) {
323
+ return parseWith(validateEnrollResponse(value), "Invalid AEP Enroll response.");
324
+ }
325
+ function validateStatusResponse(value) {
326
+ if (!isRecord3(value)) {
327
+ return invalidRoot();
328
+ }
329
+ const issues = [];
330
+ requireString2(value, "status", issues, { allowedValues: AGENT_STATUSES });
331
+ optionalString(value["owner_action_required"], "$.owner_action_required", issues, {
332
+ allowedValues: OWNER_ACTION_REQUIRED_VALUES
333
+ });
334
+ optionalStringArray2(value["requirements_pending"], "$.requirements_pending", issues);
335
+ optionalString(value["since"], "$.since", issues);
336
+ return result(value, issues);
337
+ }
338
+ function parseStatusResponse(value) {
339
+ return parseWith(validateStatusResponse(value), "Invalid AEP Status response.");
340
+ }
341
+ function validateGrantRequest(value) {
342
+ if (!isRecord3(value)) {
343
+ return invalidRoot();
344
+ }
345
+ const issues = [];
346
+ requireString2(value, "grant_type", issues, { minLength: 1 });
347
+ optionalStringArray2(value["requested_scopes"], "$.requested_scopes", issues);
348
+ return result(value, issues);
349
+ }
350
+ function parseGrantRequest(value) {
351
+ return parseWith(validateGrantRequest(value), "Invalid AEP Grant request.");
352
+ }
353
+ function validateRevokeRequest(value) {
354
+ if (!isRecord3(value)) {
355
+ return invalidRoot();
356
+ }
357
+ const issues = [];
358
+ optionalString(value["grant_type"], "$.grant_type", issues, { minLength: 1 });
359
+ optionalString(value["credential_id"], "$.credential_id", issues, { minLength: 1 });
360
+ optionalString(value["all_grant_types"], "$.all_grant_types", issues, {
361
+ allowedValues: /* @__PURE__ */ new Set(["true"])
362
+ });
363
+ const selectors = [value["grant_type"], value["credential_id"], value["all_grant_types"]].filter(
364
+ (selector) => selector !== void 0
365
+ );
366
+ if (selectors.length === 0) {
367
+ issues.push({
368
+ path: "$",
369
+ message: "Expected one of grant_type, credential_id, or all_grant_types."
370
+ });
371
+ }
372
+ if (selectors.length > 1) {
373
+ issues.push({
374
+ path: "$",
375
+ message: "Expected exactly one of grant_type, credential_id, or all_grant_types."
376
+ });
377
+ }
378
+ return result(value, issues);
379
+ }
380
+ function parseRevokeRequest(value) {
381
+ return parseWith(validateRevokeRequest(value), "Invalid AEP Revoke request.");
382
+ }
383
+ function validateRevokeResponse(value) {
384
+ if (!isRecord3(value)) {
385
+ return invalidRoot();
386
+ }
387
+ const issues = [];
388
+ if (Object.keys(value).length > 0) {
389
+ issues.push({ path: "$", message: "Expected an empty object." });
390
+ }
391
+ return result(value, issues);
392
+ }
393
+ function parseRevokeResponse(value) {
394
+ return parseWith(validateRevokeResponse(value), "Invalid AEP Revoke response.");
395
+ }
396
+ function validateClientAssertionClaims(value) {
397
+ if (!isRecord3(value)) {
398
+ return invalidRoot();
399
+ }
400
+ const issues = [];
401
+ requireString2(value, "iss", issues, { minLength: 1 });
402
+ requireString2(value, "sub", issues, { minLength: 1 });
403
+ requireString2(value, "aud", issues, { minLength: 1 });
404
+ requireString2(value, "op", issues, { allowedValues: AUTHENTICATED_COMMANDS });
405
+ requireInteger(value["iat"], "$.iat", issues);
406
+ requireInteger(value["exp"], "$.exp", issues);
407
+ requireString2(value, "jti", issues, { minLength: 1 });
408
+ return result(value, issues);
409
+ }
410
+ function parseClientAssertionClaims(value) {
411
+ return parseWith(validateClientAssertionClaims(value), "Invalid AEP client assertion claims.");
412
+ }
413
+ function validateProblemDetails(value) {
414
+ if (!isRecord3(value)) {
415
+ return invalidRoot();
416
+ }
417
+ const issues = [];
418
+ requireString2(value, "type", issues, { pattern: PROBLEM_TYPE_PATTERN });
419
+ requireString2(value, "title", issues, { minLength: 1 });
420
+ requireInteger(value["status"], "$.status", issues);
421
+ requireString2(value, "code", issues, { minLength: 1 });
422
+ optionalString(value["detail"], "$.detail", issues);
423
+ optionalString(value["instance"], "$.instance", issues);
424
+ return result(value, issues);
425
+ }
426
+ function parseProblemDetails(value) {
427
+ return parseWith(validateProblemDetails(value), "Invalid AEP Problem Details.");
428
+ }
429
+ function validateOAuthBearerGrantResponse(value) {
430
+ if (!isRecord3(value)) {
431
+ return invalidRoot();
432
+ }
433
+ const issues = [];
434
+ requireString2(value, "access_token", issues, { minLength: 1 });
435
+ requireString2(value, "credential_id", issues, { minLength: 1 });
436
+ requireString2(value, "expires_at", issues, { minLength: 1 });
437
+ requireStringArray2(value["scopes"], "$.scopes", issues);
438
+ requireString2(value, "token_type", issues, { allowedValues: /* @__PURE__ */ new Set(["Bearer"]) });
439
+ return result(value, issues);
440
+ }
441
+ function validateApiKeyGrantResponse(value) {
442
+ if (!isRecord3(value)) {
443
+ return invalidRoot();
444
+ }
445
+ const issues = [];
446
+ requireString2(value, "api_key", issues, { minLength: 1 });
447
+ requireString2(value, "credential_id", issues, { minLength: 1 });
448
+ requireString2(value, "expires_at", issues, { minLength: 1 });
449
+ requireString2(value, "header", issues, { minLength: 1 });
450
+ requireStringArray2(value["scopes"], "$.scopes", issues);
451
+ return result(value, issues);
452
+ }
453
+ function validateBasicGrantResponse(value) {
454
+ if (!isRecord3(value)) {
455
+ return invalidRoot();
456
+ }
457
+ const issues = [];
458
+ requireString2(value, "credential_id", issues, { minLength: 1 });
459
+ requireString2(value, "expires_at", issues, { minLength: 1 });
460
+ requireString2(value, "password", issues, { minLength: 1 });
461
+ optionalString(value["realm"], "$.realm", issues, { minLength: 1 });
462
+ requireStringArray2(value["scopes"], "$.scopes", issues);
463
+ requireString2(value, "username", issues, { minLength: 1 });
464
+ return result(value, issues);
465
+ }
466
+ function validateBuiltInGrantResponse(grantType, value) {
467
+ if (grantType === AEP_GRANT_TYPE_OAUTH_BEARER) {
468
+ return validateOAuthBearerGrantResponse(value);
469
+ }
470
+ if (grantType === AEP_GRANT_TYPE_API_KEY) {
471
+ return validateApiKeyGrantResponse(value);
472
+ }
473
+ if (grantType === AEP_GRANT_TYPE_BASIC) {
474
+ return validateBasicGrantResponse(value);
475
+ }
476
+ return {
477
+ ok: false,
478
+ issues: [{ path: "$.grant_type", message: "Expected a built-in AEP grant type." }]
479
+ };
480
+ }
481
+ function parseBuiltInGrantResponse(grantType, value) {
482
+ return parseWith(validateBuiltInGrantResponse(grantType, value), "Invalid AEP Grant response.");
483
+ }
484
+ function parseWith(validation, message) {
485
+ if (validation.ok) {
486
+ return validation.value;
487
+ }
488
+ throw new AepValidationError(message, validation.issues);
489
+ }
490
+ function invalidRoot() {
491
+ return {
492
+ ok: false,
493
+ issues: [{ path: "$", message: "Expected an object." }]
494
+ };
495
+ }
496
+ function result(value, issues) {
497
+ if (issues.length > 0) {
498
+ return { ok: false, issues };
499
+ }
500
+ return { ok: true, issues: [], value };
501
+ }
502
+ function requireString2(record, field, issues, options = {}) {
503
+ validateString(record[field], `$.${field}`, issues, options);
504
+ }
505
+ function optionalString(value, path, issues, options = {}) {
506
+ if (value === void 0) {
507
+ return;
508
+ }
509
+ validateString(value, path, issues, options);
510
+ }
511
+ function validateString(value, path, issues, options) {
512
+ if (typeof value !== "string") {
513
+ issues.push({ path, message: "Expected a string." });
514
+ return;
515
+ }
516
+ if (options.minLength !== void 0 && value.length < options.minLength) {
517
+ issues.push({ path, message: `Expected at least ${options.minLength} character(s).` });
518
+ }
519
+ if (options.allowedValues !== void 0 && !options.allowedValues.has(value)) {
520
+ issues.push({ path, message: "Expected a registered AEP value." });
521
+ }
522
+ if (options.pattern !== void 0 && !options.pattern.test(value)) {
523
+ issues.push({ path, message: `Expected string to match ${options.pattern.source}.` });
524
+ }
525
+ }
526
+ function optionalRecord(value, path, issues) {
527
+ if (value === void 0) {
528
+ return;
529
+ }
530
+ if (!isRecord3(value)) {
531
+ issues.push({ path, message: "Expected an object." });
532
+ }
533
+ }
534
+ function requireInteger(value, path, issues) {
535
+ if (!Number.isInteger(value)) {
536
+ issues.push({ path, message: "Expected an integer." });
537
+ }
538
+ }
539
+ function optionalStringArray2(value, path, issues) {
540
+ if (value === void 0) {
541
+ return;
542
+ }
543
+ requireStringArray2(value, path, issues);
544
+ }
545
+ function requireStringArray2(value, path, issues) {
546
+ if (!Array.isArray(value)) {
547
+ issues.push({ path, message: "Expected an array." });
548
+ return;
549
+ }
550
+ value.forEach((item, index) => {
551
+ if (typeof item !== "string") {
552
+ issues.push({ path: `${path}[${index}]`, message: "Expected a string." });
553
+ }
554
+ });
555
+ }
556
+ function isRecord3(value) {
557
+ return typeof value === "object" && value !== null && !Array.isArray(value);
558
+ }
559
+
560
+ // src/jwt.ts
561
+ async function signClientAssertionJwt(claims, options) {
562
+ const parsed = parseClientAssertionClaims(claims);
563
+ const key = await importJoseKey(options.key, options.alg);
564
+ return new SignJWT(parsed).setProtectedHeader({
565
+ alg: options.alg,
566
+ ...options.kid === void 0 ? {} : { kid: options.kid },
567
+ typ: options.typ ?? "JWT"
568
+ }).sign(key);
569
+ }
570
+ async function verifyClientAssertionJwt(clientAssertion, options) {
571
+ const verifyOptions = {
572
+ ...options.algorithms === void 0 ? {} : { algorithms: options.algorithms },
573
+ ...options.audience === void 0 ? {} : { audience: options.audience },
574
+ ...options.clockTolerance === void 0 ? {} : { clockTolerance: options.clockTolerance },
575
+ ...options.currentDate === void 0 ? {} : { currentDate: options.currentDate },
576
+ ...options.issuer === void 0 ? {} : { issuer: options.issuer },
577
+ ...options.subject === void 0 ? {} : { subject: options.subject }
578
+ };
579
+ let result2;
580
+ if (typeof options.key === "function") {
581
+ const resolveKey = options.key;
582
+ result2 = await jwtVerify(
583
+ clientAssertion,
584
+ async (protectedHeader, token) => importJoseKey(await resolveKey(protectedHeader, token), protectedHeader.alg),
585
+ verifyOptions
586
+ );
587
+ } else {
588
+ result2 = await jwtVerify(
589
+ clientAssertion,
590
+ await importJoseKey(options.key, options.algorithms?.[0]),
591
+ verifyOptions
592
+ );
593
+ }
594
+ return parseClientAssertionClaims(result2.payload);
595
+ }
596
+ async function importJoseKey(key, alg) {
597
+ if (!isPemKey(key)) {
598
+ return key;
599
+ }
600
+ if (alg === void 0) {
601
+ throw new TypeError("AEP JOSE PEM key import requires an algorithm.");
602
+ }
603
+ if (key.format === "pkcs8") {
604
+ return importPKCS8(key.pem, alg);
605
+ }
606
+ if (key.format === "spki") {
607
+ return importSPKI(key.pem, alg);
608
+ }
609
+ return importX509(key.pem, alg);
610
+ }
611
+ async function importJwkJoseKey(jwk, alg) {
612
+ return importJWK(jwk, alg);
613
+ }
614
+ function decodeJwtUnverified(token) {
615
+ const [encodedHeader, encodedPayload] = token.split(".");
616
+ if (encodedHeader === void 0 || encodedPayload === void 0) {
617
+ throw new Error("Invalid JWT.");
618
+ }
619
+ return {
620
+ header: parseBase64UrlJson(encodedHeader),
621
+ payload: parseBase64UrlJson(encodedPayload)
622
+ };
623
+ }
624
+ function isPemKey(key) {
625
+ return typeof key === "object" && "pem" in key && typeof key.pem === "string" && "format" in key;
626
+ }
627
+ function parseBase64UrlJson(encoded) {
628
+ const parsed = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
629
+ if (!isRecord4(parsed)) {
630
+ throw new Error("Expected JWT part to decode to an object.");
631
+ }
632
+ return parsed;
633
+ }
634
+ function isRecord4(value) {
635
+ return typeof value === "object" && value !== null && !Array.isArray(value);
636
+ }
637
+
638
+ // src/schemas.ts
639
+ var inspectDocumentSchema = {
640
+ $schema: "https://json-schema.org/draft/2020-12/schema",
641
+ $id: "https://www.aep.foundation/schemas/inspect-document.schema.json",
642
+ title: "AEP Inspect Document",
643
+ type: "object",
644
+ required: ["aep_version", "bindings", "commands", "core", "http", "identity", "service"],
645
+ additionalProperties: true,
646
+ properties: {
647
+ aep_version: {
648
+ type: "string",
649
+ pattern: "^[0-9]+\\.[0-9]+$"
650
+ },
651
+ bindings: {
652
+ type: "object",
653
+ required: ["supported"],
654
+ additionalProperties: true,
655
+ properties: {
656
+ supported: {
657
+ type: "array",
658
+ minItems: 1,
659
+ items: {
660
+ type: "string",
661
+ enum: ["http"]
662
+ }
663
+ }
664
+ }
665
+ },
666
+ claims: {
667
+ type: "object",
668
+ additionalProperties: true,
669
+ properties: {
670
+ required: {
671
+ type: "array",
672
+ items: {
673
+ type: "string"
674
+ }
675
+ },
676
+ preferred: {
677
+ type: "array",
678
+ items: {
679
+ type: "string"
680
+ }
681
+ },
682
+ optional: {
683
+ type: "array",
684
+ items: {
685
+ type: "string"
686
+ }
687
+ }
688
+ }
689
+ },
690
+ commands: {
691
+ type: "object",
692
+ required: ["supported"],
693
+ additionalProperties: true,
694
+ properties: {
695
+ supported: {
696
+ type: "array",
697
+ minItems: 1,
698
+ items: {
699
+ type: "string",
700
+ enum: ["inspect", "enroll", "grant", "revoke", "status"]
701
+ }
702
+ },
703
+ grant_types: {
704
+ type: "array",
705
+ items: {
706
+ type: "string"
707
+ }
708
+ }
709
+ }
710
+ },
711
+ core: {
712
+ type: "object",
713
+ additionalProperties: true,
714
+ properties: {
715
+ signing_algorithms: {
716
+ type: "array",
717
+ minItems: 1,
718
+ items: {
719
+ type: "string"
720
+ }
721
+ }
722
+ }
723
+ },
724
+ extensions: {
725
+ type: "object",
726
+ additionalProperties: true,
727
+ properties: {
728
+ supported: {
729
+ type: "array",
730
+ items: {
731
+ type: "string"
732
+ }
733
+ }
734
+ }
735
+ },
736
+ http: {
737
+ type: "object",
738
+ required: ["endpoint_base"],
739
+ additionalProperties: true,
740
+ properties: {
741
+ endpoint_base: {
742
+ type: "string",
743
+ pattern: "^/"
744
+ }
745
+ }
746
+ },
747
+ identity: {
748
+ type: "object",
749
+ required: ["methods"],
750
+ additionalProperties: true,
751
+ properties: {
752
+ methods: {
753
+ type: "array",
754
+ minItems: 1,
755
+ items: {
756
+ type: "string",
757
+ pattern: "^[a-z0-9]+(?::[a-z0-9]+)*(?:-[a-z0-9]+)*$"
758
+ }
759
+ }
760
+ }
761
+ },
762
+ service: {
763
+ type: "object",
764
+ required: ["did"],
765
+ additionalProperties: true,
766
+ properties: {
767
+ did: {
768
+ type: "string",
769
+ pattern: "^did:"
770
+ }
771
+ }
772
+ }
773
+ }
774
+ };
775
+ export {
776
+ AEP_AUTHENTICATED_COMMANDS,
777
+ AEP_AUTH_SCHEME,
778
+ AEP_BINDINGS,
779
+ AEP_BUILT_IN_GRANT_TYPES,
780
+ AEP_COMMANDS,
781
+ AEP_GRANT_TYPE_API_KEY,
782
+ AEP_GRANT_TYPE_BASIC,
783
+ AEP_GRANT_TYPE_OAUTH_BEARER,
784
+ AEP_IDENTITY_METHOD_DID_WEB,
785
+ AEP_MEDIA_TYPE,
786
+ AEP_PROBLEM_MEDIA_TYPE,
787
+ AEP_SIGNING_ALGORITHMS,
788
+ AEP_VERSION,
789
+ AEP_WELL_KNOWN_PATH,
790
+ AepValidationError,
791
+ DEFAULT_HTTP_ENDPOINT_BASE,
792
+ commandPath,
793
+ commandPathFromInspect,
794
+ createProblemDetails,
795
+ decodeJwtUnverified,
796
+ didWebDocumentUrl,
797
+ importJoseKey,
798
+ importJwkJoseKey,
799
+ inspectDocumentSchema,
800
+ isInspectDocument,
801
+ normalizeEndpointBase,
802
+ parseBuiltInGrantResponse,
803
+ parseClientAssertionClaims,
804
+ parseEnrollRequest,
805
+ parseEnrollResponse,
806
+ parseGrantRequest,
807
+ parseInspectDocument,
808
+ parseProblemDetails,
809
+ parseRevokeRequest,
810
+ parseRevokeResponse,
811
+ parseStatusResponse,
812
+ resolveDidWebPublicKey,
813
+ signClientAssertionJwt,
814
+ validateApiKeyGrantResponse,
815
+ validateBasicGrantResponse,
816
+ validateBuiltInGrantResponse,
817
+ validateClientAssertionClaims,
818
+ validateEnrollRequest,
819
+ validateEnrollResponse,
820
+ validateGrantRequest,
821
+ validateInspectDocument,
822
+ validateOAuthBearerGrantResponse,
823
+ validateProblemDetails,
824
+ validateRevokeRequest,
825
+ validateRevokeResponse,
826
+ validateStatusResponse,
827
+ verifyClientAssertionJwt
828
+ };
829
+ //# sourceMappingURL=index.js.map