Skip to content

Commit d82a475

Browse files
committed
Adds more tests for missing headers
1 parent df8c687 commit d82a475

File tree

2 files changed

+76
-13
lines changed

2 files changed

+76
-13
lines changed

http_shopify_webhook.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,19 @@ import (
99
"net/http"
1010
)
1111

12+
// HTTP errors.
13+
const (
14+
errMissingSignature = "Missing signature from request"
15+
errMissingShop = "Missing shop from request"
16+
errSignature = "Invalid webhook signature"
17+
)
18+
19+
// HTTP headers.
20+
const (
21+
headerHmac = "X-Shopify-Hmac-Sha256"
22+
headerShop = "X-Shopify-Shop-Domain"
23+
)
24+
1225
// Public webhook verify wrapper.
1326
// Can be used with any framework tapping into net/http.
1427
// Simply pass in the secret key for the Shopify app.
@@ -27,18 +40,18 @@ func WebhookVerify(key string, fn http.HandlerFunc) http.HandlerFunc {
2740
// Pass in the secret key for the Shopify app and the next handler.`
2841
func WebhookVerifyRequest(key string, w http.ResponseWriter, r *http.Request) bool {
2942
// HMAC from request headers and the shop.
30-
shmac := r.Header.Get("X-Shopify-Hmac-Sha256")
31-
shop := r.Header.Get("X-Shopify-Shop-Domain")
43+
shmac := r.Header.Get(headerHmac)
44+
shop := r.Header.Get(headerShop)
3245

3346
if shop == "" {
3447
// No shop provided.
35-
http.Error(w, "Missing shop domain", http.StatusBadRequest)
48+
httpError(errMissingShop, http.StatusBadRequest, w)
3649
return false
3750
}
3851

3952
if shmac == "" {
4053
// No HMAC provided.
41-
http.Error(w, "Missing signature", http.StatusBadRequest)
54+
httpError(errMissingSignature, http.StatusBadRequest, w)
4255
return false
4356
}
4457

@@ -52,7 +65,7 @@ func WebhookVerifyRequest(key string, w http.ResponseWriter, r *http.Request) bo
5265

5366
// Verify all is ok.
5467
if ok := isValidSignature(lhmac, shmac); !ok {
55-
http.Error(w, "Invalid webhook signature", http.StatusBadRequest)
68+
httpError(errSignature, http.StatusBadRequest, w)
5669
return false
5770
}
5871
return true
@@ -71,3 +84,8 @@ func newSignature(key string, bb []byte) string {
7184
func isValidSignature(lhmac string, shmac string) bool {
7285
return lhmac == shmac
7386
}
87+
88+
// Common place to issue an error to the response writer.
89+
func httpError(msg string, code int, w http.ResponseWriter) {
90+
http.Error(w, msg, code)
91+
}

http_shopify_webhook_test.go

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,24 @@ import (
55
"fmt"
66
"net/http"
77
"net/http/httptest"
8+
"strings"
89
"testing"
910
)
1011

1112
// Test base verification function works.
12-
func TestVerifyRequest(t *testing.T) {
13+
func TestIsValidSignatureSuccess(t *testing.T) {
1314
// Setup a simple body with a matching HMAC.
1415
body := []byte(`{"key":"value"}`)
1516
hmac := "7iASoA8WSbw19M/h+lgrLr2ly/LvgnE9bcLsk9gflvs="
1617

1718
// Create a signature
1819
lhmac := newSignature("secret", body)
1920
if ok := isValidSignature(lhmac, hmac); !ok {
20-
t.Errorf("expected request data to verify")
21+
t.Error("expected request data to verify")
2122
}
2223
}
2324

24-
func TestVerifyRequestError(t *testing.T) {
25+
func TestIsValidSignatureFailure(t *testing.T) {
2526
// Setup a simple body with a matching HMAC, but missing shop.
2627
body := []byte(`{"key":"value"}`)
2728
hmac := "ee2012a00f1649bc35f4cfe1fa582b2ebda5cbf2ef82713d6dc2ec93d81f96fb"
@@ -38,7 +39,7 @@ func TestVerifyRequestError(t *testing.T) {
3839
// Create a signature
3940
lhmac = newSignature("secret", body)
4041
if ok := isValidSignature(lhmac, hmac); ok {
41-
t.Errorf("expected request data to not verify, but it did")
42+
t.Error("expected request data to not verify, but it did")
4243
}
4344
}
4445

@@ -53,11 +54,11 @@ func TestNetHttpSuccess(t *testing.T) {
5354
// Setup the server with our data.
5455
rec, ran := setupServer(key, shop, hmac, body)
5556
if c := rec.Code; c != http.StatusOK {
56-
t.Errorf("expected status code %v got %v", http.StatusOK, c)
57+
t.Errorf("expected status code %d got %v", http.StatusOK, c)
5758
}
5859

5960
if !ran {
60-
t.Errorf("expected next handler to run but did not")
61+
t.Error("expected next handler to run but did not")
6162
}
6263
}
6364

@@ -72,11 +73,55 @@ func TestNetHttpFailure(t *testing.T) {
7273
// Setup the server with our data.
7374
rec, ran := setupServer(key, shop, hmac, body)
7475
if c := rec.Code; c != http.StatusBadRequest {
75-
t.Errorf("expected status code %v got %v", http.StatusBadRequest, c)
76+
t.Errorf("expected status code %d got %v", http.StatusBadRequest, c)
77+
}
78+
79+
if ran == true {
80+
t.Error("expected next handler to not run but it did")
81+
}
82+
}
83+
84+
// Test for missing HMAC header from request.
85+
func TestMissingHeaderHMAC(t *testing.T) {
86+
// Set our data.
87+
key := "secret"
88+
body := `{"key":"value"}`
89+
shop := "example.myshopify.com"
90+
91+
// Setup the server with our data. No shop.
92+
rec, ran := setupServer(key, shop, "", body)
93+
if c := rec.Code; c != http.StatusBadRequest {
94+
t.Errorf("expected status code %d got %v", http.StatusBadRequest, c)
95+
}
96+
97+
if b := rec.Body; !strings.Contains(b.String(), errMissingSignature) {
98+
t.Errorf("expected '%s' body got '%v'", errMissingSignature, b)
99+
}
100+
101+
if ran == true {
102+
t.Error("expected next handler to not run but it did")
103+
}
104+
}
105+
106+
// Test for missing shop header from request.
107+
func TestMissingHeaderShop(t *testing.T) {
108+
// Set our data.
109+
key := "secret"
110+
body := `{"key":"value"}`
111+
hmac := "ee2012a00f1649bc35f"
112+
113+
// Setup the server with our data. No shop.
114+
rec, ran := setupServer(key, "", hmac, body)
115+
if c := rec.Code; c != http.StatusBadRequest {
116+
t.Errorf("expected status code %d got %v", http.StatusBadRequest, c)
117+
}
118+
119+
if b := rec.Body; !strings.Contains(b.String(), errMissingShop) {
120+
t.Errorf("expected '%s' body got '%v'", errMissingShop, b)
76121
}
77122

78123
if ran == true {
79-
t.Errorf("expected next handler to not run but it did")
124+
t.Error("expected next handler to not run but it did")
80125
}
81126
}
82127

0 commit comments

Comments
 (0)