@graphql-mesh/hmac-upstream-signature 1.2.7-alpha-20241114122631-5a3a4345bb55e05e6bd057ae38f412d5d33315fd → 1.2.7-alpha-54b3273d0d9033d32f549a6b937921426c35b08b
Sign up to get free protection for your applications and to get access to all the features.
- package/CHANGELOG.md +354 -0
- package/dist/index.cjs +161 -0
- package/dist/index.d.cts +95 -0
- package/dist/index.d.ts +95 -0
- package/dist/index.js +152 -0
- package/package.json +44 -30
- package/cjs/index.js +0 -110
- package/cjs/package.json +0 -1
- package/esm/index.js +0 -102
- package/typings/index.d.cts +0 -19
- package/typings/index.d.ts +0 -19
package/CHANGELOG.md
ADDED
@@ -0,0 +1,354 @@
|
|
1
|
+
# @graphql-mesh/hmac-upstream-signature
|
2
|
+
|
3
|
+
## 1.2.7-alpha-54b3273d0d9033d32f549a6b937921426c35b08b
|
4
|
+
|
5
|
+
### Patch Changes
|
6
|
+
|
7
|
+
- Updated dependencies [[`16fa46b`](https://github.com/graphql-hive/gateway/commit/16fa46b0e31d1fcbfee977fe02efa5e3eabdb150)]:
|
8
|
+
- @graphql-mesh/transport-common@0.7.14-alpha-54b3273d0d9033d32f549a6b937921426c35b08b
|
9
|
+
|
10
|
+
## 1.2.6
|
11
|
+
|
12
|
+
### Patch Changes
|
13
|
+
|
14
|
+
- Updated dependencies
|
15
|
+
[[`eee53b9`](https://github.com/ardatan/graphql-mesh/commit/eee53b9f455653166c39bca627b3261fbefe4eb7)]:
|
16
|
+
- @graphql-mesh/utils@0.102.12
|
17
|
+
- @graphql-mesh/types@0.102.12
|
18
|
+
- @graphql-mesh/transport-common@0.7.13
|
19
|
+
|
20
|
+
## 1.2.5
|
21
|
+
|
22
|
+
### Patch Changes
|
23
|
+
|
24
|
+
- Updated dependencies
|
25
|
+
[[`de41fc2`](https://github.com/ardatan/graphql-mesh/commit/de41fc2932433f8da35b9de9492720e6c8c100af),
|
26
|
+
[`de41fc2`](https://github.com/ardatan/graphql-mesh/commit/de41fc2932433f8da35b9de9492720e6c8c100af),
|
27
|
+
[`de41fc2`](https://github.com/ardatan/graphql-mesh/commit/de41fc2932433f8da35b9de9492720e6c8c100af)]:
|
28
|
+
- @graphql-mesh/transport-common@0.7.12
|
29
|
+
- @graphql-mesh/types@0.102.11
|
30
|
+
- @graphql-mesh/utils@0.102.11
|
31
|
+
|
32
|
+
## 1.2.4
|
33
|
+
|
34
|
+
## 1.2.3
|
35
|
+
|
36
|
+
### Patch Changes
|
37
|
+
|
38
|
+
- Updated dependencies
|
39
|
+
[[`997b81c`](https://github.com/ardatan/graphql-mesh/commit/997b81c8a5d28508057806b4f16eecc5b713cf71),
|
40
|
+
[`997b81c`](https://github.com/ardatan/graphql-mesh/commit/997b81c8a5d28508057806b4f16eecc5b713cf71),
|
41
|
+
[`997b81c`](https://github.com/ardatan/graphql-mesh/commit/997b81c8a5d28508057806b4f16eecc5b713cf71)]:
|
42
|
+
- @graphql-mesh/transport-common@0.7.11
|
43
|
+
- @graphql-mesh/types@0.102.10
|
44
|
+
- @graphql-mesh/utils@0.102.10
|
45
|
+
|
46
|
+
## 1.2.2
|
47
|
+
|
48
|
+
### Patch Changes
|
49
|
+
|
50
|
+
- Updated dependencies
|
51
|
+
[[`fad4d27`](https://github.com/ardatan/graphql-mesh/commit/fad4d27bfebb80a374c2041b86ffab509845effe)]:
|
52
|
+
- @graphql-mesh/utils@0.102.9
|
53
|
+
- @graphql-mesh/types@0.102.9
|
54
|
+
- @graphql-mesh/transport-common@0.7.10
|
55
|
+
|
56
|
+
## 1.2.1
|
57
|
+
|
58
|
+
## 1.2.0
|
59
|
+
|
60
|
+
### Patch Changes
|
61
|
+
|
62
|
+
- Updated dependencies
|
63
|
+
[[`518c42c`](https://github.com/ardatan/graphql-mesh/commit/518c42c5a2bee00e224df95c2beb758a28d1323c),
|
64
|
+
[`518c42c`](https://github.com/ardatan/graphql-mesh/commit/518c42c5a2bee00e224df95c2beb758a28d1323c),
|
65
|
+
[`518c42c`](https://github.com/ardatan/graphql-mesh/commit/518c42c5a2bee00e224df95c2beb758a28d1323c)]:
|
66
|
+
- @graphql-mesh/transport-common@0.7.9
|
67
|
+
- @graphql-mesh/types@0.102.8
|
68
|
+
- @graphql-mesh/utils@0.102.8
|
69
|
+
|
70
|
+
## 1.1.1
|
71
|
+
|
72
|
+
### Patch Changes
|
73
|
+
|
74
|
+
- Updated dependencies
|
75
|
+
[[`50bf472`](https://github.com/ardatan/graphql-mesh/commit/50bf4723657d27dc196d80407bda40c93aa5c9be),
|
76
|
+
[`50bf472`](https://github.com/ardatan/graphql-mesh/commit/50bf4723657d27dc196d80407bda40c93aa5c9be),
|
77
|
+
[`50bf472`](https://github.com/ardatan/graphql-mesh/commit/50bf4723657d27dc196d80407bda40c93aa5c9be)]:
|
78
|
+
- @graphql-mesh/transport-common@0.7.8
|
79
|
+
- @graphql-mesh/types@0.102.7
|
80
|
+
- @graphql-mesh/utils@0.102.7
|
81
|
+
|
82
|
+
## 1.1.0
|
83
|
+
|
84
|
+
## 1.0.5
|
85
|
+
|
86
|
+
### Patch Changes
|
87
|
+
|
88
|
+
- Updated dependencies
|
89
|
+
[[`bf588d3`](https://github.com/ardatan/graphql-mesh/commit/bf588d372c0078378aaa24beea2da794af7949e6)]:
|
90
|
+
- @graphql-mesh/utils@0.102.6
|
91
|
+
- @graphql-mesh/types@0.102.6
|
92
|
+
- @graphql-mesh/transport-common@0.7.7
|
93
|
+
|
94
|
+
## 1.0.4
|
95
|
+
|
96
|
+
## 1.0.3
|
97
|
+
|
98
|
+
## 1.0.2
|
99
|
+
|
100
|
+
## 1.0.1
|
101
|
+
|
102
|
+
## 1.0.0
|
103
|
+
|
104
|
+
## 0.4.4
|
105
|
+
|
106
|
+
## 0.4.3
|
107
|
+
|
108
|
+
## 0.4.2
|
109
|
+
|
110
|
+
## 0.4.1
|
111
|
+
|
112
|
+
## 0.4.0
|
113
|
+
|
114
|
+
### Minor Changes
|
115
|
+
|
116
|
+
- [#7580](https://github.com/ardatan/graphql-mesh/pull/7580)
|
117
|
+
[`75e9f63`](https://github.com/ardatan/graphql-mesh/commit/75e9f63d09514a0af786f909dc8c32ac09a1a849)
|
118
|
+
Thanks [@ardatan](https://github.com/ardatan)! - BREAKING: All types prefixed with `MeshServe`,
|
119
|
+
now are prefixed with `Gateway`. e.g. `MeshServeRuntime` -> `GatewayRuntime`
|
120
|
+
|
121
|
+
Runtime factory is renamed; `createServeRuntime` -> `createGatewayRuntime`
|
122
|
+
|
123
|
+
The expected export name for config files are renamed from `serveConfig` to `gatewayConfig`
|
124
|
+
|
125
|
+
RENAMING:
|
126
|
+
|
127
|
+
You can rename the product, config file name etc by using the following config options;
|
128
|
+
|
129
|
+
For example;
|
130
|
+
|
131
|
+
```ts
|
132
|
+
productName = 'Mesh Gateway';
|
133
|
+
productDescription =
|
134
|
+
'Mesh Gateway is a GraphQL Gateway that can be used to serve a supergraph schema.';
|
135
|
+
productLogo = '<svg>...</svg>';
|
136
|
+
productPackageName = '@graphql-mesh/gateway';
|
137
|
+
```
|
138
|
+
|
139
|
+
### Patch Changes
|
140
|
+
|
141
|
+
- [#7594](https://github.com/ardatan/graphql-mesh/pull/7594)
|
142
|
+
[`9f01438`](https://github.com/ardatan/graphql-mesh/commit/9f01438fbdf327c0a4bfa0cf440d890ec871ffcc)
|
143
|
+
Thanks [@ardatan](https://github.com/ardatan)! - Adding these plugins to serve-runtime by default,
|
144
|
+
and make them configurable through the configuration;
|
145
|
+
|
146
|
+
- `useResponseCache`
|
147
|
+
- `useContentEncoding`
|
148
|
+
- `useDeferStream`
|
149
|
+
- `useExecutionCancellation`
|
150
|
+
- `useUpstreamCancellation`
|
151
|
+
- `useDisableIntrospection`
|
152
|
+
- `useCSRFPrevention`
|
153
|
+
- `useCustomAgent`
|
154
|
+
- `useGenericAuth`
|
155
|
+
- `useHMACUpstreamSignature`
|
156
|
+
- `useWebhooks`
|
157
|
+
|
158
|
+
In addition, the following ones are added to the serve-cli:
|
159
|
+
|
160
|
+
- `useJWT`
|
161
|
+
- `usePrometheus`
|
162
|
+
- `useOpenTelemetry`
|
163
|
+
- `useRateLimit`
|
164
|
+
|
165
|
+
- Updated dependencies
|
166
|
+
[[`3bf14b3`](https://github.com/ardatan/graphql-mesh/commit/3bf14b33ee621cce004a329928b8a04a68218016),
|
167
|
+
[`b7f6ebf`](https://github.com/ardatan/graphql-mesh/commit/b7f6ebfa077957c3a1ecad1fed449e972cb09ae0),
|
168
|
+
[`0a3e52c`](https://github.com/ardatan/graphql-mesh/commit/0a3e52c2ad2941e7c48f0e80706db41644797c2d)]:
|
169
|
+
- @graphql-mesh/utils@0.102.5
|
170
|
+
- @graphql-mesh/types@0.102.5
|
171
|
+
- @graphql-mesh/transport-common@0.7.6
|
172
|
+
|
173
|
+
## 0.3.6
|
174
|
+
|
175
|
+
### Patch Changes
|
176
|
+
|
177
|
+
- Updated dependencies
|
178
|
+
[[`5146df0`](https://github.com/ardatan/graphql-mesh/commit/5146df0fd3313227d5d7df2beb726ca89e13923f)]:
|
179
|
+
- @graphql-mesh/transport-common@0.7.5
|
180
|
+
|
181
|
+
## 0.3.5
|
182
|
+
|
183
|
+
### Patch Changes
|
184
|
+
|
185
|
+
- Updated dependencies
|
186
|
+
[[`edbc074`](https://github.com/ardatan/graphql-mesh/commit/edbc074523ebc86114bb3342f86b7bcd9268d005),
|
187
|
+
[`edbc074`](https://github.com/ardatan/graphql-mesh/commit/edbc074523ebc86114bb3342f86b7bcd9268d005),
|
188
|
+
[`edbc074`](https://github.com/ardatan/graphql-mesh/commit/edbc074523ebc86114bb3342f86b7bcd9268d005)]:
|
189
|
+
- @graphql-mesh/transport-common@0.7.4
|
190
|
+
- @graphql-mesh/types@0.102.4
|
191
|
+
- @graphql-mesh/utils@0.102.4
|
192
|
+
|
193
|
+
## 0.3.4
|
194
|
+
|
195
|
+
### Patch Changes
|
196
|
+
|
197
|
+
- Updated dependencies
|
198
|
+
[[`14ec31f`](https://github.com/ardatan/graphql-mesh/commit/14ec31f95bc06e9a3d06fae387fc40cc534e01f4),
|
199
|
+
[`14ec31f`](https://github.com/ardatan/graphql-mesh/commit/14ec31f95bc06e9a3d06fae387fc40cc534e01f4),
|
200
|
+
[`14ec31f`](https://github.com/ardatan/graphql-mesh/commit/14ec31f95bc06e9a3d06fae387fc40cc534e01f4)]:
|
201
|
+
- @graphql-mesh/transport-common@0.7.3
|
202
|
+
- @graphql-mesh/types@0.102.3
|
203
|
+
- @graphql-mesh/utils@0.102.3
|
204
|
+
|
205
|
+
## 0.3.3
|
206
|
+
|
207
|
+
## 0.3.2
|
208
|
+
|
209
|
+
### Patch Changes
|
210
|
+
|
211
|
+
- Updated dependencies
|
212
|
+
[[`5d95aad`](https://github.com/ardatan/graphql-mesh/commit/5d95aad185448e8e3a004a08e364f98ee9bbee2a)]:
|
213
|
+
- @graphql-mesh/utils@0.102.2
|
214
|
+
- @graphql-mesh/types@0.102.2
|
215
|
+
- @graphql-mesh/transport-common@0.7.2
|
216
|
+
|
217
|
+
## 0.3.1
|
218
|
+
|
219
|
+
### Patch Changes
|
220
|
+
|
221
|
+
- Updated dependencies
|
222
|
+
[[`e49a7e6`](https://github.com/ardatan/graphql-mesh/commit/e49a7e69475b652a53a0f289a44247e8b7ea96de),
|
223
|
+
[`60bfc22`](https://github.com/ardatan/graphql-mesh/commit/60bfc2240108af0a599a66451517a146cace879d)]:
|
224
|
+
- @graphql-mesh/utils@0.102.1
|
225
|
+
- @graphql-mesh/transport-common@0.7.1
|
226
|
+
- @graphql-mesh/types@0.102.1
|
227
|
+
|
228
|
+
## 0.3.0
|
229
|
+
|
230
|
+
### Patch Changes
|
231
|
+
|
232
|
+
- Updated dependencies
|
233
|
+
[[`db41f96`](https://github.com/ardatan/graphql-mesh/commit/db41f96b392de95d5f3aff958df399bf58575373)]:
|
234
|
+
- @graphql-mesh/types@0.102.0
|
235
|
+
- @graphql-mesh/utils@0.102.0
|
236
|
+
- @graphql-mesh/transport-common@0.7.0
|
237
|
+
|
238
|
+
## 0.2.3
|
239
|
+
|
240
|
+
## 0.2.2
|
241
|
+
|
242
|
+
### Patch Changes
|
243
|
+
|
244
|
+
- [#7518](https://github.com/ardatan/graphql-mesh/pull/7518)
|
245
|
+
[`b0cdc83`](https://github.com/ardatan/graphql-mesh/commit/b0cdc839699a1dd90d125289b49b75f703cbb18e)
|
246
|
+
Thanks [@enisdenjo](https://github.com/enisdenjo)! - dependencies updates:
|
247
|
+
- Updated dependency
|
248
|
+
[`@graphql-mesh/transport-common@^0.6.1` ↗︎](https://www.npmjs.com/package/@graphql-mesh/transport-common/v/0.6.1)
|
249
|
+
(from `^0.6.0`, in `dependencies`)
|
250
|
+
|
251
|
+
## 0.2.1
|
252
|
+
|
253
|
+
### Patch Changes
|
254
|
+
|
255
|
+
- Updated dependencies
|
256
|
+
[[`67e1062`](https://github.com/ardatan/graphql-mesh/commit/67e10629c70ec553234c1ffc99af4b89ddb31985)]:
|
257
|
+
- @graphql-mesh/transport-common@0.6.1
|
258
|
+
|
259
|
+
## 0.2.0
|
260
|
+
|
261
|
+
### Patch Changes
|
262
|
+
|
263
|
+
- Updated dependencies
|
264
|
+
[[`d784488`](https://github.com/ardatan/graphql-mesh/commit/d784488dcf04b3b0bf32f386baf8b48e1f20d27e),
|
265
|
+
[`190e9ec`](https://github.com/ardatan/graphql-mesh/commit/190e9ece9bc050a0564f3b5292ab5229e63d40a6),
|
266
|
+
[`d784488`](https://github.com/ardatan/graphql-mesh/commit/d784488dcf04b3b0bf32f386baf8b48e1f20d27e),
|
267
|
+
[`190e9ec`](https://github.com/ardatan/graphql-mesh/commit/190e9ece9bc050a0564f3b5292ab5229e63d40a6),
|
268
|
+
[`d784488`](https://github.com/ardatan/graphql-mesh/commit/d784488dcf04b3b0bf32f386baf8b48e1f20d27e),
|
269
|
+
[`190e9ec`](https://github.com/ardatan/graphql-mesh/commit/190e9ece9bc050a0564f3b5292ab5229e63d40a6),
|
270
|
+
[`d784488`](https://github.com/ardatan/graphql-mesh/commit/d784488dcf04b3b0bf32f386baf8b48e1f20d27e)]:
|
271
|
+
- @graphql-mesh/transport-common@0.6.0
|
272
|
+
- @graphql-mesh/types@0.101.0
|
273
|
+
- @graphql-mesh/utils@0.101.0
|
274
|
+
|
275
|
+
## 0.1.0
|
276
|
+
|
277
|
+
### Patch Changes
|
278
|
+
|
279
|
+
- Updated dependencies
|
280
|
+
[[`c06a048`](https://github.com/ardatan/graphql-mesh/commit/c06a0482e7431683f0b75fde3aebbb97aca00c4c),
|
281
|
+
[`c06a048`](https://github.com/ardatan/graphql-mesh/commit/c06a0482e7431683f0b75fde3aebbb97aca00c4c),
|
282
|
+
[`c06a048`](https://github.com/ardatan/graphql-mesh/commit/c06a0482e7431683f0b75fde3aebbb97aca00c4c),
|
283
|
+
[`a324c5e`](https://github.com/ardatan/graphql-mesh/commit/a324c5ef300c25dcfa265f3457453b50af0b83e7),
|
284
|
+
[`4d1eb28`](https://github.com/ardatan/graphql-mesh/commit/4d1eb285c2b703c5f80473ad0f316004306fac7f),
|
285
|
+
[`a324c5e`](https://github.com/ardatan/graphql-mesh/commit/a324c5ef300c25dcfa265f3457453b50af0b83e7)]:
|
286
|
+
- @graphql-mesh/transport-common@0.5.0
|
287
|
+
- @graphql-mesh/types@0.100.0
|
288
|
+
- @graphql-mesh/utils@0.100.0
|
289
|
+
|
290
|
+
## 0.0.9
|
291
|
+
|
292
|
+
### Patch Changes
|
293
|
+
|
294
|
+
- Updated dependencies
|
295
|
+
[[`a1bfc49`](https://github.com/ardatan/graphql-mesh/commit/a1bfc492ac3378f22b79a51824407e776b496a84)]:
|
296
|
+
- @graphql-mesh/types@0.99.7
|
297
|
+
- @graphql-mesh/utils@0.99.7
|
298
|
+
- @graphql-mesh/transport-common@0.4.7
|
299
|
+
|
300
|
+
## 0.0.8
|
301
|
+
|
302
|
+
### Patch Changes
|
303
|
+
|
304
|
+
- Updated dependencies
|
305
|
+
[[`6c67e77`](https://github.com/ardatan/graphql-mesh/commit/6c67e77d3c308615a733577293ecb6dd55793aeb),
|
306
|
+
[`6c67e77`](https://github.com/ardatan/graphql-mesh/commit/6c67e77d3c308615a733577293ecb6dd55793aeb),
|
307
|
+
[`6c67e77`](https://github.com/ardatan/graphql-mesh/commit/6c67e77d3c308615a733577293ecb6dd55793aeb),
|
308
|
+
[`6c67e77`](https://github.com/ardatan/graphql-mesh/commit/6c67e77d3c308615a733577293ecb6dd55793aeb),
|
309
|
+
[`6c67e77`](https://github.com/ardatan/graphql-mesh/commit/6c67e77d3c308615a733577293ecb6dd55793aeb)]:
|
310
|
+
- @graphql-mesh/transport-common@0.4.6
|
311
|
+
- @graphql-mesh/types@0.99.6
|
312
|
+
- @graphql-mesh/utils@0.99.6
|
313
|
+
|
314
|
+
## 0.0.7
|
315
|
+
|
316
|
+
## 0.0.6
|
317
|
+
|
318
|
+
## 0.0.5
|
319
|
+
|
320
|
+
## 0.0.4
|
321
|
+
|
322
|
+
### Patch Changes
|
323
|
+
|
324
|
+
- Updated dependencies
|
325
|
+
[[`33c23e8`](https://github.com/ardatan/graphql-mesh/commit/33c23e83a60328df806a8adc8d262a0c6de7e5a4)]:
|
326
|
+
- @graphql-mesh/utils@0.99.5
|
327
|
+
- @graphql-mesh/types@0.99.5
|
328
|
+
- @graphql-mesh/transport-common@0.4.5
|
329
|
+
|
330
|
+
## 0.0.3
|
331
|
+
|
332
|
+
### Patch Changes
|
333
|
+
|
334
|
+
- Updated dependencies
|
335
|
+
[[`597e790`](https://github.com/ardatan/graphql-mesh/commit/597e7905e542be06e7f576d8ffde3f94d7b0630b),
|
336
|
+
[`597e790`](https://github.com/ardatan/graphql-mesh/commit/597e7905e542be06e7f576d8ffde3f94d7b0630b)]:
|
337
|
+
- @graphql-mesh/utils@0.99.4
|
338
|
+
- @graphql-mesh/types@0.99.4
|
339
|
+
- @graphql-mesh/transport-common@0.4.4
|
340
|
+
|
341
|
+
## 0.0.2
|
342
|
+
|
343
|
+
### Patch Changes
|
344
|
+
|
345
|
+
- [#7318](https://github.com/ardatan/graphql-mesh/pull/7318)
|
346
|
+
[`f2af8a3`](https://github.com/ardatan/graphql-mesh/commit/f2af8a3ca005c2173b74f2b6e3aa9cf48e38b153)
|
347
|
+
Thanks [@dotansimha](https://github.com/dotansimha)! - Initial commit and introduce a new plugin.
|
348
|
+
|
349
|
+
- Updated dependencies
|
350
|
+
[[`5e5dec5`](https://github.com/ardatan/graphql-mesh/commit/5e5dec51b571df8d23a4379f61fd7fbd7a3df58e),
|
351
|
+
[`5e5dec5`](https://github.com/ardatan/graphql-mesh/commit/5e5dec51b571df8d23a4379f61fd7fbd7a3df58e)]:
|
352
|
+
- @graphql-mesh/utils@0.99.3
|
353
|
+
- @graphql-mesh/types@0.99.3
|
354
|
+
- @graphql-mesh/transport-common@0.4.3
|
package/dist/index.cjs
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
'use strict';
|
2
|
+
|
3
|
+
var transportCommon = require('@graphql-mesh/transport-common');
|
4
|
+
var utils = require('@graphql-mesh/utils');
|
5
|
+
var jsonStableStringify = require('json-stable-stringify');
|
6
|
+
|
7
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
8
|
+
|
9
|
+
var jsonStableStringify__default = /*#__PURE__*/_interopDefault(jsonStableStringify);
|
10
|
+
|
11
|
+
const DEFAULT_EXTENSION_NAME = "hmac-signature";
|
12
|
+
const DEFAULT_SHOULD_SIGN_FN = () => true;
|
13
|
+
const defaultExecutionRequestSerializer = (executionRequest) => jsonStableStringify__default.default({
|
14
|
+
query: transportCommon.defaultPrintFn(executionRequest.document),
|
15
|
+
variables: executionRequest.variables
|
16
|
+
});
|
17
|
+
const defaultParamsSerializer = (params) => jsonStableStringify__default.default({
|
18
|
+
query: params.query,
|
19
|
+
variables: params.variables
|
20
|
+
});
|
21
|
+
function createCryptoKey({
|
22
|
+
textEncoder,
|
23
|
+
crypto,
|
24
|
+
secret,
|
25
|
+
usages
|
26
|
+
}) {
|
27
|
+
return crypto.subtle.importKey(
|
28
|
+
"raw",
|
29
|
+
textEncoder.encode(secret),
|
30
|
+
{ name: "HMAC", hash: "SHA-256" },
|
31
|
+
false,
|
32
|
+
usages
|
33
|
+
);
|
34
|
+
}
|
35
|
+
function useHmacUpstreamSignature(options) {
|
36
|
+
if (!options.secret) {
|
37
|
+
throw new Error(
|
38
|
+
'Property "secret" is required for useHmacUpstreamSignature plugin'
|
39
|
+
);
|
40
|
+
}
|
41
|
+
const shouldSign = options.shouldSign || DEFAULT_SHOULD_SIGN_FN;
|
42
|
+
const extensionName = options.extensionName || DEFAULT_EXTENSION_NAME;
|
43
|
+
const serializeExecutionRequest = options.serializeExecutionRequest || defaultExecutionRequestSerializer;
|
44
|
+
let key$;
|
45
|
+
let fetchAPI;
|
46
|
+
let textEncoder;
|
47
|
+
return {
|
48
|
+
onYogaInit({ yoga }) {
|
49
|
+
fetchAPI = yoga.fetchAPI;
|
50
|
+
},
|
51
|
+
onSubgraphExecute({
|
52
|
+
subgraphName,
|
53
|
+
subgraph,
|
54
|
+
executionRequest,
|
55
|
+
setExecutionRequest,
|
56
|
+
logger
|
57
|
+
}) {
|
58
|
+
logger?.debug(`running shouldSign for subgraph ${subgraphName}`);
|
59
|
+
if (shouldSign({ subgraphName, subgraph, executionRequest })) {
|
60
|
+
logger?.debug(
|
61
|
+
`shouldSign is true for subgraph ${subgraphName}, signing request`
|
62
|
+
);
|
63
|
+
textEncoder ||= new fetchAPI.TextEncoder();
|
64
|
+
key$ ||= createCryptoKey({
|
65
|
+
textEncoder,
|
66
|
+
crypto: fetchAPI.crypto,
|
67
|
+
secret: options.secret,
|
68
|
+
usages: ["sign"]
|
69
|
+
});
|
70
|
+
return utils.mapMaybePromise(key$, async (key) => {
|
71
|
+
key$ = key;
|
72
|
+
const serializedExecutionRequest = serializeExecutionRequest(executionRequest);
|
73
|
+
const encodedContent = textEncoder.encode(serializedExecutionRequest);
|
74
|
+
const signature = await fetchAPI.crypto.subtle.sign(
|
75
|
+
"HMAC",
|
76
|
+
key,
|
77
|
+
encodedContent
|
78
|
+
);
|
79
|
+
const extensionValue = btoa(
|
80
|
+
String.fromCharCode(...new Uint8Array(signature))
|
81
|
+
);
|
82
|
+
logger?.debug(
|
83
|
+
`produced hmac signature for subgraph ${subgraphName}, signature: ${signature}, signed payload: ${serializedExecutionRequest}`
|
84
|
+
);
|
85
|
+
setExecutionRequest({
|
86
|
+
...executionRequest,
|
87
|
+
extensions: {
|
88
|
+
...executionRequest.extensions,
|
89
|
+
[extensionName]: extensionValue
|
90
|
+
}
|
91
|
+
});
|
92
|
+
});
|
93
|
+
} else {
|
94
|
+
logger?.debug(
|
95
|
+
`shouldSign is false for subgraph ${subgraphName}, skipping hmac signature`
|
96
|
+
);
|
97
|
+
}
|
98
|
+
}
|
99
|
+
};
|
100
|
+
}
|
101
|
+
function useHmacSignatureValidation(options) {
|
102
|
+
if (!options.secret) {
|
103
|
+
throw new Error(
|
104
|
+
'Property "secret" is required for useHmacSignatureValidation plugin'
|
105
|
+
);
|
106
|
+
}
|
107
|
+
const extensionName = options.extensionName || DEFAULT_EXTENSION_NAME;
|
108
|
+
let key$;
|
109
|
+
let textEncoder;
|
110
|
+
let logger;
|
111
|
+
const paramsSerializer = options.serializeParams || defaultParamsSerializer;
|
112
|
+
return {
|
113
|
+
onYogaInit({ yoga }) {
|
114
|
+
logger = yoga.logger;
|
115
|
+
},
|
116
|
+
onParams({ params, fetchAPI }) {
|
117
|
+
textEncoder ||= new fetchAPI.TextEncoder();
|
118
|
+
const extension = params.extensions?.[extensionName];
|
119
|
+
if (!extension) {
|
120
|
+
logger.warn(
|
121
|
+
`Missing HMAC signature: extension ${extensionName} not found in request.`
|
122
|
+
);
|
123
|
+
throw new Error(
|
124
|
+
`Missing HMAC signature: extension ${extensionName} not found in request.`
|
125
|
+
);
|
126
|
+
}
|
127
|
+
key$ ||= createCryptoKey({
|
128
|
+
textEncoder,
|
129
|
+
crypto: fetchAPI.crypto,
|
130
|
+
secret: options.secret,
|
131
|
+
usages: ["verify"]
|
132
|
+
});
|
133
|
+
return key$.then(async (key) => {
|
134
|
+
const sigBuf = Uint8Array.from(atob(extension), (c) => c.charCodeAt(0));
|
135
|
+
const serializedParams = paramsSerializer(params);
|
136
|
+
logger.debug(
|
137
|
+
`HMAC signature will be calculate based on serialized params: ${serializedParams}`
|
138
|
+
);
|
139
|
+
const result = await fetchAPI.crypto.subtle.verify(
|
140
|
+
"HMAC",
|
141
|
+
key,
|
142
|
+
sigBuf,
|
143
|
+
textEncoder.encode(serializedParams)
|
144
|
+
);
|
145
|
+
if (!result) {
|
146
|
+
logger.error(
|
147
|
+
`HMAC signature does not match the body content. short circuit request.`
|
148
|
+
);
|
149
|
+
throw new Error(
|
150
|
+
`Invalid HMAC signature: extension ${extensionName} does not match the body content.`
|
151
|
+
);
|
152
|
+
}
|
153
|
+
});
|
154
|
+
}
|
155
|
+
};
|
156
|
+
}
|
157
|
+
|
158
|
+
exports.defaultExecutionRequestSerializer = defaultExecutionRequestSerializer;
|
159
|
+
exports.defaultParamsSerializer = defaultParamsSerializer;
|
160
|
+
exports.useHmacSignatureValidation = useHmacSignatureValidation;
|
161
|
+
exports.useHmacUpstreamSignature = useHmacUpstreamSignature;
|
package/dist/index.d.cts
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
import { ExecutionRequest, Executor, MaybePromise, Maybe } from '@graphql-tools/utils';
|
2
|
+
import { Plugin, YogaInitialContext, GraphQLParams } from 'graphql-yoga';
|
3
|
+
import { TransportEntry } from '@graphql-mesh/transport-common';
|
4
|
+
import { Logger, OnFetchHook, MeshFetch, MeshPubSub, KeyValueCache } from '@graphql-mesh/types';
|
5
|
+
import { GraphQLSchema, ExecutionResult } from 'graphql';
|
6
|
+
|
7
|
+
declare module 'graphql' {
|
8
|
+
interface GraphQLResolveInfo {
|
9
|
+
executionRequest?: ExecutionRequest;
|
10
|
+
}
|
11
|
+
}
|
12
|
+
interface UnifiedGraphPlugin<TContext> {
|
13
|
+
onSubgraphExecute?: OnSubgraphExecuteHook<TContext>;
|
14
|
+
}
|
15
|
+
type OnSubgraphExecuteHook<TContext = any> = (payload: OnSubgraphExecutePayload<TContext>) => MaybePromise<Maybe<OnSubgraphExecuteDoneHook | void>>;
|
16
|
+
interface OnSubgraphExecutePayload<TContext> {
|
17
|
+
subgraph: GraphQLSchema;
|
18
|
+
subgraphName: string;
|
19
|
+
transportEntry?: TransportEntry;
|
20
|
+
executionRequest: ExecutionRequest<any, TContext>;
|
21
|
+
setExecutionRequest(executionRequest: ExecutionRequest): void;
|
22
|
+
executor: Executor;
|
23
|
+
setExecutor(executor: Executor): void;
|
24
|
+
requestId?: string;
|
25
|
+
logger?: Logger;
|
26
|
+
}
|
27
|
+
interface OnSubgraphExecuteDonePayload {
|
28
|
+
result: AsyncIterable<ExecutionResult> | ExecutionResult;
|
29
|
+
setResult(result: AsyncIterable<ExecutionResult> | ExecutionResult): void;
|
30
|
+
}
|
31
|
+
type OnSubgraphExecuteDoneHook = (payload: OnSubgraphExecuteDonePayload) => MaybePromise<Maybe<OnSubgraphExecuteDoneResult | void>>;
|
32
|
+
type OnSubgraphExecuteDoneResultOnNext = (payload: OnSubgraphExecuteDoneOnNextPayload) => MaybePromise<void>;
|
33
|
+
interface OnSubgraphExecuteDoneOnNextPayload {
|
34
|
+
result: ExecutionResult;
|
35
|
+
setResult(result: ExecutionResult): void;
|
36
|
+
}
|
37
|
+
type OnSubgraphExecuteDoneResultOnEnd = () => MaybePromise<void>;
|
38
|
+
type OnSubgraphExecuteDoneResult = {
|
39
|
+
onNext?: OnSubgraphExecuteDoneResultOnNext;
|
40
|
+
onEnd?: OnSubgraphExecuteDoneResultOnEnd;
|
41
|
+
};
|
42
|
+
|
43
|
+
interface GatewayConfigContext {
|
44
|
+
/**
|
45
|
+
* WHATWG compatible Fetch implementation.
|
46
|
+
*/
|
47
|
+
fetch: MeshFetch;
|
48
|
+
/**
|
49
|
+
* The logger to use throught Mesh and it's plugins.
|
50
|
+
*/
|
51
|
+
logger: Logger;
|
52
|
+
/**
|
53
|
+
* Current working directory.
|
54
|
+
*/
|
55
|
+
cwd: string;
|
56
|
+
/**
|
57
|
+
* Event bus for pub/sub.
|
58
|
+
*/
|
59
|
+
pubsub?: MeshPubSub;
|
60
|
+
/**
|
61
|
+
* Cache Storage
|
62
|
+
*/
|
63
|
+
cache?: KeyValueCache;
|
64
|
+
}
|
65
|
+
interface GatewayContext extends GatewayConfigContext, YogaInitialContext {
|
66
|
+
/**
|
67
|
+
* Environment agnostic HTTP headers provided with the request.
|
68
|
+
*/
|
69
|
+
headers: Record<string, string>;
|
70
|
+
/**
|
71
|
+
* Runtime context available within WebSocket connections.
|
72
|
+
*/
|
73
|
+
connectionParams: Record<string, string>;
|
74
|
+
}
|
75
|
+
type GatewayPlugin<TPluginContext extends Record<string, any> = Record<string, any>, TContext extends Record<string, any> = Record<string, any>> = Plugin<Partial<TPluginContext> & GatewayContext & TContext> & UnifiedGraphPlugin<Partial<TPluginContext> & GatewayContext & TContext> & {
|
76
|
+
onFetch?: OnFetchHook<Partial<TPluginContext> & GatewayContext & TContext>;
|
77
|
+
} & Partial<Disposable | AsyncDisposable>;
|
78
|
+
|
79
|
+
type HMACUpstreamSignatureOptions = {
|
80
|
+
secret: string;
|
81
|
+
shouldSign?: (input: Pick<OnSubgraphExecutePayload<{}>, 'subgraph' | 'subgraphName' | 'executionRequest'>) => boolean;
|
82
|
+
extensionName?: string;
|
83
|
+
serializeExecutionRequest?: (executionRequest: ExecutionRequest) => string;
|
84
|
+
};
|
85
|
+
declare const defaultExecutionRequestSerializer: (executionRequest: ExecutionRequest) => string;
|
86
|
+
declare const defaultParamsSerializer: (params: GraphQLParams) => string;
|
87
|
+
declare function useHmacUpstreamSignature(options: HMACUpstreamSignatureOptions): GatewayPlugin;
|
88
|
+
type HMACUpstreamSignatureValidationOptions = {
|
89
|
+
secret: string;
|
90
|
+
extensionName?: string;
|
91
|
+
serializeParams?: (params: GraphQLParams) => string;
|
92
|
+
};
|
93
|
+
declare function useHmacSignatureValidation(options: HMACUpstreamSignatureValidationOptions): Plugin;
|
94
|
+
|
95
|
+
export { type HMACUpstreamSignatureOptions, type HMACUpstreamSignatureValidationOptions, defaultExecutionRequestSerializer, defaultParamsSerializer, useHmacSignatureValidation, useHmacUpstreamSignature };
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
import { ExecutionRequest, Executor, MaybePromise, Maybe } from '@graphql-tools/utils';
|
2
|
+
import { Plugin, YogaInitialContext, GraphQLParams } from 'graphql-yoga';
|
3
|
+
import { TransportEntry } from '@graphql-mesh/transport-common';
|
4
|
+
import { Logger, OnFetchHook, MeshFetch, MeshPubSub, KeyValueCache } from '@graphql-mesh/types';
|
5
|
+
import { GraphQLSchema, ExecutionResult } from 'graphql';
|
6
|
+
|
7
|
+
declare module 'graphql' {
|
8
|
+
interface GraphQLResolveInfo {
|
9
|
+
executionRequest?: ExecutionRequest;
|
10
|
+
}
|
11
|
+
}
|
12
|
+
interface UnifiedGraphPlugin<TContext> {
|
13
|
+
onSubgraphExecute?: OnSubgraphExecuteHook<TContext>;
|
14
|
+
}
|
15
|
+
type OnSubgraphExecuteHook<TContext = any> = (payload: OnSubgraphExecutePayload<TContext>) => MaybePromise<Maybe<OnSubgraphExecuteDoneHook | void>>;
|
16
|
+
interface OnSubgraphExecutePayload<TContext> {
|
17
|
+
subgraph: GraphQLSchema;
|
18
|
+
subgraphName: string;
|
19
|
+
transportEntry?: TransportEntry;
|
20
|
+
executionRequest: ExecutionRequest<any, TContext>;
|
21
|
+
setExecutionRequest(executionRequest: ExecutionRequest): void;
|
22
|
+
executor: Executor;
|
23
|
+
setExecutor(executor: Executor): void;
|
24
|
+
requestId?: string;
|
25
|
+
logger?: Logger;
|
26
|
+
}
|
27
|
+
interface OnSubgraphExecuteDonePayload {
|
28
|
+
result: AsyncIterable<ExecutionResult> | ExecutionResult;
|
29
|
+
setResult(result: AsyncIterable<ExecutionResult> | ExecutionResult): void;
|
30
|
+
}
|
31
|
+
type OnSubgraphExecuteDoneHook = (payload: OnSubgraphExecuteDonePayload) => MaybePromise<Maybe<OnSubgraphExecuteDoneResult | void>>;
|
32
|
+
type OnSubgraphExecuteDoneResultOnNext = (payload: OnSubgraphExecuteDoneOnNextPayload) => MaybePromise<void>;
|
33
|
+
interface OnSubgraphExecuteDoneOnNextPayload {
|
34
|
+
result: ExecutionResult;
|
35
|
+
setResult(result: ExecutionResult): void;
|
36
|
+
}
|
37
|
+
type OnSubgraphExecuteDoneResultOnEnd = () => MaybePromise<void>;
|
38
|
+
type OnSubgraphExecuteDoneResult = {
|
39
|
+
onNext?: OnSubgraphExecuteDoneResultOnNext;
|
40
|
+
onEnd?: OnSubgraphExecuteDoneResultOnEnd;
|
41
|
+
};
|
42
|
+
|
43
|
+
interface GatewayConfigContext {
|
44
|
+
/**
|
45
|
+
* WHATWG compatible Fetch implementation.
|
46
|
+
*/
|
47
|
+
fetch: MeshFetch;
|
48
|
+
/**
|
49
|
+
* The logger to use throught Mesh and it's plugins.
|
50
|
+
*/
|
51
|
+
logger: Logger;
|
52
|
+
/**
|
53
|
+
* Current working directory.
|
54
|
+
*/
|
55
|
+
cwd: string;
|
56
|
+
/**
|
57
|
+
* Event bus for pub/sub.
|
58
|
+
*/
|
59
|
+
pubsub?: MeshPubSub;
|
60
|
+
/**
|
61
|
+
* Cache Storage
|
62
|
+
*/
|
63
|
+
cache?: KeyValueCache;
|
64
|
+
}
|
65
|
+
interface GatewayContext extends GatewayConfigContext, YogaInitialContext {
|
66
|
+
/**
|
67
|
+
* Environment agnostic HTTP headers provided with the request.
|
68
|
+
*/
|
69
|
+
headers: Record<string, string>;
|
70
|
+
/**
|
71
|
+
* Runtime context available within WebSocket connections.
|
72
|
+
*/
|
73
|
+
connectionParams: Record<string, string>;
|
74
|
+
}
|
75
|
+
type GatewayPlugin<TPluginContext extends Record<string, any> = Record<string, any>, TContext extends Record<string, any> = Record<string, any>> = Plugin<Partial<TPluginContext> & GatewayContext & TContext> & UnifiedGraphPlugin<Partial<TPluginContext> & GatewayContext & TContext> & {
|
76
|
+
onFetch?: OnFetchHook<Partial<TPluginContext> & GatewayContext & TContext>;
|
77
|
+
} & Partial<Disposable | AsyncDisposable>;
|
78
|
+
|
79
|
+
type HMACUpstreamSignatureOptions = {
|
80
|
+
secret: string;
|
81
|
+
shouldSign?: (input: Pick<OnSubgraphExecutePayload<{}>, 'subgraph' | 'subgraphName' | 'executionRequest'>) => boolean;
|
82
|
+
extensionName?: string;
|
83
|
+
serializeExecutionRequest?: (executionRequest: ExecutionRequest) => string;
|
84
|
+
};
|
85
|
+
declare const defaultExecutionRequestSerializer: (executionRequest: ExecutionRequest) => string;
|
86
|
+
declare const defaultParamsSerializer: (params: GraphQLParams) => string;
|
87
|
+
declare function useHmacUpstreamSignature(options: HMACUpstreamSignatureOptions): GatewayPlugin;
|
88
|
+
type HMACUpstreamSignatureValidationOptions = {
|
89
|
+
secret: string;
|
90
|
+
extensionName?: string;
|
91
|
+
serializeParams?: (params: GraphQLParams) => string;
|
92
|
+
};
|
93
|
+
declare function useHmacSignatureValidation(options: HMACUpstreamSignatureValidationOptions): Plugin;
|
94
|
+
|
95
|
+
export { type HMACUpstreamSignatureOptions, type HMACUpstreamSignatureValidationOptions, defaultExecutionRequestSerializer, defaultParamsSerializer, useHmacSignatureValidation, useHmacUpstreamSignature };
|
package/dist/index.js
ADDED
@@ -0,0 +1,152 @@
|
|
1
|
+
import { defaultPrintFn } from '@graphql-mesh/transport-common';
|
2
|
+
import { mapMaybePromise } from '@graphql-mesh/utils';
|
3
|
+
import jsonStableStringify from 'json-stable-stringify';
|
4
|
+
|
5
|
+
const DEFAULT_EXTENSION_NAME = "hmac-signature";
|
6
|
+
const DEFAULT_SHOULD_SIGN_FN = () => true;
|
7
|
+
const defaultExecutionRequestSerializer = (executionRequest) => jsonStableStringify({
|
8
|
+
query: defaultPrintFn(executionRequest.document),
|
9
|
+
variables: executionRequest.variables
|
10
|
+
});
|
11
|
+
const defaultParamsSerializer = (params) => jsonStableStringify({
|
12
|
+
query: params.query,
|
13
|
+
variables: params.variables
|
14
|
+
});
|
15
|
+
function createCryptoKey({
|
16
|
+
textEncoder,
|
17
|
+
crypto,
|
18
|
+
secret,
|
19
|
+
usages
|
20
|
+
}) {
|
21
|
+
return crypto.subtle.importKey(
|
22
|
+
"raw",
|
23
|
+
textEncoder.encode(secret),
|
24
|
+
{ name: "HMAC", hash: "SHA-256" },
|
25
|
+
false,
|
26
|
+
usages
|
27
|
+
);
|
28
|
+
}
|
29
|
+
function useHmacUpstreamSignature(options) {
|
30
|
+
if (!options.secret) {
|
31
|
+
throw new Error(
|
32
|
+
'Property "secret" is required for useHmacUpstreamSignature plugin'
|
33
|
+
);
|
34
|
+
}
|
35
|
+
const shouldSign = options.shouldSign || DEFAULT_SHOULD_SIGN_FN;
|
36
|
+
const extensionName = options.extensionName || DEFAULT_EXTENSION_NAME;
|
37
|
+
const serializeExecutionRequest = options.serializeExecutionRequest || defaultExecutionRequestSerializer;
|
38
|
+
let key$;
|
39
|
+
let fetchAPI;
|
40
|
+
let textEncoder;
|
41
|
+
return {
|
42
|
+
onYogaInit({ yoga }) {
|
43
|
+
fetchAPI = yoga.fetchAPI;
|
44
|
+
},
|
45
|
+
onSubgraphExecute({
|
46
|
+
subgraphName,
|
47
|
+
subgraph,
|
48
|
+
executionRequest,
|
49
|
+
setExecutionRequest,
|
50
|
+
logger
|
51
|
+
}) {
|
52
|
+
logger?.debug(`running shouldSign for subgraph ${subgraphName}`);
|
53
|
+
if (shouldSign({ subgraphName, subgraph, executionRequest })) {
|
54
|
+
logger?.debug(
|
55
|
+
`shouldSign is true for subgraph ${subgraphName}, signing request`
|
56
|
+
);
|
57
|
+
textEncoder ||= new fetchAPI.TextEncoder();
|
58
|
+
key$ ||= createCryptoKey({
|
59
|
+
textEncoder,
|
60
|
+
crypto: fetchAPI.crypto,
|
61
|
+
secret: options.secret,
|
62
|
+
usages: ["sign"]
|
63
|
+
});
|
64
|
+
return mapMaybePromise(key$, async (key) => {
|
65
|
+
key$ = key;
|
66
|
+
const serializedExecutionRequest = serializeExecutionRequest(executionRequest);
|
67
|
+
const encodedContent = textEncoder.encode(serializedExecutionRequest);
|
68
|
+
const signature = await fetchAPI.crypto.subtle.sign(
|
69
|
+
"HMAC",
|
70
|
+
key,
|
71
|
+
encodedContent
|
72
|
+
);
|
73
|
+
const extensionValue = btoa(
|
74
|
+
String.fromCharCode(...new Uint8Array(signature))
|
75
|
+
);
|
76
|
+
logger?.debug(
|
77
|
+
`produced hmac signature for subgraph ${subgraphName}, signature: ${signature}, signed payload: ${serializedExecutionRequest}`
|
78
|
+
);
|
79
|
+
setExecutionRequest({
|
80
|
+
...executionRequest,
|
81
|
+
extensions: {
|
82
|
+
...executionRequest.extensions,
|
83
|
+
[extensionName]: extensionValue
|
84
|
+
}
|
85
|
+
});
|
86
|
+
});
|
87
|
+
} else {
|
88
|
+
logger?.debug(
|
89
|
+
`shouldSign is false for subgraph ${subgraphName}, skipping hmac signature`
|
90
|
+
);
|
91
|
+
}
|
92
|
+
}
|
93
|
+
};
|
94
|
+
}
|
95
|
+
function useHmacSignatureValidation(options) {
|
96
|
+
if (!options.secret) {
|
97
|
+
throw new Error(
|
98
|
+
'Property "secret" is required for useHmacSignatureValidation plugin'
|
99
|
+
);
|
100
|
+
}
|
101
|
+
const extensionName = options.extensionName || DEFAULT_EXTENSION_NAME;
|
102
|
+
let key$;
|
103
|
+
let textEncoder;
|
104
|
+
let logger;
|
105
|
+
const paramsSerializer = options.serializeParams || defaultParamsSerializer;
|
106
|
+
return {
|
107
|
+
onYogaInit({ yoga }) {
|
108
|
+
logger = yoga.logger;
|
109
|
+
},
|
110
|
+
onParams({ params, fetchAPI }) {
|
111
|
+
textEncoder ||= new fetchAPI.TextEncoder();
|
112
|
+
const extension = params.extensions?.[extensionName];
|
113
|
+
if (!extension) {
|
114
|
+
logger.warn(
|
115
|
+
`Missing HMAC signature: extension ${extensionName} not found in request.`
|
116
|
+
);
|
117
|
+
throw new Error(
|
118
|
+
`Missing HMAC signature: extension ${extensionName} not found in request.`
|
119
|
+
);
|
120
|
+
}
|
121
|
+
key$ ||= createCryptoKey({
|
122
|
+
textEncoder,
|
123
|
+
crypto: fetchAPI.crypto,
|
124
|
+
secret: options.secret,
|
125
|
+
usages: ["verify"]
|
126
|
+
});
|
127
|
+
return key$.then(async (key) => {
|
128
|
+
const sigBuf = Uint8Array.from(atob(extension), (c) => c.charCodeAt(0));
|
129
|
+
const serializedParams = paramsSerializer(params);
|
130
|
+
logger.debug(
|
131
|
+
`HMAC signature will be calculate based on serialized params: ${serializedParams}`
|
132
|
+
);
|
133
|
+
const result = await fetchAPI.crypto.subtle.verify(
|
134
|
+
"HMAC",
|
135
|
+
key,
|
136
|
+
sigBuf,
|
137
|
+
textEncoder.encode(serializedParams)
|
138
|
+
);
|
139
|
+
if (!result) {
|
140
|
+
logger.error(
|
141
|
+
`HMAC signature does not match the body content. short circuit request.`
|
142
|
+
);
|
143
|
+
throw new Error(
|
144
|
+
`Invalid HMAC signature: extension ${extensionName} does not match the body content.`
|
145
|
+
);
|
146
|
+
}
|
147
|
+
});
|
148
|
+
}
|
149
|
+
};
|
150
|
+
}
|
151
|
+
|
152
|
+
export { defaultExecutionRequestSerializer, defaultParamsSerializer, useHmacSignatureValidation, useHmacUpstreamSignature };
|
package/package.json
CHANGED
@@ -1,48 +1,62 @@
|
|
1
1
|
{
|
2
2
|
"name": "@graphql-mesh/hmac-upstream-signature",
|
3
|
-
"version": "1.2.7-alpha-
|
4
|
-
"
|
5
|
-
"peerDependencies": {
|
6
|
-
"@graphql-mesh/types": "0.102.13-alpha-20241114122631-5a3a4345bb55e05e6bd057ae38f412d5d33315fd",
|
7
|
-
"@graphql-mesh/utils": "0.102.13-alpha-20241114122631-5a3a4345bb55e05e6bd057ae38f412d5d33315fd",
|
8
|
-
"graphql": "*",
|
9
|
-
"tslib": "^2.4.0"
|
10
|
-
},
|
11
|
-
"dependencies": {
|
12
|
-
"@graphql-mesh/transport-common": "^0.7.13",
|
13
|
-
"json-stable-stringify": "^1.1.1"
|
14
|
-
},
|
3
|
+
"version": "1.2.7-alpha-54b3273d0d9033d32f549a6b937921426c35b08b",
|
4
|
+
"type": "module",
|
15
5
|
"repository": {
|
16
6
|
"type": "git",
|
17
|
-
"url": "
|
7
|
+
"url": "git+https://github.com/graphql-hive/gateway.git",
|
18
8
|
"directory": "packages/plugins/hmac-upstream-signature"
|
19
9
|
},
|
10
|
+
"author": {
|
11
|
+
"email": "contact@the-guild.dev",
|
12
|
+
"name": "The Guild",
|
13
|
+
"url": "https://the-guild.dev"
|
14
|
+
},
|
20
15
|
"license": "MIT",
|
21
16
|
"engines": {
|
22
|
-
"node": ">=
|
17
|
+
"node": ">=18.0.0"
|
23
18
|
},
|
24
|
-
"main": "
|
25
|
-
"module": "esm/index.js",
|
26
|
-
"typings": "typings/index.d.ts",
|
27
|
-
"typescript": {
|
28
|
-
"definition": "typings/index.d.ts"
|
29
|
-
},
|
30
|
-
"type": "module",
|
19
|
+
"main": "./dist/index.js",
|
31
20
|
"exports": {
|
32
21
|
".": {
|
33
22
|
"require": {
|
34
|
-
"types": "./
|
35
|
-
"default": "./
|
23
|
+
"types": "./dist/index.d.cts",
|
24
|
+
"default": "./dist/index.cjs"
|
36
25
|
},
|
37
26
|
"import": {
|
38
|
-
"types": "./
|
39
|
-
"default": "./
|
40
|
-
},
|
41
|
-
"default": {
|
42
|
-
"types": "./typings/index.d.ts",
|
43
|
-
"default": "./esm/index.js"
|
27
|
+
"types": "./dist/index.d.ts",
|
28
|
+
"default": "./dist/index.js"
|
44
29
|
}
|
45
30
|
},
|
46
31
|
"./package.json": "./package.json"
|
47
|
-
}
|
32
|
+
},
|
33
|
+
"types": "./dist/index.d.ts",
|
34
|
+
"files": [
|
35
|
+
"dist"
|
36
|
+
],
|
37
|
+
"scripts": {
|
38
|
+
"build": "pkgroll --clean-dist",
|
39
|
+
"prepack": "yarn build"
|
40
|
+
},
|
41
|
+
"peerDependencies": {
|
42
|
+
"graphql": "^15.9.0 || ^16.9.0"
|
43
|
+
},
|
44
|
+
"dependencies": {
|
45
|
+
"@graphql-mesh/cross-helpers": "^0.4.7",
|
46
|
+
"@graphql-mesh/store": "^0.102.12",
|
47
|
+
"@graphql-mesh/transport-common": "^0.7.14-alpha-54b3273d0d9033d32f549a6b937921426c35b08b",
|
48
|
+
"@graphql-mesh/types": "^0.102.12",
|
49
|
+
"@graphql-mesh/utils": "^0.102.12",
|
50
|
+
"@graphql-tools/utils": "^10.5.5",
|
51
|
+
"json-stable-stringify": "^1.1.1",
|
52
|
+
"tslib": "^2.4.0"
|
53
|
+
},
|
54
|
+
"devDependencies": {
|
55
|
+
"@graphql-hive/gateway": "1.5.0-alpha-54b3273d0d9033d32f549a6b937921426c35b08b",
|
56
|
+
"@types/json-stable-stringify": "^1.1.0",
|
57
|
+
"graphql": "^16.9.0",
|
58
|
+
"graphql-yoga": "^5.7.0",
|
59
|
+
"pkgroll": "2.5.1"
|
60
|
+
},
|
61
|
+
"sideEffects": false
|
48
62
|
}
|
package/cjs/index.js
DELETED
@@ -1,110 +0,0 @@
|
|
1
|
-
"use strict";
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.defaultParamsSerializer = exports.defaultExecutionRequestSerializer = void 0;
|
4
|
-
exports.useHmacUpstreamSignature = useHmacUpstreamSignature;
|
5
|
-
exports.useHmacSignatureValidation = useHmacSignatureValidation;
|
6
|
-
const tslib_1 = require("tslib");
|
7
|
-
const json_stable_stringify_1 = tslib_1.__importDefault(require("json-stable-stringify"));
|
8
|
-
const transport_common_1 = require("@graphql-mesh/transport-common");
|
9
|
-
const utils_1 = require("@graphql-mesh/utils");
|
10
|
-
const DEFAULT_EXTENSION_NAME = 'hmac-signature';
|
11
|
-
const DEFAULT_SHOULD_SIGN_FN = () => true;
|
12
|
-
const defaultExecutionRequestSerializer = (executionRequest) => (0, json_stable_stringify_1.default)({
|
13
|
-
query: (0, transport_common_1.defaultPrintFn)(executionRequest.document),
|
14
|
-
variables: executionRequest.variables,
|
15
|
-
});
|
16
|
-
exports.defaultExecutionRequestSerializer = defaultExecutionRequestSerializer;
|
17
|
-
const defaultParamsSerializer = (params) => (0, json_stable_stringify_1.default)({
|
18
|
-
query: params.query,
|
19
|
-
variables: params.variables,
|
20
|
-
});
|
21
|
-
exports.defaultParamsSerializer = defaultParamsSerializer;
|
22
|
-
function createCryptoKey({ textEncoder, crypto, secret, usages, }) {
|
23
|
-
return crypto.subtle.importKey('raw', textEncoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, usages);
|
24
|
-
}
|
25
|
-
function useHmacUpstreamSignature(options) {
|
26
|
-
if (!options.secret) {
|
27
|
-
throw new Error('Property "secret" is required for useHmacUpstreamSignature plugin');
|
28
|
-
}
|
29
|
-
const shouldSign = options.shouldSign || DEFAULT_SHOULD_SIGN_FN;
|
30
|
-
const extensionName = options.extensionName || DEFAULT_EXTENSION_NAME;
|
31
|
-
const serializeExecutionRequest = options.serializeExecutionRequest || exports.defaultExecutionRequestSerializer;
|
32
|
-
let key$;
|
33
|
-
let fetchAPI;
|
34
|
-
let textEncoder;
|
35
|
-
return {
|
36
|
-
onYogaInit({ yoga }) {
|
37
|
-
fetchAPI = yoga.fetchAPI;
|
38
|
-
},
|
39
|
-
onSubgraphExecute({ subgraphName, subgraph, executionRequest, setExecutionRequest, logger }) {
|
40
|
-
logger.debug(`running shouldSign for subgraph ${subgraphName}`);
|
41
|
-
if (shouldSign({ subgraphName, subgraph, executionRequest })) {
|
42
|
-
logger.debug(`shouldSign is true for subgraph ${subgraphName}, signing request`);
|
43
|
-
textEncoder ||= new fetchAPI.TextEncoder();
|
44
|
-
key$ ||= createCryptoKey({
|
45
|
-
textEncoder,
|
46
|
-
crypto: fetchAPI.crypto,
|
47
|
-
secret: options.secret,
|
48
|
-
usages: ['sign'],
|
49
|
-
});
|
50
|
-
return (0, utils_1.mapMaybePromise)(key$, async (key) => {
|
51
|
-
key$ = key;
|
52
|
-
const serializedExecutionRequest = serializeExecutionRequest(executionRequest);
|
53
|
-
const encodedContent = textEncoder.encode(serializedExecutionRequest);
|
54
|
-
const signature = await fetchAPI.crypto.subtle.sign('HMAC', key, encodedContent);
|
55
|
-
const extensionValue = btoa(String.fromCharCode(...new Uint8Array(signature)));
|
56
|
-
logger.debug(`produced hmac signature for subgraph ${subgraphName}, signature: ${signature}, signed payload: ${serializedExecutionRequest}`);
|
57
|
-
setExecutionRequest({
|
58
|
-
...executionRequest,
|
59
|
-
extensions: {
|
60
|
-
...executionRequest.extensions,
|
61
|
-
[extensionName]: extensionValue,
|
62
|
-
},
|
63
|
-
});
|
64
|
-
});
|
65
|
-
}
|
66
|
-
else {
|
67
|
-
logger.debug(`shouldSign is false for subgraph ${subgraphName}, skipping hmac signature`);
|
68
|
-
}
|
69
|
-
},
|
70
|
-
};
|
71
|
-
}
|
72
|
-
function useHmacSignatureValidation(options) {
|
73
|
-
if (!options.secret) {
|
74
|
-
throw new Error('Property "secret" is required for useHmacSignatureValidation plugin');
|
75
|
-
}
|
76
|
-
const extensionName = options.extensionName || DEFAULT_EXTENSION_NAME;
|
77
|
-
let key$;
|
78
|
-
let textEncoder;
|
79
|
-
let logger;
|
80
|
-
const paramsSerializer = options.serializeParams || exports.defaultParamsSerializer;
|
81
|
-
return {
|
82
|
-
onYogaInit({ yoga }) {
|
83
|
-
logger = yoga.logger;
|
84
|
-
},
|
85
|
-
onParams({ params, fetchAPI }) {
|
86
|
-
textEncoder ||= new fetchAPI.TextEncoder();
|
87
|
-
const extension = params.extensions?.[extensionName];
|
88
|
-
if (!extension) {
|
89
|
-
logger.warn(`Missing HMAC signature: extension ${extensionName} not found in request.`);
|
90
|
-
throw new Error(`Missing HMAC signature: extension ${extensionName} not found in request.`);
|
91
|
-
}
|
92
|
-
key$ ||= createCryptoKey({
|
93
|
-
textEncoder,
|
94
|
-
crypto: fetchAPI.crypto,
|
95
|
-
secret: options.secret,
|
96
|
-
usages: ['verify'],
|
97
|
-
});
|
98
|
-
return key$.then(async (key) => {
|
99
|
-
const sigBuf = Uint8Array.from(atob(extension), c => c.charCodeAt(0));
|
100
|
-
const serializedParams = paramsSerializer(params);
|
101
|
-
logger.debug(`HMAC signature will be calculate based on serialized params: ${serializedParams}`);
|
102
|
-
const result = await fetchAPI.crypto.subtle.verify('HMAC', key, sigBuf, textEncoder.encode(serializedParams));
|
103
|
-
if (!result) {
|
104
|
-
logger.error(`HMAC signature does not match the body content. short circuit request.`);
|
105
|
-
throw new Error(`Invalid HMAC signature: extension ${extensionName} does not match the body content.`);
|
106
|
-
}
|
107
|
-
});
|
108
|
-
},
|
109
|
-
};
|
110
|
-
}
|
package/cjs/package.json
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"type":"commonjs"}
|
package/esm/index.js
DELETED
@@ -1,102 +0,0 @@
|
|
1
|
-
import jsonStableStringify from 'json-stable-stringify';
|
2
|
-
import { defaultPrintFn } from '@graphql-mesh/transport-common';
|
3
|
-
import { mapMaybePromise } from '@graphql-mesh/utils';
|
4
|
-
const DEFAULT_EXTENSION_NAME = 'hmac-signature';
|
5
|
-
const DEFAULT_SHOULD_SIGN_FN = () => true;
|
6
|
-
export const defaultExecutionRequestSerializer = (executionRequest) => jsonStableStringify({
|
7
|
-
query: defaultPrintFn(executionRequest.document),
|
8
|
-
variables: executionRequest.variables,
|
9
|
-
});
|
10
|
-
export const defaultParamsSerializer = (params) => jsonStableStringify({
|
11
|
-
query: params.query,
|
12
|
-
variables: params.variables,
|
13
|
-
});
|
14
|
-
function createCryptoKey({ textEncoder, crypto, secret, usages, }) {
|
15
|
-
return crypto.subtle.importKey('raw', textEncoder.encode(secret), { name: 'HMAC', hash: 'SHA-256' }, false, usages);
|
16
|
-
}
|
17
|
-
export function useHmacUpstreamSignature(options) {
|
18
|
-
if (!options.secret) {
|
19
|
-
throw new Error('Property "secret" is required for useHmacUpstreamSignature plugin');
|
20
|
-
}
|
21
|
-
const shouldSign = options.shouldSign || DEFAULT_SHOULD_SIGN_FN;
|
22
|
-
const extensionName = options.extensionName || DEFAULT_EXTENSION_NAME;
|
23
|
-
const serializeExecutionRequest = options.serializeExecutionRequest || defaultExecutionRequestSerializer;
|
24
|
-
let key$;
|
25
|
-
let fetchAPI;
|
26
|
-
let textEncoder;
|
27
|
-
return {
|
28
|
-
onYogaInit({ yoga }) {
|
29
|
-
fetchAPI = yoga.fetchAPI;
|
30
|
-
},
|
31
|
-
onSubgraphExecute({ subgraphName, subgraph, executionRequest, setExecutionRequest, logger }) {
|
32
|
-
logger.debug(`running shouldSign for subgraph ${subgraphName}`);
|
33
|
-
if (shouldSign({ subgraphName, subgraph, executionRequest })) {
|
34
|
-
logger.debug(`shouldSign is true for subgraph ${subgraphName}, signing request`);
|
35
|
-
textEncoder ||= new fetchAPI.TextEncoder();
|
36
|
-
key$ ||= createCryptoKey({
|
37
|
-
textEncoder,
|
38
|
-
crypto: fetchAPI.crypto,
|
39
|
-
secret: options.secret,
|
40
|
-
usages: ['sign'],
|
41
|
-
});
|
42
|
-
return mapMaybePromise(key$, async (key) => {
|
43
|
-
key$ = key;
|
44
|
-
const serializedExecutionRequest = serializeExecutionRequest(executionRequest);
|
45
|
-
const encodedContent = textEncoder.encode(serializedExecutionRequest);
|
46
|
-
const signature = await fetchAPI.crypto.subtle.sign('HMAC', key, encodedContent);
|
47
|
-
const extensionValue = btoa(String.fromCharCode(...new Uint8Array(signature)));
|
48
|
-
logger.debug(`produced hmac signature for subgraph ${subgraphName}, signature: ${signature}, signed payload: ${serializedExecutionRequest}`);
|
49
|
-
setExecutionRequest({
|
50
|
-
...executionRequest,
|
51
|
-
extensions: {
|
52
|
-
...executionRequest.extensions,
|
53
|
-
[extensionName]: extensionValue,
|
54
|
-
},
|
55
|
-
});
|
56
|
-
});
|
57
|
-
}
|
58
|
-
else {
|
59
|
-
logger.debug(`shouldSign is false for subgraph ${subgraphName}, skipping hmac signature`);
|
60
|
-
}
|
61
|
-
},
|
62
|
-
};
|
63
|
-
}
|
64
|
-
export function useHmacSignatureValidation(options) {
|
65
|
-
if (!options.secret) {
|
66
|
-
throw new Error('Property "secret" is required for useHmacSignatureValidation plugin');
|
67
|
-
}
|
68
|
-
const extensionName = options.extensionName || DEFAULT_EXTENSION_NAME;
|
69
|
-
let key$;
|
70
|
-
let textEncoder;
|
71
|
-
let logger;
|
72
|
-
const paramsSerializer = options.serializeParams || defaultParamsSerializer;
|
73
|
-
return {
|
74
|
-
onYogaInit({ yoga }) {
|
75
|
-
logger = yoga.logger;
|
76
|
-
},
|
77
|
-
onParams({ params, fetchAPI }) {
|
78
|
-
textEncoder ||= new fetchAPI.TextEncoder();
|
79
|
-
const extension = params.extensions?.[extensionName];
|
80
|
-
if (!extension) {
|
81
|
-
logger.warn(`Missing HMAC signature: extension ${extensionName} not found in request.`);
|
82
|
-
throw new Error(`Missing HMAC signature: extension ${extensionName} not found in request.`);
|
83
|
-
}
|
84
|
-
key$ ||= createCryptoKey({
|
85
|
-
textEncoder,
|
86
|
-
crypto: fetchAPI.crypto,
|
87
|
-
secret: options.secret,
|
88
|
-
usages: ['verify'],
|
89
|
-
});
|
90
|
-
return key$.then(async (key) => {
|
91
|
-
const sigBuf = Uint8Array.from(atob(extension), c => c.charCodeAt(0));
|
92
|
-
const serializedParams = paramsSerializer(params);
|
93
|
-
logger.debug(`HMAC signature will be calculate based on serialized params: ${serializedParams}`);
|
94
|
-
const result = await fetchAPI.crypto.subtle.verify('HMAC', key, sigBuf, textEncoder.encode(serializedParams));
|
95
|
-
if (!result) {
|
96
|
-
logger.error(`HMAC signature does not match the body content. short circuit request.`);
|
97
|
-
throw new Error(`Invalid HMAC signature: extension ${extensionName} does not match the body content.`);
|
98
|
-
}
|
99
|
-
});
|
100
|
-
},
|
101
|
-
};
|
102
|
-
}
|
package/typings/index.d.cts
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
import type { GraphQLParams, Plugin as YogaPlugin } from 'graphql-yoga';
|
2
|
-
import type { GatewayPlugin } from '@graphql-hive/gateway';
|
3
|
-
import type { OnSubgraphExecutePayload } from '@graphql-mesh/fusion-runtime';
|
4
|
-
import type { ExecutionRequest } from '@graphql-tools/utils';
|
5
|
-
export type HMACUpstreamSignatureOptions = {
|
6
|
-
secret: string;
|
7
|
-
shouldSign?: (input: Pick<OnSubgraphExecutePayload<{}>, 'subgraph' | 'subgraphName' | 'executionRequest'>) => boolean;
|
8
|
-
extensionName?: string;
|
9
|
-
serializeExecutionRequest?: (executionRequest: ExecutionRequest) => string;
|
10
|
-
};
|
11
|
-
export declare const defaultExecutionRequestSerializer: (executionRequest: ExecutionRequest) => any;
|
12
|
-
export declare const defaultParamsSerializer: (params: GraphQLParams) => any;
|
13
|
-
export declare function useHmacUpstreamSignature(options: HMACUpstreamSignatureOptions): GatewayPlugin;
|
14
|
-
export type HMACUpstreamSignatureValidationOptions = {
|
15
|
-
secret: string;
|
16
|
-
extensionName?: string;
|
17
|
-
serializeParams?: (params: GraphQLParams) => string;
|
18
|
-
};
|
19
|
-
export declare function useHmacSignatureValidation(options: HMACUpstreamSignatureValidationOptions): YogaPlugin;
|
package/typings/index.d.ts
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
import type { GraphQLParams, Plugin as YogaPlugin } from 'graphql-yoga';
|
2
|
-
import type { GatewayPlugin } from '@graphql-hive/gateway';
|
3
|
-
import type { OnSubgraphExecutePayload } from '@graphql-mesh/fusion-runtime';
|
4
|
-
import type { ExecutionRequest } from '@graphql-tools/utils';
|
5
|
-
export type HMACUpstreamSignatureOptions = {
|
6
|
-
secret: string;
|
7
|
-
shouldSign?: (input: Pick<OnSubgraphExecutePayload<{}>, 'subgraph' | 'subgraphName' | 'executionRequest'>) => boolean;
|
8
|
-
extensionName?: string;
|
9
|
-
serializeExecutionRequest?: (executionRequest: ExecutionRequest) => string;
|
10
|
-
};
|
11
|
-
export declare const defaultExecutionRequestSerializer: (executionRequest: ExecutionRequest) => any;
|
12
|
-
export declare const defaultParamsSerializer: (params: GraphQLParams) => any;
|
13
|
-
export declare function useHmacUpstreamSignature(options: HMACUpstreamSignatureOptions): GatewayPlugin;
|
14
|
-
export type HMACUpstreamSignatureValidationOptions = {
|
15
|
-
secret: string;
|
16
|
-
extensionName?: string;
|
17
|
-
serializeParams?: (params: GraphQLParams) => string;
|
18
|
-
};
|
19
|
-
export declare function useHmacSignatureValidation(options: HMACUpstreamSignatureValidationOptions): YogaPlugin;
|