Personalization

Profiles API and HMAC v2 authorization

Based on Personalization account configuration, API calls may require HMAC authentication in the form of a HMAC-SHA256 message hash as a header within the request. HMAC is a keyed-hash authentication code that calculates a message authentication code (MAC) involving a cryptographic hash function in combination with a secret cryptographic key. SHA256 is one kind of cryptographic hash function used in the calculation of an HMAC header; the resulting algorithm is known as HMAC-SHA256.

Profiles API calls authenticate using HMAC v2 to protect your data and ensure that your secret keys stay secure, while using the Access Key ID and secret access key associated with your Personalization subscription.

Important

Profiles API calls support authentication only with HMAC v2.

Acquia has HMAC implementation scripts in several languages, including the following:

For more information about the HMAC implementation that is in use, see the Acquia HMAC spec.

Setting HMAC authentication as an HTTP request

In the Profiles API, HMAC authentication is set as a header in an HTTP request. The HTTP client signs the request by adding the following HTTP headers:

Authorization : <HMACAuthorization>
X-Authorization-Timestamp : <Unix Timestamp In Seconds>
X-Authorization-Content-SHA256 : <HashedContent> (if Content-Length > 0)

Creating the authorization header

To create the authorization header, include the following attributes:

  • realm: The provider—for example, Acquia or MyCompany
  • id: The API key’s unique identifier, which is an arbitrary string
  • nonce: A hex version 1 or 4 UUID
  • version: The version of HMAC this request uses
  • headers: A list of additional request headers that are to be included in the signature base string—these are lowercase, and are separated with the semicolon ( ; ) character
  • signature: The Base64-encoded signature as described in Creating the signature

Ensure that each attribute value is enclosed in double quotes and percent encoded.

Creating the signature

The signature is a Base64-encoded binary HMAC-SHA256 digest generated from the following elements:

  • Base64 Hashed SecretKey: The API key’s shared secret. The secret key must be a 256 to 512 bit binary value. The secret key will normally be stored as a Base64-encoded or hex-encoded string representation, but must be decoded to the binary value before use.
  • StringToSign: A concatenated string generated from the following parts:
    • HTTP-Verb: The uppercase HTTP request method. For example, GET or POST.
    • Host: The hostname in lowercase, matching the HTTP Host request header field, including any port number.
    • Path: The HTTP request path with leading slash. For example, /resource/11.
    • QueryParameters: Any query parameters or empty string, which should be the exact string sent by the client, including percent encoding.
    • AuthorizationHeaderParameters: Normalized parameters similar to section 9.1.1 of OAuth 1.0a, which uses the following parameters:

      • id
      • nonce
      • realm
      • version

      Parameters are sorted by name and separated by & with name and value separated by =. They are percent encoded.

    • AdditionalSignedHeaders: The normalized header names and values specified in the headers parameter of the authorization header Names should be lowercase, sorted by name, separated from value by a colon, and the value followed by a newline (so each extra header is on its own line). If there are no added signed headers, an empty line should not be added to the signature base string.
    • X-Authorization-Timestamp: The value of the X-Authorization-Timestamp header, a Unix timestamp (integer seconds since Jan 1, 1970 UTC) - required for all requests If this value differs by more than 900 seconds (15 minutes) from the time of the server, the request will be rejected.
    • Content-Type: The lowercase value of the Content-type header or an empty string if absent (omit if Content-Length is 0)
    • Body-Hash: The Base64-encoded SHA-256 digest of the raw body of the HTTP request, for POST, PUT, PATCH, DELETE or other requests that may have a body (omit this parameter if Content-Length is 0) This value should be identical to the string sent as the X-Authorization-Content-SHA256 header.

X-Authorization-Content-SHA256 header

This header is the Base64-encoded SHA-256 hash value used to generate the signature base string. It is required for any request where Content-Length is not 0. For example, a POST request with a body. This header should be provided by the client to ensure that the request body it sent was not tampered on its way to the server. After the server receives the request body, it forms the Body-Hash, and then compares it to the request body again.

Example

In the following example, the HTTP Authorization header and signature are constructed:

HMACAuthorization = "acquia-http-hmac" + " " +
"realm=" + Provider + "," +
"id=" + AccessKey + "," +
"nonce=" + HexV4OfRandomUUID + "," +
"version=" + HMACVersion + "," +
"headers=" + AdditionalSignedHeaderNames + "," +
"signature=" + HMACSignature
AdditionalSignedHeaderNames = "" or
Lowercase( HTTP-Header-Name ) [ + ";" + Lowercase( HTTP-Header-Name ), for additional headers]

HMACSignature = Base64( HMAC-SHA256 ( SecretKey, UTF-8-Encoding-Of( StringToSign ) ) )

