Skip to content

Commit add499e

Browse files
Func: Make time validation always and finish documentation
1 parent e2de81e commit add499e

File tree

2 files changed

+35
-33
lines changed

2 files changed

+35
-33
lines changed

signature/signature.go

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,27 @@
11
package signature
22

3+
/*
4+
Package signature implements signature verification for MessageBird webhooks.
5+
6+
To use define a new validator using your MessageBird Signing key. You can use the
7+
ValidRequest method, just pass the request as a parameter:
8+
9+
validator := signature.NewValidator("your signing key")
10+
if err := validator.ValidRequest(r); err != nil {
11+
// handle error
12+
}
13+
14+
Or use the handler as a middleware for your server:
15+
16+
http.Handle("/path", validator.Validate(YourHandler))
17+
18+
It will reject the requests that contain invalid signatures.
19+
The validator uses a 5ms seconds window to accept requests as valid, to change
20+
this value, set the ValidityWindow to the disired duration.
21+
Take into account that the validity window works around the current time:
22+
[now - ValidityWindow/2, now + ValidityWindow/2]
23+
*/
24+
325
import (
426
"bytes"
527
"crypto/hmac"
@@ -18,10 +40,10 @@ const (
1840
sHeader = "MessageBird-Signature"
1941
)
2042

21-
// Window of acceptance for a request, if the time stamp is within this time, it will evaluated as valid
43+
// ValidityWindow defines the time window in which to validate a request.
2244
var ValidityWindow = 5 * time.Second
2345

24-
// StringToTime converts from Unicod Epoch enconded timestamps to time.Time Go objects
46+
// StringToTime converts from Unicod Epoch enconded timestamps to time.Time Go objects.
2547
func stringToTime(s string) (time.Time, error) {
2648
sec, err := strconv.ParseInt(s, 10, 64)
2749
if err != nil {
@@ -31,7 +53,7 @@ func stringToTime(s string) (time.Time, error) {
3153
}
3254

3355
// HMACSHA256 generates HMACS enconded hashes using the provided Key and SHA256
34-
// encoding for the message
56+
// encoding for the message.
3557
func hMACSHA256(message, key []byte) ([]byte, error) {
3658
mac := hmac.New(sha256.New, []byte(key))
3759
if _, err := mac.Write(message); err != nil {
@@ -40,17 +62,15 @@ func hMACSHA256(message, key []byte) ([]byte, error) {
4062
return mac.Sum(nil), nil
4163
}
4264

43-
// Validator type represents a MessageBird signature validator
65+
// Validator type represents a MessageBird signature validator.
4466
type Validator struct {
45-
SigningKey string // Signing Key provided by MessageBird
46-
Period *time.Duration // Period for a message to be accepted as real, set no nil to bypass the time validator
47-
} // Five seconds by default
67+
SigningKey string // Signing Key provided by MessageBird.
68+
}
4869

49-
// NewValidator returns a signature validator object
70+
// NewValidator returns a signature validator object.
5071
func NewValidator(signingKey string) *Validator {
5172
return &Validator{
5273
SigningKey: signingKey,
53-
Period: &ValidityWindow,
5474
}
5575
}
5676

@@ -61,12 +81,8 @@ func (v *Validator) validTimestamp(ts string) bool {
6181
if err != nil {
6282
return false
6383
}
64-
if v.Period == nil {
65-
return true
66-
}
67-
68-
diff := time.Now().Add(*v.Period / 2).Sub(t)
69-
return diff < *v.Period && diff > 0
84+
diff := time.Now().Add(ValidityWindow / 2).Sub(t)
85+
return diff < ValidityWindow && diff > 0
7086
}
7187

7288
// calculateSignature calculates the MessageBird-Signature using HMAC_SHA_256
@@ -100,7 +116,7 @@ func (v *Validator) validSignature(ts, rqp string, b []byte, rs string) bool {
100116
}
101117

102118
// ValidRequest is a method that takes care of the signature validation of
103-
// incoming requests
119+
// incoming requests.
104120
// To use just pass the request:
105121
// signature.Validate(request)
106122
func (v *Validator) ValidRequest(r *http.Request) error {

signature/signature_test.go

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,6 @@ func TestCalculateSignature(t *testing.T) {
7575
}
7676
for _, tt := range cases {
7777
v := NewValidator(tt.sKey)
78-
v.Period = nil
7978
s, err := v.calculateSignature(tt.ts, tt.qp, []byte(tt.b))
8079
if err != nil {
8180
t.Errorf("Error calculating signature: %s, expected: %s", s, tt.es)
@@ -88,56 +87,42 @@ func TestCalculateSignature(t *testing.T) {
8887
}
8988
}
9089
func TestValidTimestamp(t *testing.T) {
91-
var p time.Duration = time.Second * 2
9290
now := time.Now()
9391
nowts := fmt.Sprintf("%d", now.Unix())
9492
var cases = []struct {
9593
name string
9694
ts string
97-
p *time.Duration
9895
e bool
9996
}{
10097
{
10198
name: "Succesful",
10299
ts: nowts,
103-
p: nil,
104100
e: true,
105101
},
106102
{
107103
name: "Empty time stamp",
108104
ts: "",
109-
p: nil,
110105
e: false,
111106
},
112107
{
113108
name: "Invalid time stamp",
114109
ts: "wrongTs",
115-
p: nil,
116110
e: false,
117111
},
118-
{
119-
name: "Succesful with time check",
120-
ts: nowts,
121-
p: &p,
122-
e: true,
123-
},
124112
{
125113
name: "Time stamp 24 hours in the futute",
126114
ts: fmt.Sprintf("%d", now.AddDate(0, 0, 1).Unix()),
127-
p: &p,
128115
e: false,
129116
},
130117
{
131118
name: "Time stamp 24 hours in the past",
132119
ts: fmt.Sprintf("%d", now.AddDate(0, 0, -1).Unix()),
133-
p: &p,
134120
e: false,
135121
},
136122
}
137123

138124
for _, tt := range cases {
139125
v := NewValidator(testKey)
140-
v.Period = tt.p
141126
r := v.validTimestamp(tt.ts)
142127
if r != tt.e {
143128
t.Errorf("Unexpected error validating ts: %s, test case: %s", tt.ts, tt.name)
@@ -182,7 +167,7 @@ func TestValidSignature(t *testing.T) {
182167

183168
for _, tt := range cases {
184169
v := NewValidator(testKey)
185-
v.Period = nil
170+
ValidityWindow = time.Hour * 100000
186171
r := v.validSignature(tt.ts, tt.qp, []byte(tt.b), tt.s)
187172
if r != tt.e {
188173
t.Errorf("Unexpected error validating signature: %s, test case: %s", tt.s, tt.name)
@@ -257,7 +242,8 @@ func TestValidate(t *testing.T) {
257242

258243
for _, tt := range cases {
259244
v := NewValidator(tt.k)
260-
v.Period = nil
245+
testTime, _ := stringToTime(testTs)
246+
ValidityWindow = time.Now().Add(time.Second*1).Sub(testTime) * 2
261247
ts := httptest.NewServer(v.Validate(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
262248
w.WriteHeader(http.StatusOK)
263249
})))

0 commit comments

Comments
 (0)