Skip to content

Commit e2de81e

Browse files
Func: Make validity period 5m by default
1 parent 3344c72 commit e2de81e

File tree

2 files changed

+38
-39
lines changed

2 files changed

+38
-39
lines changed

signature/signature.go

Lines changed: 24 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,19 @@ import (
77
"encoding/base64"
88
"fmt"
99
"io/ioutil"
10-
"math"
1110
"net/http"
1211
"net/url"
1312
"strconv"
1413
"time"
1514
)
1615

17-
const tsHeader = "MessageBird-Request-Timestamp"
18-
const sHeader = "MessageBird-Signature"
16+
const (
17+
tsHeader = "MessageBird-Request-Timestamp"
18+
sHeader = "MessageBird-Signature"
19+
)
1920

20-
// ValidityPeriod is the time in hours after which a request is descarded
21-
type ValidityPeriod *float64
21+
// Window of acceptance for a request, if the time stamp is within this time, it will evaluated as valid
22+
var ValidityWindow = 5 * time.Second
2223

2324
// StringToTime converts from Unicod Epoch enconded timestamps to time.Time Go objects
2425
func stringToTime(s string) (time.Time, error) {
@@ -42,58 +43,52 @@ func hMACSHA256(message, key []byte) ([]byte, error) {
4243
// Validator type represents a MessageBird signature validator
4344
type Validator struct {
4445
SigningKey string // Signing Key provided by MessageBird
45-
Period ValidityPeriod // Period in hours for a message to be accepted as real, set to nil to bypass the timestamp validator
46-
}
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
4748

4849
// NewValidator returns a signature validator object
49-
func NewValidator(signingKey string, period ValidityPeriod) *Validator {
50+
func NewValidator(signingKey string) *Validator {
5051
return &Validator{
5152
SigningKey: signingKey,
52-
Period: period,
53+
Period: &ValidityWindow,
5354
}
5455
}
5556

56-
// ValidTimestamp validates if the MessageBird-Request-Timestamp is a valid
57+
// validTimestamp validates if the MessageBird-Request-Timestamp is a valid
5758
// date and if the request is older than the validator Period.
58-
func (v *Validator) ValidTimestamp(ts string) bool {
59+
func (v *Validator) validTimestamp(ts string) bool {
5960
t, err := stringToTime(ts)
6061
if err != nil {
6162
return false
6263
}
63-
if v.Period != nil {
64-
now := time.Now()
65-
diff := now.Sub(t)
66-
if math.Abs(diff.Hours()) > *v.Period {
67-
return false
68-
}
64+
if v.Period == nil {
65+
return true
6966
}
70-
return true
67+
68+
diff := time.Now().Add(*v.Period / 2).Sub(t)
69+
return diff < *v.Period && diff > 0
7170
}
7271

73-
// CalculateSignature calculates the MessageBird-Signature using HMAC_SHA_256
72+
// calculateSignature calculates the MessageBird-Signature using HMAC_SHA_256
7473
// encoding and the timestamp, query params and body from the request:
7574
// signature = HMAC_SHA_256(
7675
// TIMESTAMP + \n + QUERY_PARAMS + \n + SHA_256_SUM(BODY),
7776
// signing_key)
78-
func (v *Validator) CalculateSignature(ts, qp string, b []byte) ([]byte, error) {
77+
func (v *Validator) calculateSignature(ts, qp string, b []byte) ([]byte, error) {
7978
var m bytes.Buffer
8079
bh := sha256.Sum256(b)
8180
fmt.Fprintf(&m, "%s\n%s\n%s", ts, qp, bh[:])
82-
s, err := hMACSHA256(m.Bytes(), []byte(v.SigningKey))
83-
if err != nil {
84-
return nil, err
85-
}
86-
return s, nil
81+
return hMACSHA256(m.Bytes(), []byte(v.SigningKey))
8782
}
8883

89-
// ValidSignature takes the timestamp, query params and body from the request,
84+
// validSignature takes the timestamp, query params and body from the request,
9085
// calculates the expected signature and compares it to the one sent by MessageBird.
91-
func (v *Validator) ValidSignature(ts, rqp string, b []byte, rs string) bool {
86+
func (v *Validator) validSignature(ts, rqp string, b []byte, rs string) bool {
9287
uqp, err := url.Parse("?" + rqp)
9388
if err != nil {
9489
return false
9590
}
96-
es, err := v.CalculateSignature(ts, uqp.Query().Encode(), b)
91+
es, err := v.calculateSignature(ts, uqp.Query().Encode(), b)
9792
if err != nil {
9893
return false
9994
}
@@ -115,7 +110,7 @@ func (v *Validator) ValidRequest(r *http.Request) error {
115110
return fmt.Errorf("Unknown host: %s", r.Host)
116111
}
117112
b, _ := ioutil.ReadAll(r.Body)
118-
if v.ValidTimestamp(ts) == false || v.ValidSignature(ts, r.URL.RawQuery, b, rs) == false {
113+
if v.validTimestamp(ts) == false || v.validSignature(ts, r.URL.RawQuery, b, rs) == false {
119114
return fmt.Errorf("Unknown host: %s", r.Host)
120115
}
121116
r.Body = ioutil.NopCloser(bytes.NewBuffer(b))

signature/signature_test.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,9 @@ func TestCalculateSignature(t *testing.T) {
7474
},
7575
}
7676
for _, tt := range cases {
77-
v := NewValidator(tt.sKey, nil)
78-
s, err := v.CalculateSignature(tt.ts, tt.qp, []byte(tt.b))
77+
v := NewValidator(tt.sKey)
78+
v.Period = nil
79+
s, err := v.calculateSignature(tt.ts, tt.qp, []byte(tt.b))
7980
if err != nil {
8081
t.Errorf("Error calculating signature: %s, expected: %s", s, tt.es)
8182
}
@@ -87,13 +88,13 @@ func TestCalculateSignature(t *testing.T) {
8788
}
8889
}
8990
func TestValidTimestamp(t *testing.T) {
90-
var p float64 = 2
91+
var p time.Duration = time.Second * 2
9192
now := time.Now()
9293
nowts := fmt.Sprintf("%d", now.Unix())
9394
var cases = []struct {
9495
name string
9596
ts string
96-
p ValidityPeriod
97+
p *time.Duration
9798
e bool
9899
}{
99100
{
@@ -115,7 +116,7 @@ func TestValidTimestamp(t *testing.T) {
115116
e: false,
116117
},
117118
{
118-
name: "Succesful",
119+
name: "Succesful with time check",
119120
ts: nowts,
120121
p: &p,
121122
e: true,
@@ -135,8 +136,9 @@ func TestValidTimestamp(t *testing.T) {
135136
}
136137

137138
for _, tt := range cases {
138-
v := NewValidator(testKey, tt.p)
139-
r := v.ValidTimestamp(tt.ts)
139+
v := NewValidator(testKey)
140+
v.Period = tt.p
141+
r := v.validTimestamp(tt.ts)
140142
if r != tt.e {
141143
t.Errorf("Unexpected error validating ts: %s, test case: %s", tt.ts, tt.name)
142144
}
@@ -179,8 +181,9 @@ func TestValidSignature(t *testing.T) {
179181
}
180182

181183
for _, tt := range cases {
182-
v := NewValidator(testKey, nil)
183-
r := v.ValidSignature(tt.ts, tt.qp, []byte(tt.b), tt.s)
184+
v := NewValidator(testKey)
185+
v.Period = nil
186+
r := v.validSignature(tt.ts, tt.qp, []byte(tt.b), tt.s)
184187
if r != tt.e {
185188
t.Errorf("Unexpected error validating signature: %s, test case: %s", tt.s, tt.name)
186189
}
@@ -253,7 +256,8 @@ func TestValidate(t *testing.T) {
253256
}
254257

255258
for _, tt := range cases {
256-
v := NewValidator(tt.k, nil)
259+
v := NewValidator(tt.k)
260+
v.Period = nil
257261
ts := httptest.NewServer(v.Validate(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
258262
w.WriteHeader(http.StatusOK)
259263
})))

0 commit comments

Comments
 (0)