StringToSign = HTTP-Verb + "\n" +
Host + "\n" +
Path + "\n" +
QueryParameters + "\n" +
AuthorizationHeaderParameters + "\n" +
[ AdditionalSignedHeaders, If the headers attribute is not empty, + "\n" ] +
X-Authorization-Timestamp +
[ "\n" + Content-Type +
"\n" + HashedContent, if Content-Length > 0 ]

AuthorizationHeaderParameters = "id=" + URLEncode( AccessKey ) + "&" +
"nonce=" + URLEncode( HexV4OfRandomUUID ) + "&" +
"realm=" + URLEncode( Provider ) + "&" +
"version=" + URLEncode( Version )

AdditionalSignedHeaders = Lowercase( HTTP-Header-Name ) + ":" + HTTP-Header-Value
[ + "\n" + Lowercase( HTTP-Header-Name ) + ":" + HTTP-Header-Value, for additional headers]
(must be sorted by Lowercase( HTTP-Header-Name ) )

HashedContent = Base64( SHA256 ( Request-Body ) )

"\n" denotes a Unix-style line feed (ASCII code 0x0A).

Setting HMAC authentication using a GET method

In the following example, HMAC authentication is set using a HTTP GET method.

https://example-liftapi.lift.acquia.com/dashboard/rest/EXAMPLEINC/segments?site_id=10
X-Authorization-Timestamp: 1432075982

In this example, the authorization header contains the following values:

  • realm: AcquiaLiftWeb
  • id: Ra9YgrsKAcXDLMexg44N
  • nonce: d1954337-5319-4821-8427-115542e08d10
  • Base64 Hashed SecretKey: KgFBhwQMC4wZ6Ls9u7UNbX6jV4xEt5Xvetr9zCEQ

Signature-Base-String is:

GET
example-liftapi.lift.acquia.com
/dashboard/rest/EXAMPLEINC/segments
site_id=10
id=Ra9YgrsKAcXDLMexg44N&nonce=d1954337-5319-4821-8427-115542e08d10&realm=AcquiaLiftWeb&version=2.0
1432075982

Note

Content type and body hash are omitted for GET methods.

The request signature is 4wYr5sIgw5C3f6CjO2UGimuCmrwm+PFtZ2CjyW5+7j4=

This value is created by signing the Signature-Base-String with the hashed SecretKey.

The authorization header is:

acquia-http-hmac realm="AcquiaLiftWeb",id="Ra9YgrsKAcXDLMexg44N",nonce="d1954337-5319-4821-8427-115542e08d10",version="2.0",signature="4wYr5sIgw5C3f6CjO2UGimuCmrwm+PFtZ2CjyW5+7j4="

The full HTTP request is:

GET /dashboard/rest/EXAMPLEINC/segments
Host: example-liftapi.lift.acquia.com
X-Authorization-Timestamp: 1432075982
Authorization: acquia-http-hmac realm="AcquiaLiftWeb",id="Ra9YgrsKAcXDLMexg44N",nonce="d1954337-5319-4821-8427-115542e08d10",version="2.0",signature="R6y7kWkBnUdcSNXMxh4Vib6wSSHYKY4srCA1d4unW78="

Setting HMAC authentication using a POST method

In the following example, HMAC authentication is set as an HTTP request using a POST method.

https://example-liftapi.lift.acquia.com/dashboard/rest/EXAMPLEINC/event_import
X-Authorization-Timestamp:  1449578521
Content-Type: application/json

The body of the request contains the following values:

{"identity":"[email protected]","identity_source":"email","event_name":"Content View",
"event_source":"web","event_date":"2015-11-05 10:22:03.111","engagement_score":"15",
"identities":{"fb_event_import_eg":"facebook"}};

X-Authorization-Content-SHA256 is zC4p8Oa+aw6pTdoW1uFN0ngemDjd5QlZXBK5tcUKzCw=. This value is the SHA256-encoded request body.

In this example, the authorization header contains the following values:

  • realm: AcquiaLiftWeb
  • id: Ra9YgrsKAcXDLMexg44N
  • nonce: 64d02132-40bf-4fce-85bf-3f1bb1bfe7dd
  • Base64 Hashed SecretKey -eox4TsBBPhpi737yMxpdBbr3sgg/DEC4m47VXO0B8qJLsbdMsmN47j/ZF/EFpyUKtAhm0OWXMGaAjRaho7/93Q==

Signature-Base-String is:

POST
example-liftapi.lift.acquia.com
/dashboard/rest/EXAMPLEINC/event_import
id=Ra9YgrsKAcXDLMexg44N&nonce=64d02132-40bf-4fce-85bf-3f1bb1bfe7dd&realm=AcquiaLiftWeb&version=2.0
1449578521
application/json
zC4p8Oa+aw6pTdoW1uFN0ngemDjd5QlZXBK5tcUKzCw=

