Request Signature Verification
A guide on verifying Accredit's request signatures for secure webhook notifications
Request signature verification is an essential aspect of securing webhook endpoints. It ensures that incoming requests are authentic and have not been tampered with during transit. This guide outlines the process of verifying request signatures in Accredit's webhook endpoints.
Endpoint Verification
Accredit's webhook endpoints utilize request signature verification to ensure the integrity of incoming requests. Below are the steps involved in verifying request signatures:
-
Validate Request Headers:
- The first step is to validate the request headers, particularly the
X-Signature
header. - The presence of the
X-Signature
header is checked. If it is missing, the request is deemed invalid. - The value of the
X-Signature
header is then verified using the clients public key.
- The first step is to validate the request headers, particularly the
-
Verify Request Signature:
- Accredit's webhook endpoints use RSA-based signature verification.
- The request signature is computed based on the request content and compared against the signature provided in the
X-Signature
header. - If the signatures match, the request is considered valid; otherwise, it is rejected.
Code Example
Here is an example of how request signature verification can implemented in C#:
[HttpPost, Route("baseWebhookNotification")]
public async Task<IHttpActionResult> WebhookReceivedTest(baseWebhookNotification request)
{
var publicKey = "client-public-key"
var validateRequestHeaders = await WebhookValidationHelper.ValidateRequestHeaders(Request, publicKey);
if (!validateRequestHeaders.isValid)
{
return BadRequest(validateRequestHeaders.errorMessage);
}
return Ok();
}
public static class WebhookValidationHelper
{
public static async Task<(bool isValid, string errorMessage)> ValidateRequestHeaders(HttpRequestMessage request, string publicKey)
{
var signatureHeader = request.Headers.GetValues("X-Signature").FirstOrDefault();
if (string.IsNullOrEmpty(signatureHeader))
{
return (false, "X-Signature header is missing");
}
if (!await WebhookSignatureKeyHelper.VerifyRequestSignature(request.Content, signatureHeader, publicKey.FromBase64String()))
{
return (false, "Invalid X-Signature header");
}
return (true, null);
}
}
public static class WebhookSignatureKeyHelper
{
private const string SigningAlgorithm = "SHA-256withRSA";
public static async Task<bool> VerifyRequestSignature(HttpContent content, string base64Signature, byte[] publicKeyBytes)
{
ISigner signer = SignerUtilities.GetSigner(SigningAlgorithm);
signer.Init(false, PublicKeyFactory.CreateKey(publicKeyBytes));
byte[] data = await content.ReadAsByteArrayAsync();
signer.BlockUpdate(data, 0, data.Length);
return signer.VerifySignature(Convert.FromBase64String(base64Signature));
}
}
Updated about 1 year ago