Skip to content

Commit

Permalink
Apply JCS before signature validation (#54)
Browse files Browse the repository at this point in the history
  • Loading branch information
amh4r authored Aug 23, 2024
1 parent fc978db commit 9e60ab4
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 14 deletions.
2 changes: 1 addition & 1 deletion consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ package inngestgo

const (
SDKLanguage = "go"
SDKVersion = "0.5.4"
SDKVersion = "0.7.3"
)
8 changes: 7 additions & 1 deletion handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -774,7 +774,13 @@ func (h *handler) trust(
return
}

w.Header().Add("X-Inngest-Signature", Sign(ctx, time.Now(), []byte(key), byt))
resSig, err := Sign(ctx, time.Now(), []byte(key), byt)
if err != nil {
_ = publicerr.WriteHTTP(w, err)
return
}

w.Header().Add("X-Inngest-Signature", resSig)
w.WriteHeader(200)
_, err = w.Write(byt)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ func TestIntrospection(t *testing.T) {
r := require.New(t)

reqBody := []byte("")
sig := Sign(context.Background(), time.Now(), []byte(testKey), reqBody)
sig, _ := Sign(context.Background(), time.Now(), []byte(testKey), reqBody)
req, err := http.NewRequest(http.MethodGet, server.URL, bytes.NewReader(reqBody))
r.NoError(err)
req.Header.Set("X-Inngest-Signature", sig)
Expand Down Expand Up @@ -531,7 +531,7 @@ func TestIntrospection(t *testing.T) {

reqBody := []byte("")
invalidKey := "deadbeef"
sig := Sign(context.Background(), time.Now(), []byte(invalidKey), reqBody)
sig, _ := Sign(context.Background(), time.Now(), []byte(invalidKey), reqBody)
req, err := http.NewRequest(http.MethodGet, server.URL, bytes.NewReader(reqBody))
r.NoError(err)
req.Header.Set("X-Inngest-Signature", sig)
Expand Down Expand Up @@ -591,7 +591,7 @@ func handlerPost(t *testing.T, url string, r *sdkrequest.Request) *http.Response
t.Helper()

body := marshalRequest(t, r)
sig := Sign(context.Background(), time.Now(), []byte(testKey), body)
sig, _ := Sign(context.Background(), time.Now(), []byte(testKey), body)

req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body))
require.NoError(t, err)
Expand Down
20 changes: 17 additions & 3 deletions signature.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ import (
"regexp"
"strconv"
"time"

"github.com/gowebpki/jcs"
"github.com/inngest/inngest/pkg/logger"
)

var (
Expand All @@ -22,9 +25,17 @@ var (
)

// Sign signs a request body with the given key at the given timestamp.
func Sign(ctx context.Context, at time.Time, key, body []byte) string {
func Sign(ctx context.Context, at time.Time, key, body []byte) (string, error) {
key = normalizeKey(key)

var err error
if len(body) > 0 {
body, err = jcs.Transform(body)
if err != nil {
logger.StdlibLogger(ctx).Warn("failed to canonicalize body", "error", err)
}
}

ts := at.Unix()
if at.IsZero() {
ts = time.Now().Unix()
Expand All @@ -36,7 +47,7 @@ func Sign(ctx context.Context, at time.Time, key, body []byte) string {
// timing attacks.
_, _ = mac.Write([]byte(fmt.Sprintf("%d", ts)))
sig := hex.EncodeToString(mac.Sum(nil))
return fmt.Sprintf("t=%d&s=%s", ts, sig)
return fmt.Sprintf("t=%d&s=%s", ts, sig), nil
}

// validateSignature ensures that the signature for the given body is signed with
Expand All @@ -58,7 +69,10 @@ func validateSignature(ctx context.Context, sig string, key, body []byte) (bool,
return false, ErrExpiredSignature
}

actual := Sign(ctx, ts, key, body)
actual, err := Sign(ctx, ts, key, body)
if err != nil {
return false, err
}
if actual != sig {
return false, ErrInvalidSignature
}
Expand Down
12 changes: 6 additions & 6 deletions signature_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
)

var (
testBody = []byte(`hey! if you're reading this come work with us: [email protected]`)
testBody = []byte(`{"msg": "hey! if you're reading this come work with us: [email protected]"}`)
testKey = "signkey-test-12345678"
testKeyFallback = "signkey-test-00000000"
)
Expand All @@ -23,9 +23,9 @@ func TestSign(t *testing.T) {
keyA := []byte("signkey-test-12345678")
keyB := []byte("signkey-prod-12345678")
keyC := []byte("12345678")
a := Sign(ctx, at, keyA, testBody)
b := Sign(ctx, at, keyB, testBody)
c := Sign(ctx, at, keyC, testBody)
a, _ := Sign(ctx, at, keyA, testBody)
b, _ := Sign(ctx, at, keyB, testBody)
c, _ := Sign(ctx, at, keyC, testBody)
require.Equal(t, a, b)
require.Equal(t, a, c)
})
Expand Down Expand Up @@ -54,7 +54,7 @@ func TestValidateSignature(t *testing.T) {

t.Run("with the wrong key it fails", func(t *testing.T) {
at := time.Now()
sig := Sign(ctx, at, []byte(testKey), testBody)
sig, _ := Sign(ctx, at, []byte(testKey), testBody)

ok, _, err := ValidateSignature(ctx, sig, "signkey-test-lolwtf", "", testBody)
require.False(t, ok)
Expand All @@ -64,7 +64,7 @@ func TestValidateSignature(t *testing.T) {

t.Run("with the same key and within a reasonable time it succeeds", func(t *testing.T) {
at := time.Now().Add(-5 * time.Second)
sig := Sign(ctx, at, []byte(testKey), testBody)
sig, _ := Sign(ctx, at, []byte(testKey), testBody)

ok, _, err := ValidateSignature(ctx, sig, testKey, "", testBody)
require.True(t, ok)
Expand Down

0 comments on commit 9e60ab4

Please sign in to comment.