Reputation: 1493
I want to verify the signature of an incoming request in Azure APIM. My policy looks like
<inbound>
<base />
<!-- Extract the signature from the Authorization header -->
<set-variable name="receivedSignature" value="@(context.Request.Headers.GetValueOrDefault("signature", ""))" />
<!-- Extract the data to be signed (e.g., request body) -->
<set-variable name="messageId" value="@(context.Request.Headers.GetValueOrDefault("messageId", ""))" />
<set-variable name="timestamp" value="@(context.Request.Headers.GetValueOrDefault("timestamp", ""))" />
<set-variable name="body" value="@(context.Request.Body.As<string>(preserveContent: true))" />
<set-variable name="dataToSign" value="@((string)context.Variables["messageId"] + (string)context.Variables["timestamp"] + (string)context.Variables["body"])" />
<!-- Secret key for HMAC calculation (base64 encoded) -->
<set-variable name="secretKey" value="{{secret}}" />
<set-variable name="secretKeyEncoded" value="@{
var key = (string)context.Variables["secretKey"];
int NumberChars = key.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2) {
bytes[i / 2] = Convert.ToByte(key.Substring(i, 2), 16);
}
return bytes;
}" />
<!-- Calculate the HMAC-SHA256 signature -->
<set-variable name="calculatedSignature" value="@{
var key = (byte[])context.Variables["secretKeyEncoded"];
var data = (string)context.Variables["dataToSign"];
var hmac = new System.Security.Cryptography.HMACSHA256(key);
var hashBytes = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(data));
return System.BitConverter.ToString(hashBytes).ToLower().Replace("-", string.Empty);
}" />
<!-- Validate the signature -->
<choose>
<when condition="@(context.Variables["calculatedSignature"] != context.Variables["receivedSignature"])">
<!-- Signature is invalid -->
<return-response>
<set-status code="401" reason="Unauthorized" />
<set-body>@("Invalid HMAC signature")</set-body>
</return-response>
</when>
</choose>
</inbound>
I'll get another hash code than the one from the sent signature. What can be the issue here? Suspected is the body. I have to use the raw body for that but am not sure if I'll get it with my call and in case it's wrong how to get it.
Upvotes: 0
Views: 109
Reputation: 6497
I am using your policy with a few modification in choose
block.
<policies>
<inbound>
<base />
<!-- Extract the signature from the Authorization header -->
<set-variable name="receivedSignature" value="@(context.Request.Headers.GetValueOrDefault("signature", ""))" />
<!-- Extract the data to be signed (e.g., request body) -->
<set-variable name="messageId" value="@(context.Request.Headers.GetValueOrDefault("messageId", ""))" />
<set-variable name="timestamp" value="@(context.Request.Headers.GetValueOrDefault("timestamp", ""))" />
<set-variable name="body" value="@(context.Request.Body.As<string>(preserveContent: true))" />
<set-variable name="dataToSign" value="@((string)context.Variables["messageId"] + (string)context.Variables["timestamp"] + (string)context.Variables["body"])" />
<!-- Secret key for HMAC calculation (base64 encoded) -->
<set-variable name="secretKey" value="{{secret}}" />
<set-variable name="secretKeyEncoded" value="@{
var key = (string)context.Variables["secretKey"];
int NumberChars = key.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2) {
bytes[i / 2] = Convert.ToByte(key.Substring(i, 2), 16);
}
return bytes;
}" />
<!-- Calculate the HMAC-SHA256 signature -->
<set-variable name="calculatedSignature" value="@{
var key = (byte[])context.Variables["secretKeyEncoded"];
var data = (string)context.Variables["dataToSign"];
var hmac = new System.Security.Cryptography.HMACSHA256(key);
var hashBytes = hmac.ComputeHash(System.Text.Encoding.UTF8.GetBytes(data));
return System.BitConverter.ToString(hashBytes).ToLower().Replace("-", string.Empty);
}" />
<!-- Validate the signature -->
<choose>
<when condition="@(((string)context.Variables["calculatedSignature"]).Trim().ToLower() != ((string)context.Variables["receivedSignature"]).Trim().ToLower())">
<!-- Signature is invalid -->
<return-response>
<set-status code="401" reason="Unauthorized" />
<set-body>@("Invalid HMAC signature")</set-body>
</return-response>
</when>
</choose>
</inbound>
</policies>
I am passing the request body in JSON format along with the other input data.
Trace-
While testing the policy, check if the policy is being evaluated correctly in trace and also you can check the errors.
Upvotes: 0