Skip to main content
Version: Released

Signing your Request

 

➡️ See also the Token Authentication 🔗.

This document will introduce you to the authentication process in order to make requests to By.Me web services.

First, you will see what is expected in your request headers and then you will see how to produce a “BM1 signature” to sign your request. Each step will be illustrated with examples as explained just below.

📌 To make sure that you understand each step of the signature process, we will follow two request examples – Request A and Request B – with the result expected for each step. For both examples we will have those shared data:

  • The date and time will be August 7th 2019 at 13h37m00s GMT
  • The api key will be : “BM1_ACCESS_KEY1”
  • The secret key will be : “BM1_SECRET_KEY1”

Request A

Generate a Token for your Legal Entity 🔗.

Method: POST URL: https://platform.by.me/api/3/tokens to Host: "platform.by.me" to Services: "/api/3/tokens" Body (parameters.json):

   {
"permission":"RW",
"tokenDuration":"100000"
}

Request B

Retrieve a project shopping list

Method: GET URL: (⚠ lowercase/uppercase) https://platform.by.me/api/3/project/shoppingList?userID=”1234”&productID=36415 to Host: "platform.by.me" to Services: "/api/3/project/shoppingList" to Query (parameters.json):

	{
"userID":"1234",
"productID":"36415"
}

Request Headers for Authentication Process

You need to add the correct content-type to your headers with the following headers. Unless, we will not be able to receive your data.

For example:

content-type : “application/json”

Authentication by API Key

Request.headers

{
"apikey": "THE_API_KEY",
"signature": "THE_SIGNATURE",
"timestamp": "THE_TIMESTAMP",
"content-type": "application/json"
}

Authentication by Token

Request.headers

{
"token": "THE_TOKEN",
"timestamp": "THE_TIMESTAMP",
"content-type": "application/json"
}

Timestamp Format

Format ISO-8601 without “:” and “-“ i.e. YYYYMMDD’T’HHMMSS’Z’

Note that the “Z” in this format basically means that the time is given in GMT (also known as Zulu Time).

❗ Please make sure to create your timestamp based on a time in GMT.

In our examples, August 19th 2019 at 13h37m00s (GMT) becomes:

"20190807T133700Z"

Create the Signature with the API Key and the Request

The signature uses the API Key and the request.

📌 We are using these hash algorithms: SHA-256, HMAC-SHA256 base 64. In this document, HMAC will mean HMAC-SHA256 base 64. In this document, HexEncode will represent a function that returns the base-16 encoding of the digest in lowercase characters. Regarding URI encoding, spaces are expected to be encoded with “%20” and NOT “+”.

You will need to create different strings to get the final “String-to-sign”, to hash with your secret key that will also be modified during this process.

Step 1 – Create a Canonical Request

A canonical request is made of the following string parts.

Request Method

The method is the "HTTP verb"in the request. Either "GET", "PUT", "POST" and "DELETE".

Canonical URI

URI-encode the request services, i.e. everything from "/api/api_version/" to the specified services. For example:

"/api/1/project"

If there are no services (but, this should not happen), use this string: "/"

Canonical Query String
StepDescription
1Sort the query list (in a GET request, after the “?” in the URL) by ascending ASCII code of the key (i.e. alphabetically first uppercase then lowercase).
2In case of objects: Sort the sub keys recursively by ascending ASCII code order. Sub-keys should be surrounded by brackets, and URL-encoded (see next step).
3URI-encode each key and each value. Please remember that spaces are expected to be encoded with “%20” and NOT “+”.
4Make a one-line string with:
Canonical query string = key1+"="+value1+"&"+key2+"="+value2.
Key/value pairs are separated by "&".
If there is no value for a key, live an empty string. For example:
key1 + "=" + "" + "&" +...
5If there is no query, leave an empty string by using "", like in this example:
Canonical query string= ""
Canonical Headers

The canonical headers are the combination of the following parts:

"apikey:" + YOUR_APIKEY + "\n"
+ "host:" + THE_HOST + "\n"
+ "timestamp:" + THE_TIMESTAMP

The host is the request.hostname, that is to say the URL without "http://", the services and the port. In our examples:

Canonical headers=
apikey:BM1_ACCESS_KEY1
host:platform.by.me
timestamp:20190807T133700Z
Signed Headers

❗ Copy and paste the following string:

"apikey;host;timestamp"
Hashed Request Payload
StepDescription
1Hash with SHA-256 the request payload i.e. the http request body buffer.
If there is no payload like for a GET request, hash an empty buffer.
2Then hexEncode the result.
Examples

Request A

Request payload =
{
"permission": "RW”",
"tokenDuration": "100000"
}
http request body buffer = <Buffer 7b 0a 09 22 70 65 72 6d 69 73 73 69 6f 6e 22 3a 20 22 52 57 22 2c 0a 09 22 74 6f 6b 65 6e 44 75 72 61 74 69 6f 6e 22 3a 22 31 30 30 30 30 30 22 0a 7d>
Hashed Request payload hexEncoded = c5884c11264fd47c5211f00516465b18e4e46c18d09422821732ed667f1fa046

Request B

