-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add
IsValidWebhookSignature
function for validating webhook s…
…ignature
- Loading branch information
1 parent
5e78297
commit a5bf13d
Showing
7 changed files
with
200 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# Webhook | ||
|
||
## **CheckHeader** | ||
|
||
> bool CheckHeader(header string, data []byte, secret string) | ||
Verifies the HMAC signature extracted from the "fpjs-event-signature" header of the incoming request. This is a part of the webhook signing process, which is available only for enterprise customers. | ||
If you wish to enable it, please [contact our support](https://fingerprint.com/support). | ||
|
||
### Required Parameters | ||
|
||
| Name | Type | Description | Notes | | ||
|------------|------------|------------------------------------------------------------|-------| | ||
| **header** | **string** | Value of the "fpjs-event-signature" header. | | | ||
| **data** | **[]byte** | Body of the request from which above header was extracted. | | | ||
| **secret** | **secret** | Your generated secret used to sign the request. | | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package main | ||
|
||
import ( | ||
"github.com/fingerprintjs/fingerprint-pro-server-api-go-sdk/v5/sdk/webhook" | ||
) | ||
|
||
func main() { | ||
// Your webhook signing secret. | ||
secret := "secret" | ||
|
||
// Request data. In real life scenerio this will be the body of incoming request | ||
data := []byte("data") | ||
|
||
// Value of the "fpjs-event-signature" header. | ||
header := "v1=1b2c16b75bd2a870c114153ccda5bcfca63314bc722fa160d690de133ccbb9db" | ||
|
||
isValid := webhook.CheckHeader(header, data, secret) | ||
|
||
if !isValid { | ||
panic("Invalid signature") | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package webhook | ||
|
||
import ( | ||
"crypto/hmac" | ||
"crypto/sha256" | ||
"encoding/hex" | ||
"strings" | ||
) | ||
|
||
func checkSignature(signature string, data []byte, secret string) bool { | ||
h := hmac.New(sha256.New, []byte(secret)) | ||
h.Write(data) | ||
computedSignature := hex.EncodeToString(h.Sum(nil)) | ||
return signature == computedSignature | ||
} | ||
|
||
// CheckHeader Verifies the HMAC signature extracted from the "fpjs-event-signature" header of the incoming request. This is a part of the webhook signing process, which is available only for enterprise customers. | ||
// If you wish to enable it, please contact our support: https://fingerprint.com/support | ||
func CheckHeader(header string, data []byte, secret string) bool { | ||
signatures := strings.Split(header, ",") | ||
|
||
for _, signature := range signatures { | ||
parts := strings.Split(signature, "=") | ||
if len(parts) == 2 && parts[0] == "v1" { | ||
hash := parts[1] | ||
if checkSignature(hash, data, secret) { | ||
return true | ||
} | ||
} | ||
} | ||
|
||
return false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
package test | ||
|
||
import ( | ||
"github.com/fingerprintjs/fingerprint-pro-server-api-go-sdk/v5/sdk/webhook" | ||
"github.com/stretchr/testify/assert" | ||
"testing" | ||
) | ||
|
||
const secret = "secret" | ||
const data = "data" | ||
|
||
func TestCheckHeader(t *testing.T) { | ||
const validHeader = "v1=1b2c16b75bd2a870c114153ccda5bcfca63314bc722fa160d690de133ccbb9db" | ||
|
||
t.Run("With valid signature", func(t *testing.T) { | ||
isEqual := webhook.CheckHeader(validHeader, []byte(data), secret) | ||
|
||
assert.Equal(t, true, isEqual) | ||
}) | ||
|
||
t.Run("With invalid header", func(t *testing.T) { | ||
isEqual := webhook.CheckHeader("v2=invalid", []byte(data), secret) | ||
|
||
assert.Equal(t, false, isEqual) | ||
}) | ||
|
||
t.Run("With header without version", func(t *testing.T) { | ||
isEqual := webhook.CheckHeader("invalid", []byte(data), secret) | ||
|
||
assert.Equal(t, false, isEqual) | ||
}) | ||
|
||
t.Run("With empty header", func(t *testing.T) { | ||
isEqual := webhook.CheckHeader("invalid", []byte(data), secret) | ||
|
||
assert.Equal(t, false, isEqual) | ||
}) | ||
|
||
t.Run("With empty secret", func(t *testing.T) { | ||
isEqual := webhook.CheckHeader(validHeader, []byte(data), "") | ||
|
||
assert.Equal(t, false, isEqual) | ||
}) | ||
|
||
t.Run("With empty data", func(t *testing.T) { | ||
isEqual := webhook.CheckHeader(validHeader, []byte(""), secret) | ||
|
||
assert.Equal(t, false, isEqual) | ||
}) | ||
} |