@vivero/stoma 0.1.0-rc.10

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.
Files changed (254) hide show
  1. package/CHANGELOG.md +196 -0
  2. package/LICENSE +21 -0
  3. package/README.md +325 -0
  4. package/dist/adapters/bun.d.ts +9 -0
  5. package/dist/adapters/bun.js +8 -0
  6. package/dist/adapters/bun.js.map +1 -0
  7. package/dist/adapters/cloudflare.d.ts +49 -0
  8. package/dist/adapters/cloudflare.js +85 -0
  9. package/dist/adapters/cloudflare.js.map +1 -0
  10. package/dist/adapters/deno.d.ts +9 -0
  11. package/dist/adapters/deno.js +8 -0
  12. package/dist/adapters/deno.js.map +1 -0
  13. package/dist/adapters/durable-object.d.ts +63 -0
  14. package/dist/adapters/durable-object.js +46 -0
  15. package/dist/adapters/durable-object.js.map +1 -0
  16. package/dist/adapters/index.d.ts +13 -0
  17. package/dist/adapters/index.js +53 -0
  18. package/dist/adapters/index.js.map +1 -0
  19. package/dist/adapters/memory.d.ts +9 -0
  20. package/dist/adapters/memory.js +14 -0
  21. package/dist/adapters/memory.js.map +1 -0
  22. package/dist/adapters/node.d.ts +9 -0
  23. package/dist/adapters/node.js +8 -0
  24. package/dist/adapters/node.js.map +1 -0
  25. package/dist/adapters/postgres.d.ts +109 -0
  26. package/dist/adapters/postgres.js +242 -0
  27. package/dist/adapters/postgres.js.map +1 -0
  28. package/dist/adapters/redis.d.ts +116 -0
  29. package/dist/adapters/redis.js +194 -0
  30. package/dist/adapters/redis.js.map +1 -0
  31. package/dist/adapters/testing.d.ts +32 -0
  32. package/dist/adapters/testing.js +33 -0
  33. package/dist/adapters/testing.js.map +1 -0
  34. package/dist/adapters/types.d.ts +4 -0
  35. package/dist/adapters/types.js +1 -0
  36. package/dist/adapters/types.js.map +1 -0
  37. package/dist/config/index.d.ts +11 -0
  38. package/dist/config/index.js +21 -0
  39. package/dist/config/index.js.map +1 -0
  40. package/dist/config/merge.d.ts +48 -0
  41. package/dist/config/merge.js +83 -0
  42. package/dist/config/merge.js.map +1 -0
  43. package/dist/config/schema.d.ts +254 -0
  44. package/dist/config/schema.js +109 -0
  45. package/dist/config/schema.js.map +1 -0
  46. package/dist/core/errors.d.ts +66 -0
  47. package/dist/core/errors.js +47 -0
  48. package/dist/core/errors.js.map +1 -0
  49. package/dist/core/gateway.d.ts +44 -0
  50. package/dist/core/gateway.js +400 -0
  51. package/dist/core/gateway.js.map +1 -0
  52. package/dist/core/health.d.ts +78 -0
  53. package/dist/core/health.js +65 -0
  54. package/dist/core/health.js.map +1 -0
  55. package/dist/core/pipeline.d.ts +62 -0
  56. package/dist/core/pipeline.js +214 -0
  57. package/dist/core/pipeline.js.map +1 -0
  58. package/dist/core/protocol.d.ts +4 -0
  59. package/dist/core/protocol.js +1 -0
  60. package/dist/core/protocol.js.map +1 -0
  61. package/dist/core/scope.d.ts +67 -0
  62. package/dist/core/scope.js +44 -0
  63. package/dist/core/scope.js.map +1 -0
  64. package/dist/core/types.d.ts +252 -0
  65. package/dist/core/types.js +1 -0
  66. package/dist/core/types.js.map +1 -0
  67. package/dist/index.d.ts +57 -0
  68. package/dist/index.js +158 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/observability/admin.d.ts +32 -0
  71. package/dist/observability/admin.js +85 -0
  72. package/dist/observability/admin.js.map +1 -0
  73. package/dist/observability/metrics.d.ts +78 -0
  74. package/dist/observability/metrics.js +107 -0
  75. package/dist/observability/metrics.js.map +1 -0
  76. package/dist/observability/tracing.d.ts +149 -0
  77. package/dist/observability/tracing.js +191 -0
  78. package/dist/observability/tracing.js.map +1 -0
  79. package/dist/policies/auth/api-key-auth.d.ts +64 -0
  80. package/dist/policies/auth/api-key-auth.js +93 -0
  81. package/dist/policies/auth/api-key-auth.js.map +1 -0
  82. package/dist/policies/auth/basic-auth.d.ts +33 -0
  83. package/dist/policies/auth/basic-auth.js +96 -0
  84. package/dist/policies/auth/basic-auth.js.map +1 -0
  85. package/dist/policies/auth/crypto.d.ts +29 -0
  86. package/dist/policies/auth/crypto.js +100 -0
  87. package/dist/policies/auth/crypto.js.map +1 -0
  88. package/dist/policies/auth/generate-http-signature.d.ts +30 -0
  89. package/dist/policies/auth/generate-http-signature.js +79 -0
  90. package/dist/policies/auth/generate-http-signature.js.map +1 -0
  91. package/dist/policies/auth/generate-jwt.d.ts +44 -0
  92. package/dist/policies/auth/generate-jwt.js +99 -0
  93. package/dist/policies/auth/generate-jwt.js.map +1 -0
  94. package/dist/policies/auth/http-signature-base.d.ts +55 -0
  95. package/dist/policies/auth/http-signature-base.js +140 -0
  96. package/dist/policies/auth/http-signature-base.js.map +1 -0
  97. package/dist/policies/auth/jws.d.ts +46 -0
  98. package/dist/policies/auth/jws.js +317 -0
  99. package/dist/policies/auth/jws.js.map +1 -0
  100. package/dist/policies/auth/jwt-auth.d.ts +64 -0
  101. package/dist/policies/auth/jwt-auth.js +266 -0
  102. package/dist/policies/auth/jwt-auth.js.map +1 -0
  103. package/dist/policies/auth/oauth2.d.ts +38 -0
  104. package/dist/policies/auth/oauth2.js +254 -0
  105. package/dist/policies/auth/oauth2.js.map +1 -0
  106. package/dist/policies/auth/rbac.d.ts +30 -0
  107. package/dist/policies/auth/rbac.js +115 -0
  108. package/dist/policies/auth/rbac.js.map +1 -0
  109. package/dist/policies/auth/verify-http-signature.d.ts +30 -0
  110. package/dist/policies/auth/verify-http-signature.js +147 -0
  111. package/dist/policies/auth/verify-http-signature.js.map +1 -0
  112. package/dist/policies/index.d.ts +51 -0
  113. package/dist/policies/index.js +109 -0
  114. package/dist/policies/index.js.map +1 -0
  115. package/dist/policies/mock.d.ts +60 -0
  116. package/dist/policies/mock.js +29 -0
  117. package/dist/policies/mock.js.map +1 -0
  118. package/dist/policies/observability/assign-metrics.d.ts +37 -0
  119. package/dist/policies/observability/assign-metrics.js +29 -0
  120. package/dist/policies/observability/assign-metrics.js.map +1 -0
  121. package/dist/policies/observability/metrics-reporter.d.ts +25 -0
  122. package/dist/policies/observability/metrics-reporter.js +62 -0
  123. package/dist/policies/observability/metrics-reporter.js.map +1 -0
  124. package/dist/policies/observability/request-log.d.ts +135 -0
  125. package/dist/policies/observability/request-log.js +134 -0
  126. package/dist/policies/observability/request-log.js.map +1 -0
  127. package/dist/policies/observability/server-timing.d.ts +35 -0
  128. package/dist/policies/observability/server-timing.js +89 -0
  129. package/dist/policies/observability/server-timing.js.map +1 -0
  130. package/dist/policies/proxy.d.ts +59 -0
  131. package/dist/policies/proxy.js +47 -0
  132. package/dist/policies/proxy.js.map +1 -0
  133. package/dist/policies/resilience/circuit-breaker.d.ts +4 -0
  134. package/dist/policies/resilience/circuit-breaker.js +280 -0
  135. package/dist/policies/resilience/circuit-breaker.js.map +1 -0
  136. package/dist/policies/resilience/latency-injection.d.ts +35 -0
  137. package/dist/policies/resilience/latency-injection.js +26 -0
  138. package/dist/policies/resilience/latency-injection.js.map +1 -0
  139. package/dist/policies/resilience/retry.d.ts +71 -0
  140. package/dist/policies/resilience/retry.js +79 -0
  141. package/dist/policies/resilience/retry.js.map +1 -0
  142. package/dist/policies/resilience/timeout.d.ts +32 -0
  143. package/dist/policies/resilience/timeout.js +46 -0
  144. package/dist/policies/resilience/timeout.js.map +1 -0
  145. package/dist/policies/sdk/define-policy.d.ts +176 -0
  146. package/dist/policies/sdk/define-policy.js +42 -0
  147. package/dist/policies/sdk/define-policy.js.map +1 -0
  148. package/dist/policies/sdk/helpers.d.ts +132 -0
  149. package/dist/policies/sdk/helpers.js +87 -0
  150. package/dist/policies/sdk/helpers.js.map +1 -0
  151. package/dist/policies/sdk/index.d.ts +10 -0
  152. package/dist/policies/sdk/index.js +35 -0
  153. package/dist/policies/sdk/index.js.map +1 -0
  154. package/dist/policies/sdk/priority.d.ts +44 -0
  155. package/dist/policies/sdk/priority.js +36 -0
  156. package/dist/policies/sdk/priority.js.map +1 -0
  157. package/dist/policies/sdk/testing.d.ts +53 -0
  158. package/dist/policies/sdk/testing.js +41 -0
  159. package/dist/policies/sdk/testing.js.map +1 -0
  160. package/dist/policies/sdk/trace.d.ts +73 -0
  161. package/dist/policies/sdk/trace.js +25 -0
  162. package/dist/policies/sdk/trace.js.map +1 -0
  163. package/dist/policies/traffic/cache.d.ts +4 -0
  164. package/dist/policies/traffic/cache.js +224 -0
  165. package/dist/policies/traffic/cache.js.map +1 -0
  166. package/dist/policies/traffic/dynamic-routing.d.ts +54 -0
  167. package/dist/policies/traffic/dynamic-routing.js +36 -0
  168. package/dist/policies/traffic/dynamic-routing.js.map +1 -0
  169. package/dist/policies/traffic/geo-ip-filter.d.ts +37 -0
  170. package/dist/policies/traffic/geo-ip-filter.js +74 -0
  171. package/dist/policies/traffic/geo-ip-filter.js.map +1 -0
  172. package/dist/policies/traffic/http-callout.d.ts +59 -0
  173. package/dist/policies/traffic/http-callout.js +69 -0
  174. package/dist/policies/traffic/http-callout.js.map +1 -0
  175. package/dist/policies/traffic/interrupt.d.ts +46 -0
  176. package/dist/policies/traffic/interrupt.js +38 -0
  177. package/dist/policies/traffic/interrupt.js.map +1 -0
  178. package/dist/policies/traffic/ip-filter.d.ts +47 -0
  179. package/dist/policies/traffic/ip-filter.js +57 -0
  180. package/dist/policies/traffic/ip-filter.js.map +1 -0
  181. package/dist/policies/traffic/json-threat-protection.d.ts +51 -0
  182. package/dist/policies/traffic/json-threat-protection.js +173 -0
  183. package/dist/policies/traffic/json-threat-protection.js.map +1 -0
  184. package/dist/policies/traffic/rate-limit.d.ts +4 -0
  185. package/dist/policies/traffic/rate-limit.js +145 -0
  186. package/dist/policies/traffic/rate-limit.js.map +1 -0
  187. package/dist/policies/traffic/regex-threat-protection.d.ts +54 -0
  188. package/dist/policies/traffic/regex-threat-protection.js +109 -0
  189. package/dist/policies/traffic/regex-threat-protection.js.map +1 -0
  190. package/dist/policies/traffic/request-limit.d.ts +27 -0
  191. package/dist/policies/traffic/request-limit.js +41 -0
  192. package/dist/policies/traffic/request-limit.js.map +1 -0
  193. package/dist/policies/traffic/resource-filter.d.ts +38 -0
  194. package/dist/policies/traffic/resource-filter.js +184 -0
  195. package/dist/policies/traffic/resource-filter.js.map +1 -0
  196. package/dist/policies/traffic/ssl-enforce.d.ts +27 -0
  197. package/dist/policies/traffic/ssl-enforce.js +38 -0
  198. package/dist/policies/traffic/ssl-enforce.js.map +1 -0
  199. package/dist/policies/traffic/traffic-shadow.d.ts +40 -0
  200. package/dist/policies/traffic/traffic-shadow.js +87 -0
  201. package/dist/policies/traffic/traffic-shadow.js.map +1 -0
  202. package/dist/policies/transform/assign-attributes.d.ts +33 -0
  203. package/dist/policies/transform/assign-attributes.js +38 -0
  204. package/dist/policies/transform/assign-attributes.js.map +1 -0
  205. package/dist/policies/transform/assign-content.d.ts +40 -0
  206. package/dist/policies/transform/assign-content.js +185 -0
  207. package/dist/policies/transform/assign-content.js.map +1 -0
  208. package/dist/policies/transform/cors.d.ts +57 -0
  209. package/dist/policies/transform/cors.js +23 -0
  210. package/dist/policies/transform/cors.js.map +1 -0
  211. package/dist/policies/transform/json-validation.d.ts +50 -0
  212. package/dist/policies/transform/json-validation.js +125 -0
  213. package/dist/policies/transform/json-validation.js.map +1 -0
  214. package/dist/policies/transform/override-method.d.ts +33 -0
  215. package/dist/policies/transform/override-method.js +48 -0
  216. package/dist/policies/transform/override-method.js.map +1 -0
  217. package/dist/policies/transform/request-validation.d.ts +59 -0
  218. package/dist/policies/transform/request-validation.js +121 -0
  219. package/dist/policies/transform/request-validation.js.map +1 -0
  220. package/dist/policies/transform/transform.d.ts +75 -0
  221. package/dist/policies/transform/transform.js +116 -0
  222. package/dist/policies/transform/transform.js.map +1 -0
  223. package/dist/policies/types.d.ts +4 -0
  224. package/dist/policies/types.js +1 -0
  225. package/dist/policies/types.js.map +1 -0
  226. package/dist/protocol-2fD3DJrL.d.ts +725 -0
  227. package/dist/utils/cidr.d.ts +58 -0
  228. package/dist/utils/cidr.js +107 -0
  229. package/dist/utils/cidr.js.map +1 -0
  230. package/dist/utils/debug.d.ts +1 -0
  231. package/dist/utils/debug.js +13 -0
  232. package/dist/utils/debug.js.map +1 -0
  233. package/dist/utils/headers.d.ts +68 -0
  234. package/dist/utils/headers.js +25 -0
  235. package/dist/utils/headers.js.map +1 -0
  236. package/dist/utils/ip.d.ts +64 -0
  237. package/dist/utils/ip.js +29 -0
  238. package/dist/utils/ip.js.map +1 -0
  239. package/dist/utils/redact.d.ts +30 -0
  240. package/dist/utils/redact.js +52 -0
  241. package/dist/utils/redact.js.map +1 -0
  242. package/dist/utils/request-id.d.ts +11 -0
  243. package/dist/utils/request-id.js +7 -0
  244. package/dist/utils/request-id.js.map +1 -0
  245. package/dist/utils/timing-safe.d.ts +31 -0
  246. package/dist/utils/timing-safe.js +17 -0
  247. package/dist/utils/timing-safe.js.map +1 -0
  248. package/dist/utils/timing.d.ts +27 -0
  249. package/dist/utils/timing.js +12 -0
  250. package/dist/utils/timing.js.map +1 -0
  251. package/dist/utils/trace-context.d.ts +51 -0
  252. package/dist/utils/trace-context.js +37 -0
  253. package/dist/utils/trace-context.js.map +1 -0
  254. package/package.json +213 -0