Request payload = ""
http request body buffer = null
Hashed Request payload hexEncoded = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

Finally, the canonical request is made by concatenation of each string in the same order separated by "\n" and ending it with a "\n", like in this sample:

Canonical Request =
Request Method + "\n"
+ Canonical URI + "\n"
+ Canonical query string +"\n"
+ Canonical headers + "\n"
+ Signed headers + "\n"
+ Hashed request payload + "\n"

Thus, you should get:

For Request A

Canonical Request =
POST
/api/3/tokens

apikey:BM1_ACCESS_KEY1
host:3DExperience.by.me
timestamp:20190807T133700Z
apikey;host;timestamp
c5884c11264fd47c5211f00516465b18e4e46c18d09422821732ed667f1fa046

For Request B

Canonical Request =
GET
/api/3/project/shoppingList
projectID=36415&userID=%221234%22
apikey:BM1_ACCESS_KEY1
host:3DExperience.by.me
timestamp:20190807T133700Z
apikey;host;timestamp
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855

Step 2 – Create the String to Sign

To create the String-to-sign, you will need the following string parts.

PartDescription
The algorithmThe string "BM1-HMAC-SHA256"
Date and timeThe timestamp.
Date and services + "bm1_request"The date (before the ‘T’ in the timestamp) + the services (ex: “/api/3/project”) + “/bm1_request”.
With our examples:

Request A:
Date and services + “bm1_request” = “20190807/api/3/tokens/bm1_request”

Request B:
Date and services + “bm1_request” = “20190807/api/3/project/shoppingList/bm1_request”
The canonical request hashedHash the canonical request with SHA-256.
Then, hexEncode the result.
With our examples:

Request A:
Hashed canonical request hexEncoded = e2556cbc86a06803932ed86dc08a72d397ef767fbacbe5b8b9a7fda80e2c0b0b

Request B:
Hashed canonical request hexEncoded = ef0f5e343dd61f9c80dc3ad7c08a5a4833c1456487d32b749efec624fcbe555b

Finally, the String-to-sign is made by concatenation of each string in the same order separated by "\n", in other words:

String to sign=
"BM1-HMAC-SHA256" + "\n"
+ Date and time + "\n"
+ Date and services + "bm1_request" +"\n"
+ Canonical request hashed
Expected Results for our Examples

Below are two examples of what you should get.

For Request A

String to sign =
BM1-HMAC-SHA256
20190807T133700Z
20190807/api/3/tokens/bm1_request
e2556cbc86a06803932ed86dc08a72d397ef767fbacbe5b8b9a7fda80e2c0b0b

For Request B

String to sign =
BM1-HMAC-SHA256
20190807T133700Z
20190807/api/3/project/shoppingList/bm1_request
ef0f5e343dd61f9c80dc3ad7c08a5a4833c1456487d32b749efec624fcbe555b

Step 3 – Calculate the Signature

To calculate the signature, start by deriving the Secret Key. Then, generate the signature.

Derive the Secret Key

You will have to perform two HMAC hashes, then hexEncode the result to derive the secret key.

kDate = HMAC( "BM1" + secretKey,  timestamp );
derivedSecretKey = HMAC( kDate, "bm1_request" );
derivedSecretKey = hexEncode(derivedSecretKey);

Expected Result

kDate = "kT9nl6YdU8ixC7jZuA5HSCdgWvpR4I2VjdA9CdSwXdM="
derivedSecretKey before hexEncoding = "r3z04rh5eJ5xgdlQgPUc3IBWrg3WCjoySgcun+djbpQ="

derivedSecretKey = "72337a3034726835654a357867646c51675055633349425772673357436a6f79536763756e2b646a6270513d"

Generate the Signature

Use HMAC with the derived Secret Key and the String-to-sign,then HexEncode the result as follow:

Signature = HexEncode ( HMAC ( derivedSecretKey,  StringToSign ) )

For Request A

Signature before hexEncoding = "A9YCBore20wvq2RmYyCUl5eS0cjuhWC/k/uHfHbBRn4="

Signature = “41395943426f7265323077767132526d597943556c35655330636a756857432f6b2f754866486242526e343d"

For Request B

Signature before hexEncoding = "l0Xd5J4pCreV2YrTvBvN9oGqXy41U/op6cmOBbeAtOM="

Signature = "6c305864354a347043726556325972547642764e396f477158793431552f6f7036636d4f42626541744f4d3d"

You can now add the signature to your request headers as defined at the beginning of this page.

Your request is now authenticated and ready to be sent.


Final Headers in Request Examples

You should get the following.

For Request A

Headers =
{
"apikey": "BM1_ACCESS_KEY1",
"signature": "41395943426f7265323077767132526d597943556c35655330636a756857432f6b2f754866486242526e343d",
"timestamp": "20190807T133700Z",
"content-type": "application/json"
}

For Request B

Headers =
{
"apikey": "BM1_ACCESS_KEY1",
"signature": "6c305864354a347043726556325972547642764e396f477158793431552f6f7036636d4f42626541744f4d3d",
"timestamp": "20190807T133700Z",
"content-type": "application/json"
}