Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 304129
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 12, 20262026-05-12T07:15:06+00:00 2026-05-12T07:15:06+00:00

The Amazon Product Advertising API (formerly Amazon Associates Web Service or Amazon AWS) has

  • 0

The Amazon Product Advertising API (formerly Amazon Associates Web Service or Amazon AWS) has implemented a new rule which is by August 15th 2009 all web service requests to them must be signed. They have provided sample code on their site showing how to do this in C# using both REST and SOAP. The implementation that I’m using is SOAP. You can find the sample code here, I’m not including it because there is a fair amount.

The problem I’m having is their sample code uses WSE 3 and our current code doesn’t use WSE. Does anyone know how to implement this update with just using the auto generated code from the WSDL? I’d like to not have to switch over to the WSE 3 stuff right now if I don’t have to since this update is more of a quick patch to hold us over until we can fully implement this in the current dev version (August 3rd they’re starting to drop 1 in 5 requests, in the live environment, if they aren’t signed which is bad news for our application).

Here’s a snippet of the main portion that does the actual signing of the SOAP request.

class ClientOutputFilter : SoapFilter
{
    // to store the AWS Access Key ID and corresponding Secret Key.
    String akid;
    String secret;

    // Constructor
    public ClientOutputFilter(String awsAccessKeyId, String awsSecretKey)
    {
        this.akid = awsAccessKeyId;
        this.secret = awsSecretKey;
    }

    // Here's the core logic:
    // 1. Concatenate operation name and timestamp to get StringToSign.
    // 2. Compute HMAC on StringToSign with Secret Key to get Signature.
    // 3. Add AWSAccessKeyId, Timestamp and Signature elements to the header.
    public override SoapFilterResult ProcessMessage(SoapEnvelope envelope)
    {
        var body = envelope.Body;
        var firstNode = body.ChildNodes.Item(0);
        String operation = firstNode.Name;

        DateTime currentTime = DateTime.UtcNow;
        String timestamp = currentTime.ToString("yyyy-MM-ddTHH:mm:ssZ");

        String toSign = operation + timestamp;
        byte[] toSignBytes = Encoding.UTF8.GetBytes(toSign);
        byte[] secretBytes = Encoding.UTF8.GetBytes(secret);
        HMAC signer = new HMACSHA256(secretBytes);  // important! has to be HMAC-SHA-256, SHA-1 will not work.

        byte[] sigBytes = signer.ComputeHash(toSignBytes);
        String signature = Convert.ToBase64String(sigBytes); // important! has to be Base64 encoded

        var header = envelope.Header;
        XmlDocument doc = header.OwnerDocument;

        // create the elements - Namespace and Prefix are critical!
        XmlElement akidElement = doc.CreateElement(
            AmazonHmacAssertion.AWS_PFX, 
            "AWSAccessKeyId", 
            AmazonHmacAssertion.AWS_NS);
        akidElement.AppendChild(doc.CreateTextNode(akid));

        XmlElement tsElement = doc.CreateElement(
            AmazonHmacAssertion.AWS_PFX,
            "Timestamp",
            AmazonHmacAssertion.AWS_NS);
        tsElement.AppendChild(doc.CreateTextNode(timestamp));

        XmlElement sigElement = doc.CreateElement(
            AmazonHmacAssertion.AWS_PFX,
            "Signature",
            AmazonHmacAssertion.AWS_NS);
        sigElement.AppendChild(doc.CreateTextNode(signature));

        header.AppendChild(akidElement);
        header.AppendChild(tsElement);
        header.AppendChild(sigElement);

        // we're done
        return SoapFilterResult.Continue;
    }
}

And that gets called like this when making the actual web service call

// create an instance of the serivce
var api = new AWSECommerceService();

