Layer7 API Management

Expand all | Collapse all

HMAC authentication

Jump to Best Answer
  • 1.  HMAC authentication

    Posted 03-24-2020 09:52 AM
    Hi,

    We have some project to interface with Nexus company, using HMAC authentication.
    We intend to use "Generate Security Hash" assertion.

    Here's what they provide:
    From: https://developer.infornexus.com/api/api-overview/hmac-authentication

    The client computes a hashed "signature" with several elements of the request using a SecretAccessKey. This "signature" is sent to the server along with the UserID and the AccessKeyID that are used to compute the signature in the Authorization header. The client also sends an ISO8601 compliant datetime (in UTC and in precision to the second; yyyy-mm-ddThh:mm:ss.ffffff) in the x-dapi-date header as part of the request.

    Steps to calculate Authorization Header value on the Client side...

    1. StringToSign = UTF-8-Encoding-Of(canonalizeHeaders( HTTP-Verb + PathInfo + DateTimeStamp + Payload (in case of raw post) + content-type (for POST) )) + file_content_as_bytes;

      • HTTP-Verb i.e., 'GET' or 'POST'
      • PathInfo i.e., '/rest/3.1/OrderDetail/design'
      • DateTimeStamp i.e., '2018-11-06T18:55:36.029136' (same as the one in header x-dapi-date)
      • Payload is the data passed in for a raw POST request.
      • content-type i.e., 'application/pdf' (only if a POST request)
      • canonalizeHeaders is a function that will sort and lower case all of the headers above.
      • UTF-8-Encoding-Of is a function to encode using UTF-8.
      • file_content_as_bytes (for a POST request with a file)
    2. signature = Base64( HMAC-SHA256(StringToSign,UTF-8-Encoding-Of(secretAccessKey)) );

      • StringToSign is created in step 1 above.
      • secretAccessKey is the secret key you get when generating access keys i.e., 'f8ae9e5c' (in section above)
      • UTF-8-Encoding-Of is a function to encode using UTF-8.
      • HMAC-SHA256 is a function that mixes a secret key (secretAccessKey) with the message data (StringToSign), hashes the result with the hash function, mixes that hash value with the secret key again, and then applies the hash function a second time. The output hash is 256 bits in length. Depending on the programming language and version that you use, check if the HMAC function requires the parameters to be in a certain format. For example, in python 3 there is a requirement for the parameters to be byte and bytearray.
      • Base64 - function that encodes in Base64.
    3. Authorization Header value = "HMAC_1" + " " + accessKeyId + ":" + signature + ":" + userId);

      • "HMAC_1" allows us to version auth scheme.
      • The space delimited after "HMAC_1" helps us detect a different type of authentication mode.
      • accessKeyId is the key ID you get when generating access keys i.e., '15903aae' (in section above)
      • signature is created in step 2 above.
      • userId is the Data API Agent User ID who owns this access key i.e., 'DataAPIAgent@5717989018004282' (in sections above)

    What is puzzling us is the canonicalHeaders().
    Do you see a way to do this, other than building a custom assertion ?


  • 2.  RE: HMAC authentication
    Best Answer

    Posted 03-24-2020 10:49 AM
    Hi, Philippe.

    There are two tactical assertion to accomplish this: GenerateSecuritySignatureAssertion  and ValidateSecuritySignatureAssertion

    Best regards

    ------------------------------
    Sr. Consultant Services
    HCL Enterprise Studio
    ------------------------------



  • 3.  RE: HMAC authentication

    Posted 03-24-2020 01:32 PM
    Thanks, will request them from support.


  • 4.  RE: HMAC authentication

    Posted 04-01-2020 05:36 AM
    Feedback.

    > There are two tactical assertion to accomplish this: GenerateSecuritySignatureAssertion  and ValidateSecuritySignatureAssertion

    9.4 has already 'Generate Security Hash" assertion that did the trick.

    Solution was to use:

    1 StringToSign = UTF-8-Encoding-Of(canonalizeHeaders( HTTP-Verb + PathInfo + DateTimeStamp + Payload (in case of raw post) +
    content-type (for POST) )) + file_content_as_bytes;

    Javascript code.



    2 signature = Base64( HMAC-SHA256(StringToSign,UTF-8-Encoding-Of(secretAccessKey)) );

    "Generate Security Hash" has both HMAC-SHA256 and returns already base64 encoded result.



    3 Authorization Header value = "HMAC_1" + " " + accessKeyId + ":" + signature + ":" + userId);

    Obvious: AddHeaders() assertion.


    Thx Christian from Broadcom for pointing me to typos in our code :)