Skip to content

Commit b645bba

Browse files
Juanita De La CuestaJuanita De La Cuesta
authored andcommitted
Functionality: Add comments and change params to pointers
1 parent 9b244cf commit b645bba

File tree

1 file changed

+53
-13
lines changed

1 file changed

+53
-13
lines changed

signature/signature.go

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ import (
1313
"time"
1414
)
1515

16+
// ValidityPeriod is the time in hours after which a request is descarded
17+
type ValidityPeriod *float64
18+
19+
// StringToTime converts from Unicod Epoch enconded timestamps to time.Time Go objects
1620
func StringToTime(s string) (time.Time, error) {
1721
sec, err := strconv.ParseInt(s, 10, 64)
1822
if err != nil {
@@ -21,31 +25,53 @@ func StringToTime(s string) (time.Time, error) {
2125
return time.Unix(sec, 0), nil
2226
}
2327

24-
func HMACSHA256(message, signingKey []byte) ([]byte, error) {
25-
mac := hmac.New(sha256.New, []byte(signingKey))
28+
// HMACSHA256 generates HMACS enconded hashes using the provided Key and SHA256
29+
// encoding for the message
30+
func HMACSHA256(message, key []byte) ([]byte, error) {
31+
mac := hmac.New(sha256.New, []byte(key))
2632
if _, err := mac.Write(message); err != nil {
2733
return nil, err
2834
}
2935
return mac.Sum(nil), nil
3036
}
3137

38+
// Validator type represents a MessageBird signature validator
3239
type Validator struct {
33-
SigningKey string
34-
Period float64
40+
SigningKey string // Signing Key provided by MessageBird
41+
Period ValidityPeriod // Period in hours for a message to be accepted as real, set to nil to bypass the timestamp validator
3542
Log *log.Logger
36-
LogMesssage string
43+
LogMesssage *string
44+
}
45+
46+
// NewValidator returns a signature validator object
47+
func NewValidator(signingKey string, period float64, log *log.Logger, message *string) *Validator {
48+
return &Validator{
49+
SigningKey: signingKey,
50+
Period: &period,
51+
Log: log,
52+
LogMesssage: message,
53+
}
3754
}
3855

39-
func (v *Validator) ValidTimestamp(ts time.Time) bool {
40-
if v.Period != 0 {
56+
// ValidTimestamp validates if the MessageBird-Request-Timestamp is a valid
57+
// date and if the request is older than the validator Period.
58+
func (v *Validator) ValidTimestamp(ts string) bool {
59+
if v.Period != nil {
4160
now := time.Now()
42-
if diff := now.Sub(ts); diff.Hours() > v.Period {
61+
t, err := StringToTime(ts)
62+
diff := now.Sub(t)
63+
if err != nil || diff.Hours() > *v.Period {
4364
return false
4465
}
4566
}
4667
return true
4768
}
4869

70+
// CalculateSignature calculates the MessageBird-Signature using HMAC_SHA_256
71+
// encoding and the timestamp, query params and body from the request:
72+
// signature = HMAC_SHA_256(
73+
// TIMESTAMP + \n + QUERY_PARAMS + \n + SHA_256_SUM(BODY),
74+
// signing_key)
4975
func (v *Validator) CalculateSignature(ts, qp string, b []byte) ([]byte, error) {
5076
var m bytes.Buffer
5177
bh := sha256.Sum256(b)
@@ -57,24 +83,38 @@ func (v *Validator) CalculateSignature(ts, qp string, b []byte) ([]byte, error)
5783
return s, nil
5884
}
5985

86+
// ValidSignature takes the timestamp, query params and body from the request,
87+
// calculates the expected signature and compares it to the one sent by MessageBird.
6088
func (v *Validator) ValidSignature(ts, qp, rs string, b []byte) bool {
6189
es, _ := v.CalculateSignature(ts, qp, b)
6290
drs, _ := base64.StdEncoding.DecodeString(rs)
6391
return hmac.Equal(drs, es)
6492
}
6593

66-
func (v *Validator) Wrapper(h http.Handler) http.Handler {
94+
func (v *Validator) Error(w http.ResponseWriter, r *http.Request) {
95+
if v.Log != nil {
96+
v.Log.Println(v.LogMesssage, r.Host)
97+
}
98+
http.Error(w, "Request not allowed", http.StatusUnauthorized)
99+
return
100+
}
101+
102+
// Validate is a handler wrapper that takes care of the signature validation of
103+
// incoming requests and rejects them if invalid or pass them on to your handler
104+
// otherwise.
105+
// To use just wrappe your handler with it:
106+
// http.Handle("/path", signature.Validate(handleThing))
107+
func (v *Validator) Validate(h http.Handler) http.Handler {
67108
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
68109
ts := r.Header.Get("MessageBird-Request-Timestamp")
69110
rs := r.Header.Get("MessageBird-Request-Signature")
70111
if ts == "" || rs == "" {
71-
http.Error(w, "Request not allowed", http.StatusUnauthorized)
112+
v.Error(w, r)
72113
return
73114
}
74-
t, _ := StringToTime(ts)
75115
b, _ := ioutil.ReadAll(r.Body)
76-
if v.ValidTimestamp(t) == false || v.ValidSignature(ts, r.URL.RawQuery, rs, b) == false {
77-
http.Error(w, "Request not allowed", http.StatusUnauthorized)
116+
if v.ValidTimestamp(ts) == false || v.ValidSignature(ts, r.URL.RawQuery, rs, b) == false {
117+
v.Error(w, r)
78118
return
79119
}
80120
h.ServeHTTP(w, r)

0 commit comments

Comments
 (0)