You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Refactor HMAC function and update SQL examples for clarity and consistency
- Changed function parameters to remove Option types for data and key in the HMAC function.
- Improved SQL documentation and examples for HMAC usage, including clearer descriptions and updated error handling.
- Enhanced test cases for webhook HMAC validation to ensure accurate signature checks and responses.
- Removed obsolete test file for HMAC with null values.
'Creates a unique "signature" for your data using a secret key. This signature proves that the data hasn''t been tampered with and comes from someone who knows the secret.
14
-
15
-
Think of it like a wax seal on a letter - only someone with the right seal (your secret key) can create it, and if someone changes the letter, the seal won''t match anymore.
14
+
'Creates a unique "signature" for some data using a secret key.
15
+
This signature proves that the data hasn''t been tampered with and comes from someone who knows the secret.
16
16
17
17
### What is HMAC used for?
18
18
19
-
**HMAC** (Hash-based Message Authentication Code) is commonly used to:
20
-
- **Verify webhooks**: Check that notifications from services like Shopify, Stripe, or GitHub are genuine
19
+
[**HMAC**](https://en.wikipedia.org/wiki/HMAC) (Hash-based Message Authentication Code) is commonly used to:
20
+
- **Verify webhooks**: Use HMAC to ensure only a given external service can call a given endpoint in your application.
21
+
The service signs their request with a secret key, and you verify the signature before processing the data they sent you.
22
+
Used for instance by [Stripe](https://docs.stripe.com/webhooks?verify=verify-manually), and [Shopify](https://shopify.dev/docs/apps/build/webhooks/subscribe/https#step-2-validate-the-origin-of-your-webhook-to-ensure-its-coming-from-shopify).
21
23
- **Secure API requests**: Prove that an API request comes from an authorized source
22
24
- **Generate secure tokens**: Create temporary access codes for downloads or password resets
23
25
- **Protect data**: Ensure data hasn''t been modified during transmission
@@ -35,98 +37,98 @@ The `sqlpage.hmac` function takes three inputs:
35
37
36
38
It returns a signature string. If someone changes even one letter in your data, the signature will be completely different.
37
39
38
-
### Example 1: Verify Shopify Webhooks
40
+
### Example: Verify a Webhooks signature
39
41
40
-
When Shopify sends you a webhook (like when someone places an order), it includes a signature. Here''s how to verify it''s really from Shopify:
42
+
When Shopify sends you a webhook (like when someone places an order), it includes a signature. Here''s how to verify it''s really from Shopify.
43
+
This supposes you store the secret key in an [environment variable](https://en.wikipedia.org/wiki/Environment_variable) named `WEBHOOK_SECRET`.
41
44
42
45
```sql
43
-
-- Shopify includes the signature in the X-Shopify-Hmac-SHA256 header
44
-
-- and sends the webhook data in the request body
45
-
46
-
-- First, verify the signature - redirect to error page if invalid
47
-
SELECT ''redirect'' as component,
48
-
''/error.sql?message='' || sqlpage.url_encode(''Invalid webhook signature'') as link
SELECT ''redirect'' AS component, ''/error.sql?err=expired'' AS link
92
+
WHERE $expected IS DISTINCT FROM $token OR $expires_at < datetime(''now'');
93
+
94
+
-- serve the file
92
95
```
93
96
94
-
### Important Security Tips
97
+
### Important Security Notes
95
98
96
-
- **Keep your secret key safe**: Store it in environment variables using `sqlpage.environment_variable()`, never hardcode it in your SQL files
97
-
- **Use strong keys**: Your secret should be long and random (at least 32 characters)
98
-
- **The signature is case-sensitive**: Even one wrong letter means the signature won''t match
99
-
- **Algorithms**: Use `sha256` for most cases (it''s the default), or `sha512` for extra security
100
-
- **Output formats**: Use `hex` (default) for most cases, or `base64` when the service expects base64 (like Shopify)
101
-
- **NULL handling**: If your data or key is NULL, the function returns NULL
99
+
- **Keep your secret key safe**: If your secret leaks, anyone can forge signatures and access protected pages
100
+
- **The signature is case-sensitive**: Even a single wrong letter means the signature won''t match
101
+
- **NULL handling**: Always use `IS DISTINCT FROM`, not `=` to check for hmac matches. In SQL `SELECT ''redirect'' as component WHERE sqlpage.hmac(...) != $signature` will not redirect if `$signature` is NULL (the signature is absent). Use `SELECT ''redirect'' as component WHERE sqlpage.hmac(...) IS DISTINCT FROM $signature` instead.
102
102
'
103
103
);
104
104
105
-
INSERT INTO sqlpage_function_parameters (
105
+
INSERT INTO
106
+
sqlpage_function_parameters (
106
107
"function",
107
108
"index",
108
109
"name",
109
110
"description_md",
110
111
"type"
111
112
)
112
-
VALUES (
113
+
VALUES
114
+
(
113
115
'hmac',
114
116
1,
115
117
'data',
116
-
'The input data to compute the HMAC for. Can be any text string.',
118
+
'The input data to compute the HMAC for. Can be any text string. Cannot be NULL.',
117
119
'TEXT'
118
120
),
119
121
(
120
122
'hmac',
121
123
2,
122
124
'key',
123
-
'The secret key used to compute the HMAC. Should be kept confidential.',
125
+
'The secret key used to compute the HMAC. Should be kept confidential. Cannot be NULL.',
124
126
'TEXT'
125
127
),
126
128
(
127
129
'hmac',
128
130
3,
129
131
'algorithm',
130
-
'The hash algorithm and output format. Optional, defaults to `sha256` (hex output). Supported values: `sha256`, `sha256-base64`, `sha512`, `sha512-base64`.',
132
+
'The hash algorithm and output format. Optional, defaults to `sha256` (hex output). Supported values: `sha256`, `sha256-base64`, `sha512`, `sha512-base64`. Defaults to `sha256`.',
0 commit comments