@@ -0,0 +1,99 @@
1
+ import { GatewayError } from "../../core/errors";
2
+ import { withModifiedHeaders } from "../../utils/headers";
3
+ import { definePolicy, Priority } from "../sdk";
4
+ import { base64UrlEncodeBytes, base64UrlEncodeString } from "./crypto";
5
+ function getHashAlgorithm(alg) {
6
+ switch (alg) {
7
+ case "HS256":
8
+ case "RS256":
9
+ return "SHA-256";
10
+ case "HS384":
11
+ case "RS384":
12
+ return "SHA-384";
13
+ case "HS512":
14
+ case "RS512":
15
+ return "SHA-512";
16
+ }
17
+ }
18
+ function isHmac(alg) {
19
+ return alg.startsWith("HS");
20
+ }
21
+ const generateJwt = /* @__PURE__ */ definePolicy({
22
+ name: "generate-jwt",
23
+ priority: Priority.REQUEST_TRANSFORM,
24
+ defaults: {
25
+ expiresIn: 3600,
26
+ headerName: "Authorization",
27
+ tokenPrefix: "Bearer"
28
+ },
29
+ handler: async (c, next, { config, debug }) => {
30
+ if (isHmac(config.algorithm)) {
31
+ if (!config.secret) {
32
+ throw new GatewayError(
33
+ 500,
34
+ "config_error",
35
+ "generateJwt with HMAC algorithm requires 'secret'"
36
+ );
37
+ }
38
+ } else {
39
+ if (!config.privateKey) {
40
+ throw new GatewayError(
41
+ 500,
42
+ "config_error",
43
+ "generateJwt with RSA algorithm requires 'privateKey'"
44
+ );
45
+ }
46
+ }
47
+ const jwtHeader = { alg: config.algorithm, typ: "JWT" };
48
+ const encodedHeader = base64UrlEncodeString(JSON.stringify(jwtHeader));
49
+ const now = Math.floor(Date.now() / 1e3);
50
+ const baseClaims = {
51
+ iat: now,
52
+ exp: now + (config.expiresIn ?? 3600)
53
+ };
54
+ if (config.issuer) baseClaims.iss = config.issuer;
55
+ if (config.audience) baseClaims.aud = config.audience;
56
+ let userClaims = {};
57
+ if (config.claims) {
58
+ userClaims = typeof config.claims === "function" ? await config.claims(c) : config.claims;
59
+ }
60
+ const payload = { ...baseClaims, ...userClaims };
61
+ const encodedPayload = base64UrlEncodeString(JSON.stringify(payload));
62
+ const signingInput = `${encodedHeader}.${encodedPayload}`;
63
+ const encoder = new TextEncoder();
64
+ const data = encoder.encode(signingInput);
65
+ const hash = getHashAlgorithm(config.algorithm);
66
+ let signature;
67
+ if (isHmac(config.algorithm)) {
68
+ const key = await crypto.subtle.importKey(
69
+ "raw",
70
+ encoder.encode(config.secret),
71
+ { name: "HMAC", hash },
72
+ false,
73
+ ["sign"]
74
+ );
75
+ signature = await crypto.subtle.sign("HMAC", key, data);
76
+ } else {
77
+ const key = await crypto.subtle.importKey(
78
+ "jwk",
79
+ config.privateKey,
80
+ { name: "RSASSA-PKCS1-v1_5", hash },
81
+ false,
82
+ ["sign"]
83
+ );
84
+ signature = await crypto.subtle.sign("RSASSA-PKCS1-v1_5", key, data);
85
+ }
86
+ const encodedSignature = base64UrlEncodeBytes(new Uint8Array(signature));
87
+ const token = `${signingInput}.${encodedSignature}`;
88
+ debug(`generated JWT (alg=${config.algorithm})`);
89
+ const headerValue = config.tokenPrefix ? `${config.tokenPrefix} ${token}` : token;
90
+ withModifiedHeaders(c, (headers) => {
91
+ headers.set(config.headerName, headerValue);
92
+ });
93
+ await next();
94
+ }
95
+ });
96
+ export {
97
+ generateJwt
98
+ };
99
+ //# sourceMappingURL=generate-jwt.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/policies/auth/generate-jwt.ts"],"sourcesContent":["/**\n * JWT generation policy - mints JWTs for upstream consumption.\n *\n * Signs tokens using HMAC (HS256/384/512) or RSA (RS256/384/512) and\n * attaches them to the outgoing request as a header.\n *\n * @module generate-jwt\n */\nimport type { Context } from \"hono\";\nimport { GatewayError } from \"../../core/errors\";\nimport { withModifiedHeaders } from \"../../utils/headers\";\nimport { definePolicy, Priority } from \"../sdk\";\nimport type { PolicyConfig } from \"../types\";\nimport { base64UrlEncodeBytes, base64UrlEncodeString } from \"./crypto\";\n\nexport interface GenerateJwtConfig extends PolicyConfig {\n /** Signing algorithm */\n algorithm: \"HS256\" | \"HS384\" | \"HS512\" | \"RS256\" | \"RS384\" | \"RS512\";\n /** HMAC secret (for HS* algorithms) */\n secret?: string;\n /** RSA private key as JWK (for RS* algorithms) */\n privateKey?: JsonWebKey;\n /** Claims to include. Static record or dynamic function. */\n claims?:\n | Record<string, unknown>\n | ((\n c: Context\n ) => Record<string, unknown> | Promise<Record<string, unknown>>);\n /** Token lifetime in seconds. Default: 3600 (1 hour) */\n expiresIn?: number;\n /** Issuer claim */\n issuer?: string;\n /** Audience claim */\n audience?: string;\n /** Header name for the generated token. Default: \"Authorization\" */\n headerName?: string;\n /** Token prefix. Default: \"Bearer\" */\n tokenPrefix?: string;\n}\n\nfunction getHashAlgorithm(alg: GenerateJwtConfig[\"algorithm\"]): string {\n switch (alg) {\n case \"HS256\":\n case \"RS256\":\n return \"SHA-256\";\n case \"HS384\":\n case \"RS384\":\n return \"SHA-384\";\n case \"HS512\":\n case \"RS512\":\n return \"SHA-512\";\n }\n}\n\nfunction isHmac(alg: string): boolean {\n return alg.startsWith(\"HS\");\n}\n\n/**\n * Mint JWTs and attach them to the request for upstream consumption.\n *\n * @example\n * ```ts\n * import { generateJwt } from \"@vivero/stoma\";\n *\n * generateJwt({\n * algorithm: \"HS256\",\n * secret: env.JWT_SIGNING_SECRET,\n * claims: (c) => ({ sub: c.req.header(\"x-user-id\") }),\n * issuer: \"my-gateway\",\n * expiresIn: 300,\n * });\n * ```\n */\nexport const generateJwt = /*#__PURE__*/ definePolicy<GenerateJwtConfig>({\n name: \"generate-jwt\",\n priority: Priority.REQUEST_TRANSFORM,\n defaults: {\n expiresIn: 3600,\n headerName: \"Authorization\",\n tokenPrefix: \"Bearer\",\n },\n handler: async (c, next, { config, debug }) => {\n // Validate config at request time (allows lazy secret resolution)\n if (isHmac(config.algorithm)) {\n if (!config.secret) {\n throw new GatewayError(\n 500,\n \"config_error\",\n \"generateJwt with HMAC algorithm requires 'secret'\"\n );\n }\n } else {\n if (!config.privateKey) {\n throw new GatewayError(\n 500,\n \"config_error\",\n \"generateJwt with RSA algorithm requires 'privateKey'\"\n );\n }\n }\n\n // Build header\n const jwtHeader = { alg: config.algorithm, typ: \"JWT\" };\n const encodedHeader = base64UrlEncodeString(JSON.stringify(jwtHeader));\n\n // Build payload\n const now = Math.floor(Date.now() / 1000);\n const baseClaims: Record<string, unknown> = {\n iat: now,\n exp: now + (config.expiresIn ?? 3600),\n };\n if (config.issuer) baseClaims.iss = config.issuer;\n if (config.audience) baseClaims.aud = config.audience;\n\n let userClaims: Record<string, unknown> = {};\n if (config.claims) {\n userClaims =\n typeof config.claims === \"function\"\n ? await config.claims(c)\n : config.claims;\n }\n\n const payload = { ...baseClaims, ...userClaims };\n const encodedPayload = base64UrlEncodeString(JSON.stringify(payload));\n\n // Sign\n const signingInput = `${encodedHeader}.${encodedPayload}`;\n const encoder = new TextEncoder();\n const data = encoder.encode(signingInput);\n\n const hash = getHashAlgorithm(config.algorithm);\n let signature: ArrayBuffer;\n\n if (isHmac(config.algorithm)) {\n const key = await crypto.subtle.importKey(\n \"raw\",\n encoder.encode(config.secret!),\n { name: \"HMAC\", hash },\n false,\n [\"sign\"]\n );\n signature = await crypto.subtle.sign(\"HMAC\", key, data);\n } else {\n const key = await crypto.subtle.importKey(\n \"jwk\",\n config.privateKey!,\n { name: \"RSASSA-PKCS1-v1_5\", hash },\n false,\n [\"sign\"]\n );\n signature = await crypto.subtle.sign(\"RSASSA-PKCS1-v1_5\", key, data);\n }\n\n const encodedSignature = base64UrlEncodeBytes(new Uint8Array(signature));\n const token = `${signingInput}.${encodedSignature}`;\n\n debug(`generated JWT (alg=${config.algorithm})`);\n\n // Attach to request\n const headerValue = config.tokenPrefix\n ? `${config.tokenPrefix} ${token}`\n : token;\n\n withModifiedHeaders(c, (headers) => {\n headers.set(config.headerName!, headerValue);\n });\n\n await next();\n },\n});\n"],"mappings":"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","names":[]}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Shared utilities for RFC 9421 HTTP Message Signatures.
3
+ *
4
+ * Builds the signature base string and provides crypto helpers
5
+ * used by both `generateHttpSignature` and `verifyHttpSignature`.
6
+ *
7
+ * @module http-signature-base
8
+ */
9
+ /**
10
+ * Build the signature base string per RFC 9421 Section 2.5.
11
+ *
12
+ * Each line is `"component-id": value`, ending with `"@signature-params": <params>`.
13
+ */
14
+ declare function buildSignatureBase(components: string[], signatureParams: string, request: Request): string;
15
+ /**
16
+ * Build the signature params string.
17
+ *
18
+ * Format: `("@method" "@path" ...);created=<ts>;keyid="<id>"[;expires=<ts>][;nonce="<n>"]`
19
+ */
20
+ declare function buildSignatureParams(components: string[], params: {
21
+ created: number;
22
+ keyId: string;
23
+ expires?: number;
24
+ nonce?: string;
25
+ algorithm?: string;
26
+ }): string;
27
+ /**
28
+ * Parse a signature params string from the Signature-Input header.
29
+ *
30
+ * Input: `("@method" "@path" "content-type");created=1618884473;keyid="test-key"`
31
+ * Returns the component list and key-value parameters.
32
+ */
33
+ declare function parseSignatureParams(input: string): {
34
+ components: string[];
35
+ params: Record<string, string>;
36
+ };
37
+ /** Map algorithm identifier to Web Crypto params for import + sign/verify. */
38
+ declare function algorithmToCrypto(alg: string): {
39
+ importAlg: Parameters<typeof crypto.subtle.importKey>[2];
40
+ signAlg: Parameters<typeof crypto.subtle.sign>[0];
41
+ };
42
+ /**
43
+ * Import key material for signing.
44
+ */
45
+ declare function importSigningKey(algorithm: string, secret?: string, privateKey?: JsonWebKey): Promise<CryptoKey>;
46
+ /**
47
+ * Import key material for verification.
48
+ */
49
+ declare function importVerifyKey(algorithm: string, secret?: string, publicKey?: JsonWebKey): Promise<CryptoKey>;
50
+ /** Encode bytes to standard base64. */
51
+ declare function toBase64(buffer: ArrayBuffer): string;
52
+ /** Decode standard base64 to bytes. */
53
+ declare function fromBase64(str: string): Uint8Array;
54
+
55
+ export { algorithmToCrypto, buildSignatureBase, buildSignatureParams, fromBase64, importSigningKey, importVerifyKey, parseSignatureParams, toBase64 };
@@ -0,0 +1,140 @@
1
+ function resolveDerivedComponent(componentId, request) {
2
+ const url = new URL(request.url);
3
+ switch (componentId) {
4
+ case "@method":
5
+ return request.method.toUpperCase();
6
+ case "@path":
7
+ return url.pathname;
8
+ case "@authority":
9
+ return url.host;
10
+ case "@scheme":
11
+ return url.protocol.replace(":", "");
12
+ case "@target-uri":
13
+ return url.href;
14
+ default:
15
+ throw new Error(`Unknown derived component: ${componentId}`);
16
+ }
17
+ }
18
+ function resolveComponentValue(componentId, request) {
19
+ if (componentId.startsWith("@")) {
20
+ return resolveDerivedComponent(componentId, request);
21
+ }
22
+ return request.headers.get(componentId) ?? "";
23
+ }
24
+ function buildSignatureBase(components, signatureParams, request) {
25
+ const lines = [];
26
+ for (const component of components) {
27
+ const value = resolveComponentValue(component, request);
28
+ lines.push(`"${component}": ${value}`);
29
+ }
30
+ lines.push(`"@signature-params": ${signatureParams}`);
31
+ return lines.join("\n");
32
+ }
33
+ function buildSignatureParams(components, params) {
34
+ const componentList = components.map((c) => `"${c}"`).join(" ");
35
+ let result = `(${componentList});created=${params.created};keyid="${params.keyId}"`;
36
+ if (params.algorithm) {
37
+ result += `;alg="${params.algorithm}"`;
38
+ }
39
+ if (params.expires !== void 0) {
40
+ result += `;expires=${params.expires}`;
41
+ }
42
+ if (params.nonce !== void 0) {
43
+ result += `;nonce="${params.nonce}"`;
44
+ }
45
+ return result;
46
+ }
47
+ function parseSignatureParams(input) {
48
+ const parenMatch = input.match(/^\(([^)]*)\)/);
49
+ if (!parenMatch) {
50
+ throw new Error("Invalid signature params: missing component list");
51
+ }
52
+ const componentStr = parenMatch[1];
53
+ const components = componentStr ? componentStr.match(/"([^"]+)"/g)?.map((s) => s.slice(1, -1)) ?? [] : [];
54
+ const paramStr = input.slice(parenMatch[0].length);
55
+ const params = {};
56
+ const paramRegex = /;(\w+)=("([^"]*)"|(\d+))/g;
57
+ let match = paramRegex.exec(paramStr);
58
+ while (match !== null) {
59
+ params[match[1]] = match[3] ?? match[4];
60
+ match = paramRegex.exec(paramStr);
61
+ }
62
+ return { components, params };
63
+ }
64
+ function algorithmToCrypto(alg) {
65
+ switch (alg) {
66
+ case "hmac-sha256":
67
+ return {
68
+ importAlg: { name: "HMAC", hash: "SHA-256" },
69
+ signAlg: "HMAC"
70
+ };
71
+ case "rsa-v1_5-sha256":
72
+ return {
73
+ importAlg: { name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" },
74
+ signAlg: "RSASSA-PKCS1-v1_5"
75
+ };
76
+ case "rsa-pss-sha512":
77
+ return {
78
+ importAlg: { name: "RSA-PSS", hash: "SHA-512" },
79
+ signAlg: { name: "RSA-PSS", saltLength: 64 }
80
+ };
81
+ default:
82
+ throw new Error(`Unsupported signature algorithm: ${alg}`);
83
+ }
84
+ }
85
+ async function importSigningKey(algorithm, secret, privateKey) {
86
+ const { importAlg } = algorithmToCrypto(algorithm);
87
+ if (algorithm.startsWith("hmac")) {
88
+ if (!secret) throw new Error("HMAC algorithm requires secret");
89
+ const encoder = new TextEncoder();
90
+ return crypto.subtle.importKey(
91
+ "raw",
92
+ encoder.encode(secret),
93
+ importAlg,
94
+ false,
95
+ ["sign"]
96
+ );
97
+ }
98
+ if (!privateKey) throw new Error("RSA algorithm requires privateKey");
99
+ return crypto.subtle.importKey("jwk", privateKey, importAlg, false, ["sign"]);
100
+ }
101
+ async function importVerifyKey(algorithm, secret, publicKey) {
102
+ const { importAlg } = algorithmToCrypto(algorithm);
103
+ if (algorithm.startsWith("hmac")) {
104
+ if (!secret) throw new Error("HMAC algorithm requires secret");
105
+ const encoder = new TextEncoder();
106
+ return crypto.subtle.importKey(
107
+ "raw",
108
+ encoder.encode(secret),
109
+ importAlg,
110
+ false,
111
+ ["verify"]
112
+ );
113
+ }
114
+ if (!publicKey) throw new Error("RSA algorithm requires publicKey");
115
+ return crypto.subtle.importKey("jwk", publicKey, importAlg, false, [
116
+ "verify"
117
+ ]);
118
+ }
119
+ function toBase64(buffer) {
120
+ return btoa(String.fromCharCode(...new Uint8Array(buffer)));
121
+ }
122
+ function fromBase64(str) {
123
+ const binary = atob(str);
124
+ const bytes = new Uint8Array(binary.length);
125
+ for (let i = 0; i < binary.length; i++) {
126
+ bytes[i] = binary.charCodeAt(i);
127
+ }
128
+ return bytes;
129
+ }
130
+ export {
131
+ algorithmToCrypto,
132
+ buildSignatureBase,
133
+ buildSignatureParams,
134
+ fromBase64,
135
+ importSigningKey,
136
+ importVerifyKey,
137
+ parseSignatureParams,
138
+ toBase64
139
+ };
140
+ //# sourceMappingURL=http-signature-base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/policies/auth/http-signature-base.ts"],"sourcesContent":["/**\n * Shared utilities for RFC 9421 HTTP Message Signatures.\n *\n * Builds the signature base string and provides crypto helpers\n * used by both `generateHttpSignature` and `verifyHttpSignature`.\n *\n * @module http-signature-base\n */\n\n/**\n * Resolve a derived component value from the request per RFC 9421 Section 2.2.\n */\nfunction resolveDerivedComponent(\n componentId: string,\n request: Request\n): string {\n const url = new URL(request.url);\n switch (componentId) {\n case \"@method\":\n return request.method.toUpperCase();\n case \"@path\":\n return url.pathname;\n case \"@authority\":\n return url.host;\n case \"@scheme\":\n return url.protocol.replace(\":\", \"\");\n case \"@target-uri\":\n return url.href;\n default:\n throw new Error(`Unknown derived component: ${componentId}`);\n }\n}\n\n/**\n * Resolve a component value - derived (`@method`, `@path`, etc.) or\n * regular header name (lowercased).\n */\nfunction resolveComponentValue(componentId: string, request: Request): string {\n if (componentId.startsWith(\"@\")) {\n return resolveDerivedComponent(componentId, request);\n }\n // Regular header component - value from request headers\n return request.headers.get(componentId) ?? \"\";\n}\n\n/**\n * Build the signature base string per RFC 9421 Section 2.5.\n *\n * Each line is `\"component-id\": value`, ending with `\"@signature-params\": <params>`.\n */\nexport function buildSignatureBase(\n components: string[],\n signatureParams: string,\n request: Request\n): string {\n const lines: string[] = [];\n for (const component of components) {\n const value = resolveComponentValue(component, request);\n lines.push(`\"${component}\": ${value}`);\n }\n lines.push(`\"@signature-params\": ${signatureParams}`);\n return lines.join(\"\\n\");\n}\n\n/**\n * Build the signature params string.\n *\n * Format: `(\"@method\" \"@path\" ...);created=<ts>;keyid=\"<id>\"[;expires=<ts>][;nonce=\"<n>\"]`\n */\nexport function buildSignatureParams(\n components: string[],\n params: {\n created: number;\n keyId: string;\n expires?: number;\n nonce?: string;\n algorithm?: string;\n }\n): string {\n const componentList = components.map((c) => `\"${c}\"`).join(\" \");\n let result = `(${componentList});created=${params.created};keyid=\"${params.keyId}\"`;\n if (params.algorithm) {\n result += `;alg=\"${params.algorithm}\"`;\n }\n if (params.expires !== undefined) {\n result += `;expires=${params.expires}`;\n }\n if (params.nonce !== undefined) {\n result += `;nonce=\"${params.nonce}\"`;\n }\n return result;\n}\n\n/**\n * Parse a signature params string from the Signature-Input header.\n *\n * Input: `(\"@method\" \"@path\" \"content-type\");created=1618884473;keyid=\"test-key\"`\n * Returns the component list and key-value parameters.\n */\nexport function parseSignatureParams(input: string): {\n components: string[];\n params: Record<string, string>;\n} {\n // Extract the component list inside parentheses\n const parenMatch = input.match(/^\\(([^)]*)\\)/);\n if (!parenMatch) {\n throw new Error(\"Invalid signature params: missing component list\");\n }\n\n const componentStr = parenMatch[1];\n const components = componentStr\n ? (componentStr.match(/\"([^\"]+)\"/g)?.map((s) => s.slice(1, -1)) ?? [])\n : [];\n\n // Parse params after the closing paren\n const paramStr = input.slice(parenMatch[0].length);\n const params: Record<string, string> = {};\n const paramRegex = /;(\\w+)=(\"([^\"]*)\"|(\\d+))/g;\n let match: RegExpExecArray | null = paramRegex.exec(paramStr);\n while (match !== null) {\n // match[3] is quoted string value, match[4] is unquoted numeric value\n params[match[1]] = match[3] ?? match[4];\n match = paramRegex.exec(paramStr);\n }\n\n return { components, params };\n}\n\n/** Map algorithm identifier to Web Crypto params for import + sign/verify. */\nexport function algorithmToCrypto(alg: string): {\n importAlg: Parameters<typeof crypto.subtle.importKey>[2];\n signAlg: Parameters<typeof crypto.subtle.sign>[0];\n} {\n switch (alg) {\n case \"hmac-sha256\":\n return {\n importAlg: { name: \"HMAC\", hash: \"SHA-256\" },\n signAlg: \"HMAC\",\n };\n case \"rsa-v1_5-sha256\":\n return {\n importAlg: { name: \"RSASSA-PKCS1-v1_5\", hash: \"SHA-256\" },\n signAlg: \"RSASSA-PKCS1-v1_5\",\n };\n case \"rsa-pss-sha512\":\n return {\n importAlg: { name: \"RSA-PSS\", hash: \"SHA-512\" },\n signAlg: { name: \"RSA-PSS\", saltLength: 64 },\n };\n default:\n throw new Error(`Unsupported signature algorithm: ${alg}`);\n }\n}\n\n/**\n * Import key material for signing.\n */\nexport async function importSigningKey(\n algorithm: string,\n secret?: string,\n privateKey?: JsonWebKey\n): Promise<CryptoKey> {\n const { importAlg } = algorithmToCrypto(algorithm);\n\n if (algorithm.startsWith(\"hmac\")) {\n if (!secret) throw new Error(\"HMAC algorithm requires secret\");\n const encoder = new TextEncoder();\n return crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n importAlg,\n false,\n [\"sign\"]\n );\n }\n\n if (!privateKey) throw new Error(\"RSA algorithm requires privateKey\");\n return crypto.subtle.importKey(\"jwk\", privateKey, importAlg, false, [\"sign\"]);\n}\n\n/**\n * Import key material for verification.\n */\nexport async function importVerifyKey(\n algorithm: string,\n secret?: string,\n publicKey?: JsonWebKey\n): Promise<CryptoKey> {\n const { importAlg } = algorithmToCrypto(algorithm);\n\n if (algorithm.startsWith(\"hmac\")) {\n if (!secret) throw new Error(\"HMAC algorithm requires secret\");\n const encoder = new TextEncoder();\n return crypto.subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n importAlg,\n false,\n [\"verify\"]\n );\n }\n\n if (!publicKey) throw new Error(\"RSA algorithm requires publicKey\");\n return crypto.subtle.importKey(\"jwk\", publicKey, importAlg, false, [\n \"verify\",\n ]);\n}\n\n/** Encode bytes to standard base64. */\nexport function toBase64(buffer: ArrayBuffer): string {\n return btoa(String.fromCharCode(...new Uint8Array(buffer)));\n}\n\n/** Decode standard base64 to bytes. */\nexport function fromBase64(str: string): Uint8Array {\n const binary = atob(str);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i);\n }\n return bytes;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,46 @@
1
+ import { g as PolicyConfig, P as Policy } from '../../protocol-2fD3DJrL.js';
2
+ export { clearJwksCache as clearJwsJwksCache } from './crypto.js';
3
+ import 'hono';
4
+ import '../sdk/trace.js';
5
+ import '@vivero/stoma-core';
6
+
7
+ interface JwsConfig extends PolicyConfig {
8
+ /** HMAC secret for verification */
9
+ secret?: string;
10
+ /** JWKS endpoint for RSA verification */
11
+ jwksUrl?: string;
12
+ /** Header containing the JWS. Default: "X-JWS-Signature" */
13
+ headerName?: string;
14
+ /** Where the payload comes from for detached JWS. Default: "embedded" */
15
+ payloadSource?: "embedded" | "body";
16
+ /** Whether to forward the verified payload as a header. Default: false */
17
+ forwardPayload?: boolean;
18
+ /** Header name for forwarded payload. Default: "X-JWS-Payload" */
19
+ forwardHeaderName?: string;
20
+ /** JWKS cache TTL in ms. Default: 300000 */
21
+ jwksCacheTtlMs?: number;
22
+ /** JWKS fetch timeout in milliseconds. Default: 10000 (10 seconds). */
23
+ jwksTimeoutMs?: number;
24
+ }
25
+
26
+ /**
27
+ * Verify JWS compact serialization signatures on requests.
28
+ *
29
+ * The `none` algorithm is always rejected to prevent signature bypass attacks.
30
+ * Config validation (`secret` or `jwksUrl` required) is performed at construction
31
+ * time - a missing config throws immediately, not on first request.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * import { jws } from "@vivero/stoma";
36
+ *
37
+ * // HMAC verification with embedded payload
38
+ * jws({ secret: env.JWS_SECRET });
39
+ *
40
+ * // Detached JWS - payload comes from the request body
41
+ * jws({ secret: env.JWS_SECRET, payloadSource: "body" });
42
+ * ```
43
+ */
44
+ declare const jws: (config?: JwsConfig | undefined) => Policy;
45
+
46
+ export { type JwsConfig, jws };