@@ -9,15 +9,14 @@ import (
9
9
"net/http"
10
10
)
11
11
12
- // Public webhook verify function wrapper.
12
+ // Public webhook verify wrapper.
13
13
// Can be used with any framework tapping into net/http.
14
14
// Simply pass in the secret key for the Shopify app.
15
15
// Example: `WebhookVerify("abc123", anotherHandler)`.
16
16
func WebhookVerify (key string , fn http.HandlerFunc ) http.HandlerFunc {
17
17
return func (w http.ResponseWriter , r * http.Request ) {
18
18
// Verify and if all is well, run the next handler.
19
- ok := WebhookVerifyRequest (key , w , r )
20
- if ok {
19
+ if ok := WebhookVerifyRequest (key , w , r ); ok {
21
20
fn (w , r )
22
21
}
23
22
}
@@ -26,39 +25,49 @@ func WebhookVerify(key string, fn http.HandlerFunc) http.HandlerFunc {
26
25
// Webhook verify request from HTTP.
27
26
// Returns a usable handler.
28
27
// Pass in the secret key for the Shopify app and the next handler.`
29
- func WebhookVerifyRequest (key string , w http.ResponseWriter , r * http.Request ) ( ok bool ) {
28
+ func WebhookVerifyRequest (key string , w http.ResponseWriter , r * http.Request ) bool {
30
29
// HMAC from request headers and the shop.
31
30
shmac := r .Header .Get ("X-Shopify-Hmac-Sha256" )
32
31
shop := r .Header .Get ("X-Shopify-Shop-Domain" )
33
32
33
+ if shop == "" {
34
+ // No shop provided.
35
+ http .Error (w , "Missing shop domain" , http .StatusBadRequest )
36
+ return false
37
+ }
38
+
39
+ if shmac == "" {
40
+ // No HMAC provided.
41
+ http .Error (w , "Missing signature" , http .StatusBadRequest )
42
+ return false
43
+ }
44
+
34
45
// Read the body and put it back.
35
46
bb , _ := ioutil .ReadAll (r .Body )
36
47
r .Body .Close ()
37
48
r .Body = ioutil .NopCloser (bytes .NewBuffer (bb ))
38
49
50
+ // Create a signature to compare.
51
+ lhmac := newSignature (key , bb )
52
+
39
53
// Verify all is ok.
40
- ok = verifyRequest (key , shop , shmac , bb )
41
- if ! ok {
54
+ if ok := isValidSignature (lhmac , shmac ); ! ok {
42
55
http .Error (w , "Invalid webhook signature" , http .StatusBadRequest )
43
- return
44
- }
45
-
46
- return
47
- }
48
-
49
- // Do the actual work.
50
- // Take the request body, the secret key,
51
- // Attempt to reproduce the same HMAC from the request.
52
- func verifyRequest (key string , shop string , shmac string , bb []byte ) bool {
53
- if shop == "" {
54
- // No shop provided.
55
56
return false
56
57
}
58
+ return true
59
+ }
57
60
58
- // Create an hmac of the body with the secret key to compare.
61
+ // Create an HMAC of the body (bb) with the secret key (key).
62
+ // Returns a string.
63
+ func newSignature (key string , bb []byte ) string {
59
64
h := hmac .New (sha256 .New , []byte (key ))
60
65
h .Write (bb )
61
- enc := base64 .StdEncoding .EncodeToString (h .Sum (nil ))
66
+ return base64 .StdEncoding .EncodeToString (h .Sum (nil ))
67
+ }
62
68
63
- return enc == shmac
69
+ // Compares the created HMAC signature with the request's HMAC signature.
70
+ // Returns bool of comparison result.
71
+ func isValidSignature (lhmac string , shmac string ) bool {
72
+ return lhmac == shmac
64
73
}
0 commit comments