Skip to content

Commit df8c687

Browse files
committed
Changes underlying code to seperate some concerns
1 parent 1544375 commit df8c687

File tree

3 files changed

+44
-35
lines changed

3 files changed

+44
-35
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ func main() {
109109
FUNCTIONS
110110

111111
func WebhookVerify(key string, fn http.HandlerFunc) http.HandlerFunc
112-
Public webhook verify function wrapper. Can be used with any framework
113-
tapping into net/http. Simply pass in the secret key for the Shopify app.
114-
Example: `WebhookVerify("abc123", anotherHandler)`.
112+
Public webhook verify wrapper. Can be used with any framework tapping into
113+
net/http. Simply pass in the secret key for the Shopify app. Example:
114+
`WebhookVerify("abc123", anotherHandler)`.
115115

116-
func WebhookVerifyRequest(key string, w http.ResponseWriter, r *http.Request) (ok bool)
116+
func WebhookVerifyRequest(key string, w http.ResponseWriter, r *http.Request) bool
117117
Webhook verify request from HTTP. Returns a usable handler. Pass in the
118118
secret key for the Shopify app and the next handler.`
119119

http_shopify_webhook.go

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,14 @@ import (
99
"net/http"
1010
)
1111

12-
// Public webhook verify function wrapper.
12+
// Public webhook verify wrapper.
1313
// Can be used with any framework tapping into net/http.
1414
// Simply pass in the secret key for the Shopify app.
1515
// Example: `WebhookVerify("abc123", anotherHandler)`.
1616
func WebhookVerify(key string, fn http.HandlerFunc) http.HandlerFunc {
1717
return func(w http.ResponseWriter, r *http.Request) {
1818
// 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 {
2120
fn(w, r)
2221
}
2322
}
@@ -26,39 +25,49 @@ func WebhookVerify(key string, fn http.HandlerFunc) http.HandlerFunc {
2625
// Webhook verify request from HTTP.
2726
// Returns a usable handler.
2827
// 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 {
3029
// HMAC from request headers and the shop.
3130
shmac := r.Header.Get("X-Shopify-Hmac-Sha256")
3231
shop := r.Header.Get("X-Shopify-Shop-Domain")
3332

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+
3445
// Read the body and put it back.
3546
bb, _ := ioutil.ReadAll(r.Body)
3647
r.Body.Close()
3748
r.Body = ioutil.NopCloser(bytes.NewBuffer(bb))
3849

50+
// Create a signature to compare.
51+
lhmac := newSignature(key, bb)
52+
3953
// Verify all is ok.
40-
ok = verifyRequest(key, shop, shmac, bb)
41-
if !ok {
54+
if ok := isValidSignature(lhmac, shmac); !ok {
4255
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.
5556
return false
5657
}
58+
return true
59+
}
5760

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 {
5964
h := hmac.New(sha256.New, []byte(key))
6065
h.Write(bb)
61-
enc := base64.StdEncoding.EncodeToString(h.Sum(nil))
66+
return base64.StdEncoding.EncodeToString(h.Sum(nil))
67+
}
6268

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
6473
}

http_shopify_webhook_test.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,10 @@ func TestVerifyRequest(t *testing.T) {
1313
// Setup a simple body with a matching HMAC.
1414
body := []byte(`{"key":"value"}`)
1515
hmac := "7iASoA8WSbw19M/h+lgrLr2ly/LvgnE9bcLsk9gflvs="
16-
shop := "example.myshopify.com"
1716

18-
if ok := verifyRequest("secret", shop, hmac, body); !ok {
17+
// Create a signature
18+
lhmac := newSignature("secret", body)
19+
if ok := isValidSignature(lhmac, hmac); !ok {
1920
t.Errorf("expected request data to verify")
2021
}
2122
}
@@ -24,17 +25,19 @@ func TestVerifyRequestError(t *testing.T) {
2425
// Setup a simple body with a matching HMAC, but missing shop.
2526
body := []byte(`{"key":"value"}`)
2627
hmac := "ee2012a00f1649bc35f4cfe1fa582b2ebda5cbf2ef82713d6dc2ec93d81f96fb"
27-
shop := ""
2828

29-
if ok := verifyRequest("secret", shop, hmac, body); ok {
29+
// Create a signature
30+
lhmac := newSignature("secret", body)
31+
if ok := isValidSignature(lhmac, hmac); ok {
3032
t.Errorf("expected request data to not verify, but it did")
3133
}
3234

33-
// Now add the shop, but make the HMAC not match.
34-
shop = "example.myshopify.com"
35+
// HMAC which does not match body content.
3536
hmac = "7iASoA8WSbw19M/h+"
3637

37-
if ok := verifyRequest("secret", shop, hmac, body); ok {
38+
// Create a signature
39+
lhmac = newSignature("secret", body)
40+
if ok := isValidSignature(lhmac, hmac); ok {
3841
t.Errorf("expected request data to not verify, but it did")
3942
}
4043
}
@@ -49,7 +52,6 @@ func TestNetHttpSuccess(t *testing.T) {
4952

5053
// Setup the server with our data.
5154
rec, ran := setupServer(key, shop, hmac, body)
52-
5355
if c := rec.Code; c != http.StatusOK {
5456
t.Errorf("expected status code %v got %v", http.StatusOK, c)
5557
}
@@ -69,7 +71,6 @@ func TestNetHttpFailure(t *testing.T) {
6971

7072
// Setup the server with our data.
7173
rec, ran := setupServer(key, shop, hmac, body)
72-
7374
if c := rec.Code; c != http.StatusBadRequest {
7475
t.Errorf("expected status code %v got %v", http.StatusBadRequest, c)
7576
}
@@ -99,6 +100,5 @@ func setupServer(key string, shop string, hmac string, body string) (*httptest.R
99100
// Create the handler and serve with our recorder and request.
100101
h := WebhookVerify(key, nh)
101102
h.ServeHTTP(rec, req)
102-
103103
return rec, ran
104104
}

0 commit comments

Comments
 (0)