@adcp/sdk 16.0.0-beta.1 → 16.0.0-beta.3
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 +54 -0
- package/dist/lib/core/ConversationTypes.d.mts +8 -3
- package/dist/lib/core/ConversationTypes.d.ts +8 -3
- package/dist/lib/core/SingleAgentClient.d.mts +15 -4
- package/dist/lib/core/SingleAgentClient.d.ts +15 -4
- package/dist/lib/core/SingleAgentClient.js +29 -8
- package/dist/lib/core/SingleAgentClient.mjs +29 -8
- package/dist/lib/core/TaskExecutor.js +5 -1
- package/dist/lib/core/TaskExecutor.mjs +5 -1
- package/dist/lib/errors/index.d.mts +9 -4
- package/dist/lib/errors/index.d.ts +9 -4
- package/dist/lib/identity-3.3/generated-compat.d.mts +34 -0
- package/dist/lib/identity-3.3/generated-compat.d.ts +34 -0
- package/dist/lib/identity-3.3/generated-compat.js +16 -0
- package/dist/lib/identity-3.3/generated-compat.mjs +0 -0
- package/dist/lib/identity-3.3/index.d.mts +2 -2
- package/dist/lib/identity-3.3/index.d.ts +2 -2
- package/dist/lib/identity-3.3/index.js +4 -0
- package/dist/lib/identity-3.3/index.mjs +5 -1
- package/dist/lib/identity-3.3/lifecycle.d.mts +17 -5
- package/dist/lib/identity-3.3/lifecycle.d.ts +17 -5
- package/dist/lib/identity-3.3/lifecycle.js +32 -5
- package/dist/lib/identity-3.3/lifecycle.mjs +38 -6
- package/dist/lib/identity-3.3/revocation.d.mts +39 -3
- package/dist/lib/identity-3.3/revocation.d.ts +39 -3
- package/dist/lib/identity-3.3/revocation.js +88 -18
- package/dist/lib/identity-3.3/revocation.mjs +89 -19
- package/dist/lib/identity-3.3/server.d.mts +12 -0
- package/dist/lib/identity-3.3/server.d.ts +12 -0
- package/dist/lib/identity-3.3/server.js +103 -43
- package/dist/lib/identity-3.3/server.mjs +111 -45
- package/dist/lib/identity-3.3/trust.d.mts +62 -1
- package/dist/lib/identity-3.3/trust.d.ts +62 -1
- package/dist/lib/identity-3.3/trust.js +126 -21
- package/dist/lib/identity-3.3/trust.mjs +124 -21
- package/dist/lib/identity-3.3/types.d.mts +39 -11
- package/dist/lib/identity-3.3/types.d.ts +39 -11
- package/dist/lib/index.d.mts +3 -3
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.js +8 -0
- package/dist/lib/index.mjs +9 -1
- package/dist/lib/negotiation/types.d.mts +20 -39
- package/dist/lib/negotiation/types.d.ts +20 -39
- package/dist/lib/protocols/index.d.mts +61 -25
- package/dist/lib/protocols/index.d.ts +61 -25
- package/dist/lib/protocols/index.js +11 -6
- package/dist/lib/protocols/index.mjs +5 -2
- package/dist/lib/protocols/mcp-modern.js +1 -0
- package/dist/lib/protocols/mcp-modern.mjs +2 -1
- package/dist/lib/protocols/mcp.js +1 -0
- package/dist/lib/protocols/mcp.mjs +2 -1
- package/dist/lib/protocols/responseSizeLimit.d.mts +91 -5
- package/dist/lib/protocols/responseSizeLimit.d.ts +91 -5
- package/dist/lib/protocols/responseSizeLimit.js +195 -31
- package/dist/lib/protocols/responseSizeLimit.mjs +192 -31
- package/dist/lib/reporting/bigquery/index.js +8 -0
- package/dist/lib/reporting/bigquery/index.mjs +8 -0
- package/dist/lib/schemas-data/v2.5/_provenance.json +1 -1
- package/dist/lib/server/auth-signature.d.mts +6 -1
- package/dist/lib/server/auth-signature.d.ts +6 -1
- package/dist/lib/server/auth-signature.js +24 -13
- package/dist/lib/server/auth-signature.mjs +29 -13
- package/dist/lib/server/auth.d.mts +2 -2
- package/dist/lib/server/auth.d.ts +2 -2
- package/dist/lib/server/create-adcp-server.js +31 -10
- package/dist/lib/server/create-adcp-server.mjs +37 -11
- package/dist/lib/signing/crypto.d.mts +15 -0
- package/dist/lib/signing/crypto.d.ts +15 -0
- package/dist/lib/signing/crypto.js +83 -3
- package/dist/lib/signing/crypto.mjs +86 -3
- package/dist/lib/signing/fetch-async.js +1 -1
- package/dist/lib/signing/fetch-async.mjs +1 -1
- package/dist/lib/signing/fetch.js +1 -1
- package/dist/lib/signing/fetch.mjs +1 -1
- package/dist/lib/signing/middleware.js +9 -0
- package/dist/lib/signing/middleware.mjs +14 -0
- package/dist/lib/signing/parser.d.mts +8 -5
- package/dist/lib/signing/parser.d.ts +8 -5
- package/dist/lib/signing/parser.js +77 -61
- package/dist/lib/signing/parser.mjs +77 -61
- package/dist/lib/signing/revocation.js +3 -0
- package/dist/lib/signing/revocation.mjs +3 -0
- package/dist/lib/signing/server.d.mts +1 -1
- package/dist/lib/signing/server.d.ts +1 -1
- package/dist/lib/signing/server.js +2 -0
- package/dist/lib/signing/server.mjs +2 -1
- package/dist/lib/signing/signer.js +2 -8
- package/dist/lib/signing/signer.mjs +3 -9
- package/dist/lib/signing/testing.js +2 -6
- package/dist/lib/signing/testing.mjs +3 -7
- package/dist/lib/signing/verifier.js +3 -3
- package/dist/lib/signing/verifier.mjs +4 -4
- package/dist/lib/signing/web-bot-auth.d.mts +84 -10
- package/dist/lib/signing/web-bot-auth.d.ts +84 -10
- package/dist/lib/signing/web-bot-auth.js +278 -88
- package/dist/lib/signing/web-bot-auth.mjs +279 -94
- package/dist/lib/signing/webhook-verifier.js +3 -3
- package/dist/lib/signing/webhook-verifier.mjs +4 -4
- package/dist/lib/substitution/compile.js +2 -1
- package/dist/lib/substitution/compile.mjs +2 -1
- package/dist/lib/substitution/consent-macros.d.mts +4 -0
- package/dist/lib/substitution/consent-macros.d.ts +4 -0
- package/dist/lib/substitution/consent-macros.js +45 -0
- package/dist/lib/substitution/consent-macros.mjs +20 -0
- package/dist/lib/substitution/index.d.mts +1 -1
- package/dist/lib/substitution/index.d.ts +1 -1
- package/dist/lib/substitution/index.js +2 -0
- package/dist/lib/substitution/index.mjs +2 -1
- package/dist/lib/substitution/translate.d.mts +15 -2
- package/dist/lib/substitution/translate.d.ts +15 -2
- package/dist/lib/substitution/translate.js +148 -26
- package/dist/lib/substitution/translate.mjs +147 -26
- package/dist/lib/testing/client.js +2 -1
- package/dist/lib/testing/client.mjs +2 -1
- package/dist/lib/testing/scenarios/capabilities.js +1 -1
- package/dist/lib/testing/scenarios/capabilities.mjs +1 -1
- package/dist/lib/testing/storyboard/request-signing/builder.js +2 -5
- package/dist/lib/testing/storyboard/request-signing/builder.mjs +3 -6
- package/dist/lib/testing/storyboard/signer-grader/grader.js +2 -7
- package/dist/lib/testing/storyboard/signer-grader/grader.mjs +2 -7
- package/dist/lib/testing/storyboard/validations.d.mts +1 -1
- package/dist/lib/testing/storyboard/validations.d.ts +1 -1
- package/dist/lib/types/enums.generated.d.mts +3 -0
- package/dist/lib/types/enums.generated.d.ts +3 -0
- package/dist/lib/types/enums.generated.js +9 -0
- package/dist/lib/types/enums.generated.mjs +6 -0
- package/dist/lib/v2/projection/catalog-snapshot.js +3 -1
- package/dist/lib/v2/projection/catalog-snapshot.mjs +3 -1
- package/dist/lib/v2/projection/creative-delivery.d.mts +31 -9
- package/dist/lib/v2/projection/creative-delivery.d.ts +31 -9
- package/dist/lib/v2/projection/index.d.mts +1 -1
- package/dist/lib/v2/projection/index.d.ts +1 -1
- package/dist/lib/v2/projection/index.js +2 -0
- package/dist/lib/v2/projection/index.mjs +2 -0
- package/dist/lib/v2/projection/legacy-routes.d.mts +10 -0
- package/dist/lib/v2/projection/legacy-routes.d.ts +10 -0
- package/dist/lib/v2/projection/legacy-routes.js +7 -0
- package/dist/lib/v2/projection/legacy-routes.mjs +6 -0
- package/dist/lib/validation/schema-loader.js +25 -0
- package/dist/lib/validation/schema-loader.mjs +24 -0
- package/dist/lib/version.d.mts +3 -3
- package/dist/lib/version.d.ts +3 -3
- package/dist/lib/version.js +3 -3
- package/dist/lib/version.mjs +3 -3
- package/docs/TYPE-SUMMARY.md +7 -2
- package/docs/guides/DISCOVERY-CACHE-AND-SESSION-REUSE.md +3 -2
- package/docs/guides/REPORTING-LEDGER.md +15 -5
- package/docs/guides/REPORTING-OPERATIONS.md +17 -11
- package/docs/guides/UNIVERSAL-MACRO-COMPILATION.md +38 -0
- package/docs/guides/VALIDATE-YOUR-AGENT.md +12 -0
- package/docs/llms.txt +2 -2
- package/docs/migration-12-to-13.md +8 -0
- package/docs/migration-14.x-rc-worksheet.md +4 -4
- package/docs/migration-agent-identity-3.3.md +150 -11
- package/package.json +4 -1
|
@@ -42,6 +42,10 @@ function verifySignatureAsAuthenticator(options) {
|
|
|
42
42
|
throw new TypeError(
|
|
43
43
|
"Web Bot Auth requires an origin-binding migration fence; use createIdentity33PrincipalResolver or supply assertLegacyOriginAllowed"
|
|
44
44
|
);
|
|
45
|
+
if (options.webBotAuth && !options.webBotAuth.isRevoked && !(0, import_web_bot_auth2.isWebBotAuthRevocationChecked)(options.webBotAuth.resolvePrincipal))
|
|
46
|
+
throw new TypeError(
|
|
47
|
+
"Web Bot Auth requires origin revocation: use createIdentity33PrincipalResolver({ revocation }) or supply isRevoked"
|
|
48
|
+
);
|
|
45
49
|
const revocationStore = options.revocationStore ?? new import_revocation.InMemoryRevocationStore();
|
|
46
50
|
const authenticator = async (req) => {
|
|
47
51
|
if (!hasSignatureHeader(req)) return null;
|
|
@@ -62,21 +66,22 @@ function verifySignatureAsAuthenticator(options) {
|
|
|
62
66
|
throw new import_web_bot_auth2.WebBotAuthError(403, "raw_body_missing");
|
|
63
67
|
const signers = await (0, import_web_bot_auth2.verifyWebBotAuth)(requestLike, {
|
|
64
68
|
directory: options.webBotAuth.directory,
|
|
65
|
-
deferAuthorizationErrors: typeof options.resolveOperation(req) === "string",
|
|
66
69
|
replayStore,
|
|
67
|
-
isRevoked: options.webBotAuth.isRevoked,
|
|
68
70
|
now: options.now,
|
|
69
|
-
|
|
70
|
-
"get_adcp_capabilities",
|
|
71
|
-
"get_principal",
|
|
72
|
-
"list_creative_formats",
|
|
73
|
-
"list_accounts"
|
|
74
|
-
].includes(String(options.resolveOperation(req)))
|
|
71
|
+
...options.webBotAuth.isRevoked && { isRevoked: options.webBotAuth.isRevoked }
|
|
75
72
|
});
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
const operation = options.resolveOperation(req);
|
|
74
|
+
let principal2;
|
|
75
|
+
let deferredFailure;
|
|
76
|
+
try {
|
|
77
|
+
principal2 = await options.webBotAuth.resolvePrincipal(signers, operation);
|
|
78
|
+
} catch (error) {
|
|
79
|
+
if (error instanceof import_web_bot_auth2.WebBotAuthError || error instanceof import_web_bot_auth2.WebBotAuthUnavailableError) throw error;
|
|
80
|
+
if (typeof operation !== "string") throw (0, import_web_bot_auth2.webBotAuthPrincipalFailureError)(error);
|
|
81
|
+
const deferred = (0, import_web_bot_auth2.deferWebBotAuthPrincipalFailure)(signers, error);
|
|
82
|
+
principal2 = { principal: deferred.principal };
|
|
83
|
+
deferredFailure = deferred.authorizationFailure;
|
|
84
|
+
}
|
|
80
85
|
const signer2 = signers[signers.length - 1];
|
|
81
86
|
req.verifiedSigner = {
|
|
82
87
|
keyid: signer2.keyid,
|
|
@@ -90,7 +95,9 @@ function verifySignatureAsAuthenticator(options) {
|
|
|
90
95
|
...principal2.extra,
|
|
91
96
|
webBotAuthAuthorization: {
|
|
92
97
|
signer: failed ?? signer2,
|
|
93
|
-
...failed && {
|
|
98
|
+
...(failed?.authorizationFailure ?? deferredFailure) && {
|
|
99
|
+
authorizationFailure: failed?.authorizationFailure ?? deferredFailure
|
|
100
|
+
}
|
|
94
101
|
}
|
|
95
102
|
}
|
|
96
103
|
};
|
|
@@ -117,6 +124,10 @@ function verifySignatureAsAuthenticator(options) {
|
|
|
117
124
|
} catch (err) {
|
|
118
125
|
if (err instanceof import_web_bot_auth2.WebBotAuthError)
|
|
119
126
|
throw new import_auth.AuthError(err.message, { cause: err, status: err.status, headers: err.headers, body: err.body });
|
|
127
|
+
if (err instanceof import_web_bot_auth2.WebBotAuthUnavailableError) {
|
|
128
|
+
const outage = (0, import_web_bot_auth2.webBotAuthUnavailableResponse)();
|
|
129
|
+
throw new import_auth.AuthError(err.message, { cause: err, ...outage });
|
|
130
|
+
}
|
|
120
131
|
if (err instanceof import_errors.RequestSignatureError) {
|
|
121
132
|
throw new import_auth.AuthError(`Signature rejected (${err.code}).`, { cause: err });
|
|
122
133
|
}
|
|
@@ -3,6 +3,11 @@ import { RequestSignatureError } from "../signing/errors.mjs";
|
|
|
3
3
|
import {
|
|
4
4
|
selectSignatureProfile,
|
|
5
5
|
verifyWebBotAuth,
|
|
6
|
+
isWebBotAuthRevocationChecked,
|
|
7
|
+
webBotAuthUnavailableResponse,
|
|
8
|
+
WebBotAuthUnavailableError,
|
|
9
|
+
deferWebBotAuthPrincipalFailure,
|
|
10
|
+
webBotAuthPrincipalFailureError,
|
|
6
11
|
WebBotAuthError
|
|
7
12
|
} from "../signing/web-bot-auth.mjs";
|
|
8
13
|
import { InMemoryReplayStore } from "../signing/replay.mjs";
|
|
@@ -34,6 +39,10 @@ function verifySignatureAsAuthenticator(options) {
|
|
|
34
39
|
throw new TypeError(
|
|
35
40
|
"Web Bot Auth requires an origin-binding migration fence; use createIdentity33PrincipalResolver or supply assertLegacyOriginAllowed"
|
|
36
41
|
);
|
|
42
|
+
if (options.webBotAuth && !options.webBotAuth.isRevoked && !isWebBotAuthRevocationChecked(options.webBotAuth.resolvePrincipal))
|
|
43
|
+
throw new TypeError(
|
|
44
|
+
"Web Bot Auth requires origin revocation: use createIdentity33PrincipalResolver({ revocation }) or supply isRevoked"
|
|
45
|
+
);
|
|
37
46
|
const revocationStore = options.revocationStore ?? new InMemoryRevocationStore();
|
|
38
47
|
const authenticator = async (req) => {
|
|
39
48
|
if (!hasSignatureHeader(req)) return null;
|
|
@@ -54,21 +63,22 @@ function verifySignatureAsAuthenticator(options) {
|
|
|
54
63
|
throw new WebBotAuthError(403, "raw_body_missing");
|
|
55
64
|
const signers = await verifyWebBotAuth(requestLike, {
|
|
56
65
|
directory: options.webBotAuth.directory,
|
|
57
|
-
deferAuthorizationErrors: typeof options.resolveOperation(req) === "string",
|
|
58
66
|
replayStore,
|
|
59
|
-
isRevoked: options.webBotAuth.isRevoked,
|
|
60
67
|
now: options.now,
|
|
61
|
-
|
|
62
|
-
"get_adcp_capabilities",
|
|
63
|
-
"get_principal",
|
|
64
|
-
"list_creative_formats",
|
|
65
|
-
"list_accounts"
|
|
66
|
-
].includes(String(options.resolveOperation(req)))
|
|
68
|
+
...options.webBotAuth.isRevoked && { isRevoked: options.webBotAuth.isRevoked }
|
|
67
69
|
});
|
|
68
|
-
const
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
const operation = options.resolveOperation(req);
|
|
71
|
+
let principal2;
|
|
72
|
+
let deferredFailure;
|
|
73
|
+
try {
|
|
74
|
+
principal2 = await options.webBotAuth.resolvePrincipal(signers, operation);
|
|
75
|
+
} catch (error) {
|
|
76
|
+
if (error instanceof WebBotAuthError || error instanceof WebBotAuthUnavailableError) throw error;
|
|
77
|
+
if (typeof operation !== "string") throw webBotAuthPrincipalFailureError(error);
|
|
78
|
+
const deferred = deferWebBotAuthPrincipalFailure(signers, error);
|
|
79
|
+
principal2 = { principal: deferred.principal };
|
|
80
|
+
deferredFailure = deferred.authorizationFailure;
|
|
81
|
+
}
|
|
72
82
|
const signer2 = signers[signers.length - 1];
|
|
73
83
|
req.verifiedSigner = {
|
|
74
84
|
keyid: signer2.keyid,
|
|
@@ -82,7 +92,9 @@ function verifySignatureAsAuthenticator(options) {
|
|
|
82
92
|
...principal2.extra,
|
|
83
93
|
webBotAuthAuthorization: {
|
|
84
94
|
signer: failed ?? signer2,
|
|
85
|
-
...failed && {
|
|
95
|
+
...(failed?.authorizationFailure ?? deferredFailure) && {
|
|
96
|
+
authorizationFailure: failed?.authorizationFailure ?? deferredFailure
|
|
97
|
+
}
|
|
86
98
|
}
|
|
87
99
|
}
|
|
88
100
|
};
|
|
@@ -109,6 +121,10 @@ function verifySignatureAsAuthenticator(options) {
|
|
|
109
121
|
} catch (err) {
|
|
110
122
|
if (err instanceof WebBotAuthError)
|
|
111
123
|
throw new AuthError(err.message, { cause: err, status: err.status, headers: err.headers, body: err.body });
|
|
124
|
+
if (err instanceof WebBotAuthUnavailableError) {
|
|
125
|
+
const outage = webBotAuthUnavailableResponse();
|
|
126
|
+
throw new AuthError(err.message, { cause: err, ...outage });
|
|
127
|
+
}
|
|
112
128
|
if (err instanceof RequestSignatureError) {
|
|
113
129
|
throw new AuthError(`Signature rejected (${err.code}).`, { cause: err });
|
|
114
130
|
}
|
|
@@ -145,12 +145,12 @@ export type Authenticator = (req: IncomingMessage) => AuthResult | Promise<AuthR
|
|
|
145
145
|
*/
|
|
146
146
|
export declare class AuthError extends Error {
|
|
147
147
|
readonly publicMessage: string;
|
|
148
|
-
readonly status?: 400 | 403 | 429;
|
|
148
|
+
readonly status?: 400 | 403 | 429 | 503;
|
|
149
149
|
readonly body?: Record<string, unknown>;
|
|
150
150
|
readonly headers?: Record<string, string>;
|
|
151
151
|
constructor(publicMessage: string, options?: {
|
|
152
152
|
cause?: unknown;
|
|
153
|
-
status?: 400 | 403 | 429;
|
|
153
|
+
status?: 400 | 403 | 429 | 503;
|
|
154
154
|
headers?: Record<string, string>;
|
|
155
155
|
body?: Record<string, unknown>;
|
|
156
156
|
});
|
|
@@ -145,12 +145,12 @@ export type Authenticator = (req: IncomingMessage) => AuthResult | Promise<AuthR
|
|
|
145
145
|
*/
|
|
146
146
|
export declare class AuthError extends Error {
|
|
147
147
|
readonly publicMessage: string;
|
|
148
|
-
readonly status?: 400 | 403 | 429;
|
|
148
|
+
readonly status?: 400 | 403 | 429 | 503;
|
|
149
149
|
readonly body?: Record<string, unknown>;
|
|
150
150
|
readonly headers?: Record<string, string>;
|
|
151
151
|
constructor(publicMessage: string, options?: {
|
|
152
152
|
cause?: unknown;
|
|
153
|
-
status?: 400 | 403 | 429;
|
|
153
|
+
status?: 400 | 403 | 429 | 503;
|
|
154
154
|
headers?: Record<string, string>;
|
|
155
155
|
body?: Record<string, unknown>;
|
|
156
156
|
});
|
|
@@ -1433,6 +1433,10 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
|
|
|
1433
1433
|
throw new Error(
|
|
1434
1434
|
"Web Bot Auth requires an origin-binding migration fence; use createIdentity33PrincipalResolver or supply assertLegacyOriginAllowed"
|
|
1435
1435
|
);
|
|
1436
|
+
if (signedRequests.webBotAuth && !signedRequests.webBotAuth.isRevoked && !(0, import_web_bot_auth2.isWebBotAuthRevocationChecked)(signedRequests.webBotAuth.resolvePrincipal))
|
|
1437
|
+
throw new Error(
|
|
1438
|
+
"Web Bot Auth requires origin revocation: use createIdentity33PrincipalResolver({ revocation }) or supply isRevoked"
|
|
1439
|
+
);
|
|
1436
1440
|
const requiredFor = effectiveRequestSigning.required_for ?? [];
|
|
1437
1441
|
const verifier = (0, import_middleware.createExpressVerifier)({
|
|
1438
1442
|
capability: {
|
|
@@ -1462,20 +1466,25 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
|
|
|
1462
1466
|
const signers = await (0, import_web_bot_auth2.verifyWebBotAuth)(
|
|
1463
1467
|
{ method: req.method ?? "POST", url: requestTarget, headers: req.headers, body: req.rawBody ?? "" },
|
|
1464
1468
|
{
|
|
1469
|
+
// Identity verification needs only key discovery and replay state;
|
|
1470
|
+
// revocation and binding belong to the principal resolver.
|
|
1465
1471
|
directory: signedRequests.webBotAuth.directory,
|
|
1466
|
-
deferAuthorizationErrors: typeof (0, import_operation_resolution.resolveRequestOperation)({ rawBody: req.rawBody, method: req.method, url: req.url }) === "string",
|
|
1467
1472
|
replayStore: signedRequests.replayStore,
|
|
1468
|
-
isRevoked: signedRequests.webBotAuth.isRevoked
|
|
1469
|
-
requireFreshRevocation: ![
|
|
1470
|
-
"get_adcp_capabilities",
|
|
1471
|
-
"get_principal",
|
|
1472
|
-
"list_creative_formats",
|
|
1473
|
-
"list_accounts"
|
|
1474
|
-
].includes(String((0, import_operation_resolution.resolveRequestOperation)({ rawBody: req.rawBody, method: req.method, url: req.url })))
|
|
1473
|
+
...signedRequests.webBotAuth.isRevoked && { isRevoked: signedRequests.webBotAuth.isRevoked }
|
|
1475
1474
|
}
|
|
1476
1475
|
);
|
|
1477
1476
|
const operation = (0, import_operation_resolution.resolveRequestOperation)({ rawBody: req.rawBody, method: req.method, url: req.url });
|
|
1478
|
-
|
|
1477
|
+
let principal;
|
|
1478
|
+
let deferredFailure;
|
|
1479
|
+
try {
|
|
1480
|
+
principal = await signedRequests.webBotAuth.resolvePrincipal(signers, operation);
|
|
1481
|
+
} catch (error) {
|
|
1482
|
+
if (error instanceof import_web_bot_auth2.WebBotAuthError || error instanceof import_web_bot_auth2.WebBotAuthUnavailableError) throw error;
|
|
1483
|
+
if (typeof operation !== "string") throw (0, import_web_bot_auth2.webBotAuthPrincipalFailureError)(error);
|
|
1484
|
+
const deferred = (0, import_web_bot_auth2.deferWebBotAuthPrincipalFailure)(signers, error);
|
|
1485
|
+
principal = { principal: deferred.principal };
|
|
1486
|
+
deferredFailure = deferred.authorizationFailure;
|
|
1487
|
+
}
|
|
1479
1488
|
const signer = signers[signers.length - 1];
|
|
1480
1489
|
const failed = signers.find((s) => s.authorizationFailure);
|
|
1481
1490
|
const guardedPrincipal = {
|
|
@@ -1484,7 +1493,9 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
|
|
|
1484
1493
|
...principal.extra,
|
|
1485
1494
|
webBotAuthAuthorization: {
|
|
1486
1495
|
signer: failed ?? signer,
|
|
1487
|
-
...failed && {
|
|
1496
|
+
...(failed?.authorizationFailure ?? deferredFailure) && {
|
|
1497
|
+
authorizationFailure: failed?.authorizationFailure ?? deferredFailure
|
|
1498
|
+
}
|
|
1488
1499
|
}
|
|
1489
1500
|
}
|
|
1490
1501
|
};
|
|
@@ -1495,6 +1506,12 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
|
|
|
1495
1506
|
});
|
|
1496
1507
|
return false;
|
|
1497
1508
|
} catch (error) {
|
|
1509
|
+
if (error instanceof import_web_bot_auth2.WebBotAuthUnavailableError) {
|
|
1510
|
+
const outage = (0, import_web_bot_auth2.webBotAuthUnavailableResponse)();
|
|
1511
|
+
res.writeHead(outage.status, { ...outage.headers, "Content-Type": "application/json" });
|
|
1512
|
+
res.end(JSON.stringify(outage.body));
|
|
1513
|
+
return true;
|
|
1514
|
+
}
|
|
1498
1515
|
const rejected = error instanceof import_web_bot_auth2.WebBotAuthError ? error : new import_web_bot_auth2.WebBotAuthError(403, "identity_rejected");
|
|
1499
1516
|
res.writeHead(rejected.status, { ...rejected.headers, "Content-Type": "application/json" });
|
|
1500
1517
|
res.end(JSON.stringify(rejected.body));
|
|
@@ -2981,6 +2998,8 @@ function createAdcpServer(config) {
|
|
|
2981
2998
|
try {
|
|
2982
2999
|
await config.identity33.authorize(ctx, toolName, params);
|
|
2983
3000
|
} catch (error) {
|
|
3001
|
+
if (error instanceof import_trust.TrustRecordUnavailableError)
|
|
3002
|
+
return finalize((0, import_errors2.adcpError)("SERVICE_UNAVAILABLE", { message: error.message, recovery: "transient" }));
|
|
2984
3003
|
if (error instanceof import_trust.IdentityAuthorizationError)
|
|
2985
3004
|
return finalize(
|
|
2986
3005
|
(0, import_errors2.adcpError)("PERMISSION_DENIED", {
|
|
@@ -4604,6 +4623,8 @@ function createAdcpServer(config) {
|
|
|
4604
4623
|
params
|
|
4605
4624
|
);
|
|
4606
4625
|
} catch (error) {
|
|
4626
|
+
if (error instanceof import_trust.TrustRecordUnavailableError)
|
|
4627
|
+
return (0, import_errors2.adcpError)("SERVICE_UNAVAILABLE", { message: error.message, recovery: "transient" });
|
|
4607
4628
|
if (error instanceof import_trust.IdentityAuthorizationError)
|
|
4608
4629
|
return (0, import_errors2.adcpError)("PERMISSION_DENIED", {
|
|
4609
4630
|
message: error.message,
|
|
@@ -12,10 +12,15 @@ import {
|
|
|
12
12
|
webBotAuthToolFailure,
|
|
13
13
|
selectSignatureProfile,
|
|
14
14
|
verifyWebBotAuth,
|
|
15
|
+
isWebBotAuthRevocationChecked,
|
|
16
|
+
webBotAuthUnavailableResponse,
|
|
17
|
+
WebBotAuthUnavailableError,
|
|
18
|
+
deferWebBotAuthPrincipalFailure,
|
|
19
|
+
webBotAuthPrincipalFailureError,
|
|
15
20
|
WebBotAuthError
|
|
16
21
|
} from "../signing/web-bot-auth.mjs";
|
|
17
22
|
import { validateIdentity33Payload } from "../identity-3.3/validation.mjs";
|
|
18
|
-
import { IdentityAuthorizationError } from "../identity-3.3/trust.mjs";
|
|
23
|
+
import { IdentityAuthorizationError, TrustRecordUnavailableError } from "../identity-3.3/trust.mjs";
|
|
19
24
|
import { z } from "zod";
|
|
20
25
|
import {
|
|
21
26
|
COMPATIBLE_ADCP_VERSIONS,
|
|
@@ -1516,6 +1521,10 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
|
|
|
1516
1521
|
throw new Error(
|
|
1517
1522
|
"Web Bot Auth requires an origin-binding migration fence; use createIdentity33PrincipalResolver or supply assertLegacyOriginAllowed"
|
|
1518
1523
|
);
|
|
1524
|
+
if (signedRequests.webBotAuth && !signedRequests.webBotAuth.isRevoked && !isWebBotAuthRevocationChecked(signedRequests.webBotAuth.resolvePrincipal))
|
|
1525
|
+
throw new Error(
|
|
1526
|
+
"Web Bot Auth requires origin revocation: use createIdentity33PrincipalResolver({ revocation }) or supply isRevoked"
|
|
1527
|
+
);
|
|
1519
1528
|
const requiredFor = effectiveRequestSigning.required_for ?? [];
|
|
1520
1529
|
const verifier = createExpressVerifier({
|
|
1521
1530
|
capability: {
|
|
@@ -1545,20 +1554,25 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
|
|
|
1545
1554
|
const signers = await verifyWebBotAuth(
|
|
1546
1555
|
{ method: req.method ?? "POST", url: requestTarget, headers: req.headers, body: req.rawBody ?? "" },
|
|
1547
1556
|
{
|
|
1557
|
+
// Identity verification needs only key discovery and replay state;
|
|
1558
|
+
// revocation and binding belong to the principal resolver.
|
|
1548
1559
|
directory: signedRequests.webBotAuth.directory,
|
|
1549
|
-
deferAuthorizationErrors: typeof resolveRequestOperation({ rawBody: req.rawBody, method: req.method, url: req.url }) === "string",
|
|
1550
1560
|
replayStore: signedRequests.replayStore,
|
|
1551
|
-
isRevoked: signedRequests.webBotAuth.isRevoked
|
|
1552
|
-
requireFreshRevocation: ![
|
|
1553
|
-
"get_adcp_capabilities",
|
|
1554
|
-
"get_principal",
|
|
1555
|
-
"list_creative_formats",
|
|
1556
|
-
"list_accounts"
|
|
1557
|
-
].includes(String(resolveRequestOperation({ rawBody: req.rawBody, method: req.method, url: req.url })))
|
|
1561
|
+
...signedRequests.webBotAuth.isRevoked && { isRevoked: signedRequests.webBotAuth.isRevoked }
|
|
1558
1562
|
}
|
|
1559
1563
|
);
|
|
1560
1564
|
const operation = resolveRequestOperation({ rawBody: req.rawBody, method: req.method, url: req.url });
|
|
1561
|
-
|
|
1565
|
+
let principal;
|
|
1566
|
+
let deferredFailure;
|
|
1567
|
+
try {
|
|
1568
|
+
principal = await signedRequests.webBotAuth.resolvePrincipal(signers, operation);
|
|
1569
|
+
} catch (error) {
|
|
1570
|
+
if (error instanceof WebBotAuthError || error instanceof WebBotAuthUnavailableError) throw error;
|
|
1571
|
+
if (typeof operation !== "string") throw webBotAuthPrincipalFailureError(error);
|
|
1572
|
+
const deferred = deferWebBotAuthPrincipalFailure(signers, error);
|
|
1573
|
+
principal = { principal: deferred.principal };
|
|
1574
|
+
deferredFailure = deferred.authorizationFailure;
|
|
1575
|
+
}
|
|
1562
1576
|
const signer = signers[signers.length - 1];
|
|
1563
1577
|
const failed = signers.find((s) => s.authorizationFailure);
|
|
1564
1578
|
const guardedPrincipal = {
|
|
@@ -1567,7 +1581,9 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
|
|
|
1567
1581
|
...principal.extra,
|
|
1568
1582
|
webBotAuthAuthorization: {
|
|
1569
1583
|
signer: failed ?? signer,
|
|
1570
|
-
...failed && {
|
|
1584
|
+
...(failed?.authorizationFailure ?? deferredFailure) && {
|
|
1585
|
+
authorizationFailure: failed?.authorizationFailure ?? deferredFailure
|
|
1586
|
+
}
|
|
1571
1587
|
}
|
|
1572
1588
|
}
|
|
1573
1589
|
};
|
|
@@ -1578,6 +1594,12 @@ function buildSignedRequestsPreTransport(signedRequests, effectiveRequestSigning
|
|
|
1578
1594
|
});
|
|
1579
1595
|
return false;
|
|
1580
1596
|
} catch (error) {
|
|
1597
|
+
if (error instanceof WebBotAuthUnavailableError) {
|
|
1598
|
+
const outage = webBotAuthUnavailableResponse();
|
|
1599
|
+
res.writeHead(outage.status, { ...outage.headers, "Content-Type": "application/json" });
|
|
1600
|
+
res.end(JSON.stringify(outage.body));
|
|
1601
|
+
return true;
|
|
1602
|
+
}
|
|
1581
1603
|
const rejected = error instanceof WebBotAuthError ? error : new WebBotAuthError(403, "identity_rejected");
|
|
1582
1604
|
res.writeHead(rejected.status, { ...rejected.headers, "Content-Type": "application/json" });
|
|
1583
1605
|
res.end(JSON.stringify(rejected.body));
|
|
@@ -3064,6 +3086,8 @@ function createAdcpServer(config) {
|
|
|
3064
3086
|
try {
|
|
3065
3087
|
await config.identity33.authorize(ctx, toolName, params);
|
|
3066
3088
|
} catch (error) {
|
|
3089
|
+
if (error instanceof TrustRecordUnavailableError)
|
|
3090
|
+
return finalize(adcpError("SERVICE_UNAVAILABLE", { message: error.message, recovery: "transient" }));
|
|
3067
3091
|
if (error instanceof IdentityAuthorizationError)
|
|
3068
3092
|
return finalize(
|
|
3069
3093
|
adcpError("PERMISSION_DENIED", {
|
|
@@ -4687,6 +4711,8 @@ function createAdcpServer(config) {
|
|
|
4687
4711
|
params
|
|
4688
4712
|
);
|
|
4689
4713
|
} catch (error) {
|
|
4714
|
+
if (error instanceof TrustRecordUnavailableError)
|
|
4715
|
+
return adcpError("SERVICE_UNAVAILABLE", { message: error.message, recovery: "transient" });
|
|
4690
4716
|
if (error instanceof IdentityAuthorizationError)
|
|
4691
4717
|
return adcpError("PERMISSION_DENIED", {
|
|
4692
4718
|
message: error.message,
|
|
@@ -2,3 +2,18 @@ import { type KeyObject } from 'crypto';
|
|
|
2
2
|
import type { AdcpJsonWebKey } from './types.mjs';
|
|
3
3
|
export declare function jwkToPublicKey(jwk: AdcpJsonWebKey): KeyObject;
|
|
4
4
|
export declare function verifySignature(alg: string, publicKey: KeyObject, data: Uint8Array, signature: Uint8Array): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Verify with WebCrypto when available. ES256 uses `crypto.subtle`, whose
|
|
7
|
+
* ECDSA signatures are IEEE P1363 (r||s) natively, so edge runtimes such as
|
|
8
|
+
* Cloudflare workerd verify without node:crypto option-shape differences
|
|
9
|
+
* (#3243). Other algorithms, and runtimes without WebCrypto, use
|
|
10
|
+
* {@link verifySignature}.
|
|
11
|
+
*/
|
|
12
|
+
export declare function verifySignatureAsync(alg: string, publicKey: KeyObject | AdcpJsonWebKey, data: Uint8Array, signature: Uint8Array): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Sign with a private JWK. ES256 output is IEEE P1363 (r||s). The node:crypto
|
|
15
|
+
* path passes the key as a JWK so workerd accepts it (#3243).
|
|
16
|
+
*/
|
|
17
|
+
export declare function signWithPrivateJwk(alg: string, privateJwk: AdcpJsonWebKey, data: Uint8Array): Uint8Array;
|
|
18
|
+
/** {@link signWithPrivateJwk}, preferring WebCrypto for ES256 when available. */
|
|
19
|
+
export declare function signWithPrivateJwkAsync(alg: string, privateJwk: AdcpJsonWebKey, data: Uint8Array): Promise<Uint8Array>;
|
|
@@ -2,3 +2,18 @@ import { type KeyObject } from 'crypto';
|
|
|
2
2
|
import type { AdcpJsonWebKey } from './types';
|
|
3
3
|
export declare function jwkToPublicKey(jwk: AdcpJsonWebKey): KeyObject;
|
|
4
4
|
export declare function verifySignature(alg: string, publicKey: KeyObject, data: Uint8Array, signature: Uint8Array): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Verify with WebCrypto when available. ES256 uses `crypto.subtle`, whose
|
|
7
|
+
* ECDSA signatures are IEEE P1363 (r||s) natively, so edge runtimes such as
|
|
8
|
+
* Cloudflare workerd verify without node:crypto option-shape differences
|
|
9
|
+
* (#3243). Other algorithms, and runtimes without WebCrypto, use
|
|
10
|
+
* {@link verifySignature}.
|
|
11
|
+
*/
|
|
12
|
+
export declare function verifySignatureAsync(alg: string, publicKey: KeyObject | AdcpJsonWebKey, data: Uint8Array, signature: Uint8Array): Promise<boolean>;
|
|
13
|
+
/**
|
|
14
|
+
* Sign with a private JWK. ES256 output is IEEE P1363 (r||s). The node:crypto
|
|
15
|
+
* path passes the key as a JWK so workerd accepts it (#3243).
|
|
16
|
+
*/
|
|
17
|
+
export declare function signWithPrivateJwk(alg: string, privateJwk: AdcpJsonWebKey, data: Uint8Array): Uint8Array;
|
|
18
|
+
/** {@link signWithPrivateJwk}, preferring WebCrypto for ES256 when available. */
|
|
19
|
+
export declare function signWithPrivateJwkAsync(alg: string, privateJwk: AdcpJsonWebKey, data: Uint8Array): Promise<Uint8Array>;
|
|
@@ -19,7 +19,10 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
19
19
|
var crypto_exports = {};
|
|
20
20
|
__export(crypto_exports, {
|
|
21
21
|
jwkToPublicKey: () => jwkToPublicKey,
|
|
22
|
-
|
|
22
|
+
signWithPrivateJwk: () => signWithPrivateJwk,
|
|
23
|
+
signWithPrivateJwkAsync: () => signWithPrivateJwkAsync,
|
|
24
|
+
verifySignature: () => verifySignature,
|
|
25
|
+
verifySignatureAsync: () => verifySignatureAsync
|
|
23
26
|
});
|
|
24
27
|
module.exports = __toCommonJS(crypto_exports);
|
|
25
28
|
var import_crypto = require("crypto");
|
|
@@ -45,15 +48,92 @@ function verifySignature(alg, publicKey, data, signature) {
|
|
|
45
48
|
return (0, import_crypto.verify)(null, data, publicKey, signature);
|
|
46
49
|
}
|
|
47
50
|
if (alg === "ecdsa-p256-sha256") {
|
|
48
|
-
|
|
51
|
+
try {
|
|
52
|
+
return (0, import_crypto.verify)("sha256", data, { key: publicKey, dsaEncoding: "ieee-p1363" }, signature);
|
|
53
|
+
} catch {
|
|
54
|
+
return (0, import_crypto.verify)(
|
|
55
|
+
"sha256",
|
|
56
|
+
data,
|
|
57
|
+
{ key: publicKey.export({ format: "jwk" }), format: "jwk", dsaEncoding: "ieee-p1363" },
|
|
58
|
+
signature
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if (alg === "rsa-pss-sha512") {
|
|
63
|
+
return (0, import_crypto.verify)(
|
|
64
|
+
"sha512",
|
|
65
|
+
data,
|
|
66
|
+
{ key: publicKey, padding: import_crypto.constants.RSA_PKCS1_PSS_PADDING, saltLength: 64 },
|
|
67
|
+
signature
|
|
68
|
+
);
|
|
49
69
|
}
|
|
50
70
|
return false;
|
|
51
71
|
} catch {
|
|
52
72
|
return false;
|
|
53
73
|
}
|
|
54
74
|
}
|
|
75
|
+
function subtleCrypto() {
|
|
76
|
+
const subtle = globalThis.crypto?.subtle;
|
|
77
|
+
return subtle && typeof subtle.importKey === "function" ? subtle : void 0;
|
|
78
|
+
}
|
|
79
|
+
const P256 = { name: "ECDSA", namedCurve: "P-256" };
|
|
80
|
+
const P256_SHA256 = { name: "ECDSA", hash: "SHA-256" };
|
|
81
|
+
function publicP256Jwk(jwk) {
|
|
82
|
+
return { kty: "EC", crv: "P-256", x: jwk.x, y: jwk.y };
|
|
83
|
+
}
|
|
84
|
+
function privateP256Jwk(jwk) {
|
|
85
|
+
return { kty: "EC", crv: "P-256", x: jwk.x, y: jwk.y, d: jwk.d };
|
|
86
|
+
}
|
|
87
|
+
async function verifySignatureAsync(alg, publicKey, data, signature) {
|
|
88
|
+
const subtle = subtleCrypto();
|
|
89
|
+
const keyObject = () => isKeyObject(publicKey) ? publicKey : jwkToPublicKey(publicKey);
|
|
90
|
+
if (alg !== "ecdsa-p256-sha256" || !subtle) return verifySignature(alg, keyObject(), data, signature);
|
|
91
|
+
try {
|
|
92
|
+
const jwk = isKeyObject(publicKey) ? publicKey.export({ format: "jwk" }) : publicKey;
|
|
93
|
+
const key = await importP256VerifyKey(subtle, jwk);
|
|
94
|
+
return await subtle.verify(P256_SHA256, key, toArrayBuffer(signature), toArrayBuffer(data));
|
|
95
|
+
} catch {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function isKeyObject(value) {
|
|
100
|
+
return typeof value?.export === "function" && "asymmetricKeyType" in value;
|
|
101
|
+
}
|
|
102
|
+
const p256VerifyKeys = /* @__PURE__ */ new Map();
|
|
103
|
+
function importP256VerifyKey(subtle, jwk) {
|
|
104
|
+
if (jwk.kty !== "EC" || jwk.crv !== "P-256" || typeof jwk.x !== "string" || typeof jwk.y !== "string")
|
|
105
|
+
return Promise.reject(new TypeError("Not a P-256 public key"));
|
|
106
|
+
const cacheKey = `${jwk.x}.${jwk.y}`;
|
|
107
|
+
let key = p256VerifyKeys.get(cacheKey);
|
|
108
|
+
if (!key) {
|
|
109
|
+
key = subtle.importKey("jwk", publicP256Jwk(jwk), P256, false, ["verify"]);
|
|
110
|
+
key.catch(() => p256VerifyKeys.delete(cacheKey));
|
|
111
|
+
if (p256VerifyKeys.size >= 256) p256VerifyKeys.delete(p256VerifyKeys.keys().next().value);
|
|
112
|
+
p256VerifyKeys.set(cacheKey, key);
|
|
113
|
+
}
|
|
114
|
+
return key;
|
|
115
|
+
}
|
|
116
|
+
function signWithPrivateJwk(alg, privateJwk, data) {
|
|
117
|
+
if (alg === "ed25519")
|
|
118
|
+
return new Uint8Array((0, import_crypto.sign)(null, data, (0, import_crypto.createPrivateKey)({ key: privateJwk, format: "jwk" })));
|
|
119
|
+
if (alg === "ecdsa-p256-sha256")
|
|
120
|
+
return new Uint8Array((0, import_crypto.sign)("sha256", data, { key: privateJwk, format: "jwk", dsaEncoding: "ieee-p1363" }));
|
|
121
|
+
throw new TypeError(`Unsupported signing algorithm: ${alg}`);
|
|
122
|
+
}
|
|
123
|
+
async function signWithPrivateJwkAsync(alg, privateJwk, data) {
|
|
124
|
+
const subtle = subtleCrypto();
|
|
125
|
+
if (alg !== "ecdsa-p256-sha256" || !subtle) return signWithPrivateJwk(alg, privateJwk, data);
|
|
126
|
+
const key = await subtle.importKey("jwk", privateP256Jwk(privateJwk), P256, false, ["sign"]);
|
|
127
|
+
return new Uint8Array(await subtle.sign(P256_SHA256, key, toArrayBuffer(data)));
|
|
128
|
+
}
|
|
129
|
+
function toArrayBuffer(bytes) {
|
|
130
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
131
|
+
}
|
|
55
132
|
// Annotate the CommonJS export names for ESM import in node:
|
|
56
133
|
0 && (module.exports = {
|
|
57
134
|
jwkToPublicKey,
|
|
58
|
-
|
|
135
|
+
signWithPrivateJwk,
|
|
136
|
+
signWithPrivateJwkAsync,
|
|
137
|
+
verifySignature,
|
|
138
|
+
verifySignatureAsync
|
|
59
139
|
});
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
constants,
|
|
3
|
+
createPrivateKey,
|
|
4
|
+
createPublicKey,
|
|
5
|
+
sign as nodeSign,
|
|
6
|
+
verify as nodeVerify
|
|
7
|
+
} from "crypto";
|
|
2
8
|
import { RequestSignatureError } from "./errors.mjs";
|
|
3
9
|
function jwkToPublicKey(jwk) {
|
|
4
10
|
const publicJwk = { ...jwk };
|
|
@@ -21,14 +27,91 @@ function verifySignature(alg, publicKey, data, signature) {
|
|
|
21
27
|
return nodeVerify(null, data, publicKey, signature);
|
|
22
28
|
}
|
|
23
29
|
if (alg === "ecdsa-p256-sha256") {
|
|
24
|
-
|
|
30
|
+
try {
|
|
31
|
+
return nodeVerify("sha256", data, { key: publicKey, dsaEncoding: "ieee-p1363" }, signature);
|
|
32
|
+
} catch {
|
|
33
|
+
return nodeVerify(
|
|
34
|
+
"sha256",
|
|
35
|
+
data,
|
|
36
|
+
{ key: publicKey.export({ format: "jwk" }), format: "jwk", dsaEncoding: "ieee-p1363" },
|
|
37
|
+
signature
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (alg === "rsa-pss-sha512") {
|
|
42
|
+
return nodeVerify(
|
|
43
|
+
"sha512",
|
|
44
|
+
data,
|
|
45
|
+
{ key: publicKey, padding: constants.RSA_PKCS1_PSS_PADDING, saltLength: 64 },
|
|
46
|
+
signature
|
|
47
|
+
);
|
|
25
48
|
}
|
|
26
49
|
return false;
|
|
27
50
|
} catch {
|
|
28
51
|
return false;
|
|
29
52
|
}
|
|
30
53
|
}
|
|
54
|
+
function subtleCrypto() {
|
|
55
|
+
const subtle = globalThis.crypto?.subtle;
|
|
56
|
+
return subtle && typeof subtle.importKey === "function" ? subtle : void 0;
|
|
57
|
+
}
|
|
58
|
+
const P256 = { name: "ECDSA", namedCurve: "P-256" };
|
|
59
|
+
const P256_SHA256 = { name: "ECDSA", hash: "SHA-256" };
|
|
60
|
+
function publicP256Jwk(jwk) {
|
|
61
|
+
return { kty: "EC", crv: "P-256", x: jwk.x, y: jwk.y };
|
|
62
|
+
}
|
|
63
|
+
function privateP256Jwk(jwk) {
|
|
64
|
+
return { kty: "EC", crv: "P-256", x: jwk.x, y: jwk.y, d: jwk.d };
|
|
65
|
+
}
|
|
66
|
+
async function verifySignatureAsync(alg, publicKey, data, signature) {
|
|
67
|
+
const subtle = subtleCrypto();
|
|
68
|
+
const keyObject = () => isKeyObject(publicKey) ? publicKey : jwkToPublicKey(publicKey);
|
|
69
|
+
if (alg !== "ecdsa-p256-sha256" || !subtle) return verifySignature(alg, keyObject(), data, signature);
|
|
70
|
+
try {
|
|
71
|
+
const jwk = isKeyObject(publicKey) ? publicKey.export({ format: "jwk" }) : publicKey;
|
|
72
|
+
const key = await importP256VerifyKey(subtle, jwk);
|
|
73
|
+
return await subtle.verify(P256_SHA256, key, toArrayBuffer(signature), toArrayBuffer(data));
|
|
74
|
+
} catch {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function isKeyObject(value) {
|
|
79
|
+
return typeof value?.export === "function" && "asymmetricKeyType" in value;
|
|
80
|
+
}
|
|
81
|
+
const p256VerifyKeys = /* @__PURE__ */ new Map();
|
|
82
|
+
function importP256VerifyKey(subtle, jwk) {
|
|
83
|
+
if (jwk.kty !== "EC" || jwk.crv !== "P-256" || typeof jwk.x !== "string" || typeof jwk.y !== "string")
|
|
84
|
+
return Promise.reject(new TypeError("Not a P-256 public key"));
|
|
85
|
+
const cacheKey = `${jwk.x}.${jwk.y}`;
|
|
86
|
+
let key = p256VerifyKeys.get(cacheKey);
|
|
87
|
+
if (!key) {
|
|
88
|
+
key = subtle.importKey("jwk", publicP256Jwk(jwk), P256, false, ["verify"]);
|
|
89
|
+
key.catch(() => p256VerifyKeys.delete(cacheKey));
|
|
90
|
+
if (p256VerifyKeys.size >= 256) p256VerifyKeys.delete(p256VerifyKeys.keys().next().value);
|
|
91
|
+
p256VerifyKeys.set(cacheKey, key);
|
|
92
|
+
}
|
|
93
|
+
return key;
|
|
94
|
+
}
|
|
95
|
+
function signWithPrivateJwk(alg, privateJwk, data) {
|
|
96
|
+
if (alg === "ed25519")
|
|
97
|
+
return new Uint8Array(nodeSign(null, data, createPrivateKey({ key: privateJwk, format: "jwk" })));
|
|
98
|
+
if (alg === "ecdsa-p256-sha256")
|
|
99
|
+
return new Uint8Array(nodeSign("sha256", data, { key: privateJwk, format: "jwk", dsaEncoding: "ieee-p1363" }));
|
|
100
|
+
throw new TypeError(`Unsupported signing algorithm: ${alg}`);
|
|
101
|
+
}
|
|
102
|
+
async function signWithPrivateJwkAsync(alg, privateJwk, data) {
|
|
103
|
+
const subtle = subtleCrypto();
|
|
104
|
+
if (alg !== "ecdsa-p256-sha256" || !subtle) return signWithPrivateJwk(alg, privateJwk, data);
|
|
105
|
+
const key = await subtle.importKey("jwk", privateP256Jwk(privateJwk), P256, false, ["sign"]);
|
|
106
|
+
return new Uint8Array(await subtle.sign(P256_SHA256, key, toArrayBuffer(data)));
|
|
107
|
+
}
|
|
108
|
+
function toArrayBuffer(bytes) {
|
|
109
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
110
|
+
}
|
|
31
111
|
export {
|
|
32
112
|
jwkToPublicKey,
|
|
33
|
-
|
|
113
|
+
signWithPrivateJwk,
|
|
114
|
+
signWithPrivateJwkAsync,
|
|
115
|
+
verifySignature,
|
|
116
|
+
verifySignatureAsync
|
|
34
117
|
};
|
|
@@ -82,7 +82,7 @@ function bodyToString(body) {
|
|
|
82
82
|
}
|
|
83
83
|
function decodeUtf8Strict(bytes) {
|
|
84
84
|
try {
|
|
85
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
85
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
86
86
|
} catch {
|
|
87
87
|
throw new TypeError(
|
|
88
88
|
"createSigningFetchAsync received a Uint8Array/ArrayBuffer body that is not valid UTF-8. Pass a string body, ensure the bytes are UTF-8, or sign the request manually with `signRequestAsync` against the exact wire bytes you intend to send."
|
|
@@ -61,7 +61,7 @@ function bodyToString(body) {
|
|
|
61
61
|
}
|
|
62
62
|
function decodeUtf8Strict(bytes) {
|
|
63
63
|
try {
|
|
64
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
64
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
65
65
|
} catch {
|
|
66
66
|
throw new TypeError(
|
|
67
67
|
"createSigningFetchAsync received a Uint8Array/ArrayBuffer body that is not valid UTF-8. Pass a string body, ensure the bytes are UTF-8, or sign the request manually with `signRequestAsync` against the exact wire bytes you intend to send."
|
|
@@ -91,7 +91,7 @@ function bodyToString(body) {
|
|
|
91
91
|
}
|
|
92
92
|
function decodeUtf8Strict(bytes) {
|
|
93
93
|
try {
|
|
94
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
94
|
+
return new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(bytes);
|
|
95
95
|
} catch {
|
|
96
96
|
throw new TypeError(
|
|
97
97
|
"createSigningFetch received a Uint8Array/ArrayBuffer body that is not valid UTF-8. Pass a string body, ensure the bytes are UTF-8, or sign the request manually with `signRequest` against the exact wire bytes you intend to send."
|