diff --git a/client.go b/client.go index 6b10b49..42f9788 100644 --- a/client.go +++ b/client.go @@ -27,6 +27,7 @@ type client struct { logger *logrus.Logger baseURL string token string + secret string } // ClientOption is a function that configures a Client. @@ -46,10 +47,11 @@ func WithLogger(l *logrus.Logger) ClientOption { } } -func NewClient(baseURL, token string, options ...ClientOption) *client { +func NewClient(baseURL, token, secret string, options ...ClientOption) *client { c := &client{ baseURL: strings.TrimSuffix(baseURL, "/"), token: token, + secret: secret, } c.httpClient = http.DefaultClient @@ -89,6 +91,7 @@ func (c *client) newRequest(ctx context.Context, method, url string, body interf } req.Header.Set("X-AUTH-CLIENT", c.token) + req.Header.Set("X-HMAC-SIGNATURE", SignPayload(c.secret, string(b))) return NewRequest(req), nil } diff --git a/session_test.go b/session_test.go index 00aafa0..a93118d 100644 --- a/session_test.go +++ b/session_test.go @@ -28,7 +28,7 @@ func TestCreateSession(t *testing.T) { logger, hook := logrustest.NewNullLogger() logger.SetLevel(logrus.DebugLevel) - client := veriff.NewClient("https://a.b", "token", veriff.WithHTTPClient(mockHttpClient), veriff.WithLogger(logger)) + client := veriff.NewClient("https://a.b", "token", "secret", veriff.WithHTTPClient(mockHttpClient), veriff.WithLogger(logger)) resp := &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader(veriffCreateSessionSuccess))} mockHttpClient.On("Do", mock.AnythingOfType("*http.Request")).Return(resp, nil).Once() @@ -48,7 +48,7 @@ func TestCreateSession(t *testing.T) { func TestCreateSession_RequestErr(t *testing.T) { mockHttpClient := veriff.NewMockHttpClient(t) - client := veriff.NewClient("https://a.b", "token", veriff.WithHTTPClient(mockHttpClient)) + client := veriff.NewClient("https://a.b", "token", "secret", veriff.WithHTTPClient(mockHttpClient)) _, err := client.CreateSession(nil, veriff.CreateSessionPayload{}) //lint:ignore SA1012 testing failure require.Error(t, err) @@ -57,7 +57,7 @@ func TestCreateSession_RequestErr(t *testing.T) { func TestSessionDecision(t *testing.T) { mockHttpClient := veriff.NewMockHttpClient(t) - client := veriff.NewClient("https://a.b", "token", veriff.WithHTTPClient(mockHttpClient)) + client := veriff.NewClient("https://a.b", "token", "secret", veriff.WithHTTPClient(mockHttpClient)) resp := &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader(decisionMsg))} mockHttpClient.On("Do", mock.AnythingOfType("*http.Request")).Return(resp, nil).Once() @@ -69,7 +69,7 @@ func TestSessionDecision(t *testing.T) { func TestSessionDecision_RequestErr(t *testing.T) { mockHttpClient := veriff.NewMockHttpClient(t) - client := veriff.NewClient("https://a.b", "token", veriff.WithHTTPClient(mockHttpClient)) + client := veriff.NewClient("https://a.b", "token", "secret", veriff.WithHTTPClient(mockHttpClient)) _, err := client.SessionDecision(nil, "") //lint:ignore SA1012 testing failure require.Error(t, err) @@ -78,7 +78,7 @@ func TestSessionDecision_RequestErr(t *testing.T) { func TestSessionMedia_RequestErr(t *testing.T) { mockHttpClient := veriff.NewMockHttpClient(t) - client := veriff.NewClient("https://a.b", "token", veriff.WithHTTPClient(mockHttpClient)) + client := veriff.NewClient("https://a.b", "token", "secret", veriff.WithHTTPClient(mockHttpClient)) _, err := client.SessionMedia(nil, "") //lint:ignore SA1012 testing failure require.Error(t, err) diff --git a/signer.go b/signer.go new file mode 100644 index 0000000..7d609d9 --- /dev/null +++ b/signer.go @@ -0,0 +1,13 @@ +package veriff + +import ( + "crypto/hmac" + "crypto/sha256" + "fmt" +) + +func SignPayload(secret, payload string) string { + digest := hmac.New(sha256.New, []byte(secret)) + digest.Write([]byte(payload)) + return fmt.Sprintf("%x", digest.Sum(nil)) +} diff --git a/signer_test.go b/signer_test.go new file mode 100644 index 0000000..be28e54 --- /dev/null +++ b/signer_test.go @@ -0,0 +1,15 @@ +package veriff_test + +import ( + "testing" + + "github.com/brokeyourbike/veriff-api-client-go" + "github.com/stretchr/testify/assert" +) + +func TestSignPayload(t *testing.T) { + signed1 := veriff.SignPayload("secret", "") + signed2 := veriff.SignPayload("secret", string([]byte{})) + + assert.Equal(t, signed1, signed2) +} diff --git a/webhook/verifier.go b/webhook/verifier.go index ecc857f..ccf5f1f 100644 --- a/webhook/verifier.go +++ b/webhook/verifier.go @@ -2,9 +2,9 @@ package webhook import ( "context" - "crypto/hmac" - "crypto/sha256" "fmt" + + "github.com/brokeyourbike/veriff-api-client-go" ) type Verifier interface { @@ -21,11 +21,7 @@ func NewVerifier(secrets []string) *verifier { func (v *verifier) Verify(ctx context.Context, message, signature string) error { for _, secret := range v.secrets { - digest := hmac.New(sha256.New, []byte(secret)) - digest.Write([]byte(message)) - computed := fmt.Sprintf("%x", digest.Sum(nil)) - - if computed == signature { + if veriff.SignPayload(secret, message) == signature { return nil } }