// apply the security policy, which will add the require security elements to the
// outgoing SOAP header
var amazonHmacAssertion = new AmazonHmacAssertion(MY_AWS_ID, MY_AWS_SECRET);
api.SetPolicy(amazonHmacAssertion.Policy());
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-12T07:15:07+00:00Added an answer on May 12, 2026 at 7:15 am

    I ended up updating the code to use WCF since that’s what it is in the current dev version I’ve been working on. Then I used some code that was posted on the Amazon forums, but made it a little easier to use.

    UPDATE: new easier to use code that lets you still use the config settings for everything

    In the previous code I posted, and what I’ve seen elsewhere, when the service object is created one of the constructor overrides is used to tell it to use HTTPS, give it the HTTPS url and to manually attach the message inspector that will do the signing. The downfall to not using the default constructor is you lose the ability to configure the service via the config file.

    I’ve since redone this code so you can continue to use the default, parameterless, constructor and configure the service via the config file. The benifit of this is you don’t have to recompile your code to use this, or make changes once deployed such as to maxStringContentLength (which is what caused this change to take place as well as discover the downfalls to doing it all in code). I also updated the signing part a bit so that way you can tell it what hashing algorithm to use as well as the regex for extracting the Action.

    These two changes are because not all web services from Amazon use the same hashing algorithm and the Action might need to be extracted differently. This means you can reuse the same code for each service type just by changing what’s in the config file.

    public class SigningExtension : BehaviorExtensionElement
    {
        public override Type BehaviorType
        {
            get { return typeof(SigningBehavior); }
        }
    
        [ConfigurationProperty("actionPattern", IsRequired = true)]
        public string ActionPattern
        {
            get { return this["actionPattern"] as string; }
            set { this["actionPattern"] = value; }
        }
    
        [ConfigurationProperty("algorithm", IsRequired = true)]
        public string Algorithm
        {
            get { return this["algorithm"] as string; }
            set { this["algorithm"] = value; }
        }
    
        [ConfigurationProperty("algorithmKey", IsRequired = true)]
        public string AlgorithmKey
        {
            get { return this["algorithmKey"] as string; }
            set { this["algorithmKey"] = value; }
        }
    
        protected override object CreateBehavior()
        {
            var hmac = HMAC.Create(Algorithm);
            if (hmac == null)
            {
                throw new ArgumentException(string.Format("Algorithm of type ({0}) is not supported.", Algorithm));
            }
    
            if (string.IsNullOrEmpty(AlgorithmKey))
            {
                throw new ArgumentException("AlgorithmKey cannot be null or empty.");
            }
    
            hmac.Key = Encoding.UTF8.GetBytes(AlgorithmKey);
    
            return new SigningBehavior(hmac, ActionPattern);
        }
    }
    
    public class SigningBehavior : IEndpointBehavior
    {
        private HMAC algorithm;
    
        private string actionPattern;
    
        public SigningBehavior(HMAC algorithm, string actionPattern)
        {
            this.algorithm = algorithm;
            this.actionPattern = actionPattern;
        }
    
        public void Validate(ServiceEndpoint endpoint)
        {
        }
    
        public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
        {
        }
    
        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
        }
    
        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {
            clientRuntime.MessageInspectors.Add(new SigningMessageInspector(algorithm, actionPattern));
        }
    }
    
    public class SigningMessageInspector : IClientMessageInspector
    {
        private readonly HMAC Signer;
    
        private readonly Regex ActionRegex;
    
        public SigningMessageInspector(HMAC algorithm, string actionPattern)
        {
            Signer = algorithm;
            ActionRegex = new Regex(actionPattern);
        }
    
        public void AfterReceiveReply(ref Message reply, object correlationState)
        {
        }
    
        public object BeforeSendRequest(ref Message request, IClientChannel channel)
        {
            var operation = GetOperation(request.Headers.Action);
            var timeStamp = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ");
            var toSignBytes = Encoding.UTF8.GetBytes(operation + timeStamp);
            var sigBytes = Signer.ComputeHash(toSignBytes);
            var signature = Convert.ToBase64String(sigBytes);
    
            request.Headers.Add(MessageHeader.CreateHeader("AWSAccessKeyId", Helpers.NameSpace, Helpers.AWSAccessKeyId));
            request.Headers.Add(MessageHeader.CreateHeader("Timestamp", Helpers.NameSpace, timeStamp));
            request.Headers.Add(MessageHeader.CreateHeader("Signature", Helpers.NameSpace, signature));
    
            return null;
        }
    
        private string GetOperation(string request)
        {
            var match = ActionRegex.Match(request);
            var val = match.Groups["action"];
            return val.Value;
        }
    }
    

    To use this you don’t need to make any changes to your existing code, you can even put the signing code in a whole other assembly if need be. You just need to set up the config section as so (note: the version number is important, without it matching the code will not load or run)

    <system.serviceModel>
      <extensions>
        <behaviorExtensions>
          <add name="signer" type="WebServices.Amazon.SigningExtension, AmazonExtensions, Version=1.3.11.7, Culture=neutral, PublicKeyToken=null" />
        </behaviorExtensions>
      </extensions>
      <behaviors>
        <endpointBehaviors>
          <behavior name="AWSECommerceBehaviors">
            <signer algorithm="HMACSHA256" algorithmKey="..." actionPattern="\w:\/\/.+/(?&lt;action&gt;.+)" />
          </behavior>
        </endpointBehaviors>
      </behaviors>
      <bindings>
        <basicHttpBinding>
          <binding name="AWSECommerceServiceBinding" closeTimeout="00:01:00" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true" maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536">
            <readerQuotas maxDepth="32" maxStringContentLength="16384" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
            <security mode="Transport">
              <transport clientCredentialType="None" proxyCredentialType="None" realm="" />
              <message clientCredentialType="UserName" algorithmSuite="Default" />
            </security>
          </binding>
        </basicHttpBinding>
      </bindings>
      <client>
        <endpoint address="https://ecs.amazonaws.com/onca/soap?Service=AWSECommerceService" behaviorConfiguration="AWSECommerceBehaviors" binding="basicHttpBinding" bindingConfiguration="AWSECommerceServiceBinding" contract="WebServices.Amazon.AWSECommerceServicePortType" name="AWSECommerceServicePort" />
      </client>
    </system.serviceModel>
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I've been tinkering with Yahoo Pipes and the Amazon Product Advertising API (formerly ECS)
We've recently implemented Amazon S3 in our site which led us to change the
We're looking into developing a product that would use Amazon's cloud tools (EC2, SQS,
Amazon Mechanical Turk is a mass-micro outsourcing API, where you can get lots's of
Add service reference to Amazon service fails, saying Could not load file or assembly
I've come to love Amazon's EC2 service and I'm looking for something similar that
Using Amazon's own client libraries (or alternatives ), you can get listings of available
I'm considering using Amazon's EC2 with a windows instance & SQL. I've seen some
I have read through several reviews on Amazon and some books seem outdated. I
Is there a way to run an Amazon EC2 AMI image in Windows? I'd

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.