API Management Policy example to validate SHA256 signature from sorted and truncated query string parameters

John Kennedy 1 Reputation point
2022-05-11T15:20:35.62+00:00

We found an example of creating the signature from headers, but not the query string parameters. (https://learn.microsoft.com/en-us/azure/api-management/policies/generate-shared-access-signature) We are struggling to find relevant examples and documentation for the functionality we need in the policy to verify a SHA256 signature as we need to read the query string parameters, sort and truncate and hash the resulting string to compare to the sent signature.
This is for a Shopify webhook to verify it came from Shopify. They provide a Ruby example of it seen below. Any guidance on how to write this as an Azure API Management Policy would be much appreciated.

Thanks,
John

require 'openssl'
require 'rack/utils'
SHARED_SECRET = 'hush'

Use request.query_string in rails

query_string = "extra=1&extra=2&shop=shop-name.myshopify.com&path_prefix=%2Fapps%2Fawesome_reviews&timestamp=1317327555&signature=a9718877bea71c2484f91608a7eaea1532bdf71f5c56825065fa4ccabe549ef3"

query_hash = Rack::Utils.parse_query(query_string)

=> {

"extra" => ["1", "2"],

"shop" => "shop-name.myshopify.com",

"path_prefix" => "/apps/awesome_reviews",

"timestamp" => "1317327555",

"signature" => "a9718877bea71c2484f91608a7eaea1532bdf71f5c56825065fa4ccabe549ef3",

}

Remove and save the "signature" entry

signature = query_hash.delete("signature")

sorted_params = query_hash.collect{ |k, v| "#{k}=#{Array(v).join(',')}" }.sort.join

=> "extra=1,2path_prefix=/apps/awesome_reviewsshop=shop-name.myshopify.comtimestamp=1317327555"

calculated_signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), SHARED_SECRET, sorted_params)
raise 'Invalid signature' unless ActiveSupport::SecurityUtils.secure_compare(signature, calculated_signature)

Azure API Management
Azure API Management
An Azure service that provides a hybrid, multi-cloud management platform for APIs.
2,261 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. JananiRamesh-MSFT 29,201 Reputation points
    2022-05-30T09:13:31.03+00:00

    @John Kennedy Thanks for reaching out. From the description I understand that you wanted to create a Shared access signature from the query string. In the document that you're referring they are generating the SAS key using the variables by passing the named values with the storage account details and not from the headers.

    I see for creating a signature it requires open ssl, we don't support open ssl please refer this document to see the supported libraries.

    Below is the policy to fetch the signature from the query string,

    <inbound>  
            <set-variable name="signature" value="@{  
        
    string querystring = context.Request.OriginalUrl.QueryString;  
    string[] tokens = querystring.Split('&');   
        
    return tokens[5];  
    }" />  
        </inbound>  
    

    I am not an expert in Ruby on rails, please provide the relevant code in c#, I will help you in writing a complete policy.
    please let me know in case of further queries, I would be happy to assist you.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.