Note

The preceding code example contains an empty line. This is because there are no query parameters being passed in the URL. Omitting this line may cause this code example to not work properly.

The request signature is: sW4t14rZvcZDEpJwwWWkqCRwTUYiKVAK2aHURtBCIrU=

The authorization header is:

acquia-http-hmac realm="AcquiaLiftWeb",id="f0d16792-cdc9-4585-a5fd-bae3d898d8c5",nonce="64d02132-40bf-4fce-85bf-3f1bb1bfe7dd",version="2.0",signature="sW4t14rZvcZDEpJwwWWkqCRwTUYiKVAK2aHURtBCIrU="

The full HTTP request is:

POST /dashboard/rest/EXAMPLEINC/event_import
Host: example-liftapi.lift.acquia.com
X-Authorization-Timestamp: 1449578521
Content-Type: application/json
Request body: {"identity":"[email protected]","identity_source":"email","event_name":"Content View","event_source":"web","event_date":"2015-11-05 10:22:03.111","engagement_score":"15","identities":{"fb_event_import_eg":"facebook"}}
X-Authorization-Content-SHA256: zC4p8Oa+aw6pTdoW1uFN0ngemDjd5QlZXBK5tcUKzCw=
Authorization: acquia-http-hmac realm="AcquiaLiftWeb",id="efdde334-fe7b-11e4-a322-1697f925ec7b",nonce="d1954337-5319-4821-8427-115542e08d10",version="2.0",signature="R6y7kWkBnUdcSNXMxh4Vib6wSSHYKY4srCA1d4unW78="

Response

The server responds to the client’s request by constructing a header and signature.

Response header

The following example illustrates construction of the HTTP X-Server-Authorization-HMAC-SHA256 header and signature for all non-HEAD requests:

HMACServerAuthorization = Base64( SHA256 ( ResponseStringToSign ) )

ResponseStringToSign = Nonce + "\n" +
      X-Authorization-Timestamp + "\n" +
      Response-Body

Response signature

The response signature base string is a concatenated string generated from the following elements:

  • Nonce: The nonce that was sent in the Authorization header
  • X-Authorization-Timestamp: The timestamp that was sent in the X-Authorization-Timestamp header
  • Response-Body: The response body (or empty string)

Example

The following is an example of a response signature base string:

Response body - {"id": 133, "status": "done"}
Nonce - d1954337-5319-4821-8427-115542e08d10
X-Authorization-Timestamp - 1432075982
Base64 encoded secret key - eox4TsBBPhpi737yMxpdBbr3sgg/DEC4m47VXO0B8qJLsbdMsmN47j/ZF/EFpyUKtAhm0OWXMGaAjRaho7/93Q==

Signature-Base-String is:

d1954337-5319-4821-8427-115542e08d10
1432075982
{"id": 133, "status": "done"}

The signed response is: M4wYp1MKvDpQtVOnN7LVt9L8or4pKyVLhfUFVJxHemU=

The full HTTP response is:

Response body - {"id": 133, "status": "done"}
X-Server-Authorization-HMAC-SHA256 - M4wYp1MKvDpQtVOnN7LVt9L8or4pKyVLhfUFVJxHemU=

Response validation

Requests using the GET method will return a response with a X-Server-Authorization-HMAC-SHA256 header. This header is created when the response Signature-Base-String is signed with the client’s secretKey.

Managing HMAC authentication in Personalization Web

Although HMAC is enabled by default, you can disable it for troubleshooting.

To either enable or disable HMAC authentication:

  1. Sign in to Personalization as an administrator, and then click the Admin tab.
  2. In the System menu, click Manage customers.
  3. In Account ID, click your ID.
  4. In the API Authentication settings, depending on the API call you are using, select or clear the appropriate checkboxes to either enable or disable your HMAC authentication settings:
    • Enable Segment REST Api HMAC Authentication: Controls HMAC authentication for segment calls in the Profiles API
    • Enable Event Import REST Api HMAC Authentication: Controls HMAC authentication for event imports in the Profiles API
    • Enable File Export REST Api HMAC Authentication: Controls HMAC authentication for file exports in the Profiles API
    • Enable Visitor Query REST Api HMAC Authentication: Controls HMAC authentication for visitor queries in the Profiles API

Code examples

We have developed several code examples you can use to help you understand how to make calls to the Profiles API reference using different programming languages:

  • PHP code example: Makes a call to the Profiles API based on the parameters you have provided. getMakeAPICall is the entry point of the example.
  • Java code example Makes several calls to the Profiles API. The entry point of the example is the main method.