HMAC Policy - Validate Request from Client

Hi All,

Issue: In the Trace, the HMAC policy is failing  with hmac.error = Unresolved variable : sha. {"fault":{"faultstring":"Unresolved variable : sha","detail":{"errorcode":"entities.UnresolvedVariable"}}}. I'm assuming sha is a variable set by the HMAC policy itself, as it is not referenced anywhere in my policies. Is this error related to how the request content is coming through? And if so, how do I go about determining what needs to be fixed/tweaked? Please let me know what you all think. I've included some additional info below for reference.

 

Background: I have a webhook set up in GitHub which utilizes HMAC Validation with Apigee. Using the same secret in GitHub and Apigee to encode/decode. GitHub is sending header 'X-Hub-Signature-256', the value of the header is populated using sha-256 and the secret key to hash the request content. Below is my HMAC policy code. I've tried setting the IgnoreUnresolvedVariables tag to true, but then my verification values don't match.


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<HMAC name="HMAC-1">
<DisplayName>HMAC Validate Request Content</DisplayName>
<Algorithm>SHA-256</Algorithm>
<Message ref="request.content"/>
<SecretKey ref="private.secretkey"/>
<VerificationValue encoding="base64" ref="request.header.X-Hub-Signature-256"/>
<Output>hmac_value</Output>
</HMAC>

Solved Solved
0 7 1,222
1 ACCEPTED SOLUTION

Hi All,

After performing some more troubleshooting, I found out what the issue was(GitHub side). In the GitHub Webhook configuration, the content type selected was application/json, this was causing the error. Once I changed it to application/x-www-form-urlencoded, the HMAC policy began working as expected.

View solution in original post

7 REPLIES 7

Which version? Are you sure you captured the hmac policy failure output as it looks like extract policy output(I think so).

Looks unusual.Can you confirm if all the variables are set? Try hard code/assign values and try debugging if you find anything ?

 

That's odd

There is no 'hard-coded' variable called "sha" that is referenced within the HMAC policy execution, as far as I can see. 

Can you double-check everything please? 

Can you get the HMAC policy to work (either correctly verify a valid signature, or correctly NOT verify an invalid signature) when your apiproxy is not invoked by github?

Can you get the HMAC policy to work when it is in a different API proxy? 

What if you hard-code the verification value? What if you omit it?

If I were looking at this problem I would try testing different combinations of configuration to see if I could narrow down the root cause.  It's not obvious to me, just looking at it. 

Hi @dchiesa1 ,

Why is a secret key necessary for creating SHA-256 using HMAC Policy, while SHA-256 can operate without one?  Additionally, can you demonstrate how to create a SHA-256 hash without using a secret key? Are there any other methods or mechanisms besides HMAC where we can create a hash without a key?

HMAC is not SHA. HMAC is a keyed hash; in the case of HMAC-sha256, the hash function is SHA-256. But HMAC is not the same as SHA-256. It depends on it, but it is not the same. By definition HMAC depends on a key.

In Apigee, you an use an AssignVariable with a message template to create a SHA-256 on a text value:

 

<AssignMessage name='AM-Compute-SHA256'>
  <AssignVariable>
    <Name>computed-sha256</Name>
    <Template>{sha256Base64(sourcetext)}</Template>
  </AssignVariable>
</AssignMessage>

 

That would give you the base64 encoded version. You can get the base16 (hex) encoded version by using the function sha256Hex in place of sha256Base64 .

If the source value is not text - for example if you want to compute a SHA-256 on an image or a PDF fie or some other stream that cannot be represented as a UTF-8 string - then you will need to resort to python or a Java callout to compute a SHA-256.

Hi All,

After performing some more troubleshooting, I found out what the issue was(GitHub side). In the GitHub Webhook configuration, the content type selected was application/json, this was causing the error. Once I changed it to application/x-www-form-urlencoded, the HMAC policy began working as expected.

I realize this is an old issue,  but I happened to be solving the same problem of using Github webhooks and validating the request with HMAC. The issue with Unresolved variable : sha is because the JSON payload sent from Github includes curly braces in values. For example:

{
    "ref": "refs/heads/prod",
    "before": "0000000000000000000000000000000000000000",
    "after": "edbfefbdceaf4f768802134086cbedd511d7c90b",
    "repository": {
        "id": 638509849,
        "name": "my-repo",
        "breaks_hmac_policy": "value{sha}"
    }
}

The HMAC policy supports "templating" and it's trying to interpret variables in the content.

The solution is to use variablePrefix and variableSuffix like so:

<HMAC name="HMAC-verify">
    <Algorithm>SHA-256</Algorithm>
    <Message variablePrefix="@" variableSuffix="#">{request.content}</Message>
    <SecretKey ref="private.webhook_secret"/>
    <VerificationValue encoding="hex" ref="input_hmac_value"/>
    <Output encoding="hex">output_hmac_value</Output>
</HMAC>

 So now my proxy can support both types of webhook requests: x-www-form-url-encoded and json.

Outstanding, Kurt!  Nice sleuthing and solution.