@pikku/core 0.12.133 → 0.12.134

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/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 0.12.134
2
+
3
+ ### Patch Changes
4
+
5
+ - 775b369: A webhook source's `verify` now also checks requests without a body. A bodiless request that is signed can dispatch events, such as Google Calendar and Drive notifications, which carry only headers. One that is not signed can still be answered, as before, so handshakes keep working.
6
+
1
7
  ## 0.12.133
2
8
 
3
9
  ### Patch Changes
@@ -70,7 +70,7 @@ const signedWith = async (verify, request, secret, services) => {
70
70
  return value?.startsWith(prefix) ? value.slice(prefix.length) : undefined;
71
71
  };
72
72
  if ('hmac' in verify) {
73
- const { header: name, prefix, algorithm, encoding, secretEncoding } = verify.hmac;
73
+ const { header: name, prefix, algorithm, encoding, secretEncoding, } = verify.hmac;
74
74
  return verifyHmacSignature(secret, header(name, prefix), algorithm, request.body, encoding, secretEncoding);
75
75
  }
76
76
  if ('token' in verify) {
@@ -81,23 +81,30 @@ const signedWith = async (verify, request, secret, services) => {
81
81
  return verifyPublicKeySignature(secret, header(name), request.body, options);
82
82
  };
83
83
  /**
84
- * Whether the request was checked against the source's signing secret. Throws
85
- * when it was checked and failed. A source without `verify` checks in its own
86
- * `receive`, and a request without a body has nothing signed to check.
84
+ * Whether the request was signed with the source's secret. A request with a
85
+ * body is refused when it was not. A request without one — a HEAD probe, a
86
+ * validation token in the query — only comes back unverified, so `receive`
87
+ * can answer it but not dispatch from it. A source without `verify` checks in
88
+ * its own `receive`.
87
89
  */
88
90
  const verifyRequest = async (source, request, services) => {
89
91
  if (!source?.verify)
90
92
  return true;
91
- if (request.body.length === 0)
92
- return false;
93
+ const bodiless = request.body.length === 0;
93
94
  const secret = await services.credentialService?.get(source.credential ?? webhookSecretCredentialName(source.name));
94
95
  if (typeof secret !== 'string' || !secret) {
96
+ if (bodiless)
97
+ return false;
95
98
  throw new UnauthorizedError(`The ${source.name} webhook source has no signing secret`);
96
99
  }
97
- if (!(await signedWith(source.verify, request, secret, services))) {
98
- throw new UnauthorizedError(`Invalid ${source.name} webhook signature`);
99
- }
100
- return true;
100
+ const signed = await signedWith(source.verify, request, secret, services).catch((error) => {
101
+ if (bodiless)
102
+ return false;
103
+ throw error;
104
+ });
105
+ if (signed || bodiless)
106
+ return signed;
107
+ throw new UnauthorizedError(`Invalid ${source.name} webhook signature`);
101
108
  };
102
109
  const validateEvents = async (source, events, logger) => {
103
110
  const valid = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/core",
3
- "version": "0.12.133",
3
+ "version": "0.12.134",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/pikkujs/pikku.git",