-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathwebhook.go
68 lines (55 loc) · 1.49 KB
/
webhook.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package elation
import (
"bytes"
"crypto/ed25519"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
)
const (
WebhookSignatureHeader = "El8-Ed25519-Signature"
)
var ErrPublicKeyLength = errors.New("incorrect length of public key")
type WebhookEventAction string
const (
WebhookEventActionSaved WebhookEventAction = "saved"
WebhookEventActionDeleted WebhookEventAction = "deleted"
)
func (a WebhookEventAction) String() string {
return string(a)
}
type Event struct {
Data json.RawMessage `json:"data"`
Action WebhookEventAction `json:"action"`
EventID int64 `json:"event_id"`
ApplicationID string `json:"application_id"`
Resource Resource `json:"resource"`
}
func VerifyWebhook(r *http.Request, publicKey []byte) (*Event, error) {
if len(publicKey) != ed25519.PublicKeySize {
return nil, ErrPublicKeyLength
}
sig, err := base64.StdEncoding.DecodeString(r.Header.Get(WebhookSignatureHeader))
if err != nil {
return nil, fmt.Errorf("decoding Ed25519 signature: %w", err)
}
body, err := io.ReadAll(r.Body)
if err != nil {
return nil, fmt.Errorf("reading request body: %w", err)
}
//nolint
_ = r.Body.Close()
r.Body = io.NopCloser(bytes.NewBuffer(body))
if !ed25519.Verify(publicKey, body, sig) {
return nil, errors.New("verifying signature")
}
event := &Event{}
err = json.Unmarshal(body, event)
if err != nil {
return nil, fmt.Errorf("unmarshaling body: %w", err)
}
return event, nil
}