Authentication mechanism

We use HMAC authentication which has been widely used by Amazon and Google to grant access to many of their APIs.

Base URL

https://tv-staging.trustingsocial.com/api
Production
Contact your Account Manager for the production base url.

1. API Access Key

A pair of:

  • Access Key ID: a unique identifier (UUID) of the API access key.

  • Access Key Secret: a secret key that will be used to sign the requests.

TrustVision team will provide an access key pair for each customers before integration.

2. Client signs a request

Two required headers:

  • X-TV-Timestamp: Current timestamp in RFC3339 format.

    • Example: 2019-04-21T18:00:15+07:00
  • Authorization: Header value format TV {AccessKeyID}:{Signature}.

    • Example: TV a0ce69ea-cbf7-49cc-ab47-6381ed7c5cf8:Rm4qG9YHhDaaUdwQlKqPjuzgQkyobDFVfZAZrlEVFwc=

Where

  • AccessKeyID: provided by TrustVision.
  • Signature: a Base64 encoded HMAC SHA256 hash of the StringToSign, refer to the following pseudo code:
text
# Pseudo code
StringToSign = HttpMethod + "\n" + UrlPath + "\n" + Timestamp
# HttpMethod: such as `POST`, `GET`, `PUT`, `PATCH`, `DELETE`
# UrlPath: relative route path of the resource (exclude the domain). Example: `/v1/images`
# Timestamp: the time of the request in RFC3339 format. The client must also
  send this timestamp with the request in the `X-TV-Timestamp` header.

Signature = Base64(HmacSha256(AccessKeySecret, Utf8EncodingOf(StringToSign)))

Advanced: Hash the Content using MD5 and add to StringToSign

text
StringToSign = HttpMethod + "\n" + UrlPath + "\n" + Timestamp + "\n" + ContentMD5;
# ContentMD: hash whole JSON content

Note: When we use content MD5 hashing, we have to AES-256 encrypt JSON content to new JSON structure first

Go
{
    "payload": string, // AES-256 encrypted content
}

Please contact the administrator for more detail.

Reference: Base64 encoded HMAC SHA256 hash (in different languages)

Sample Signature generation code:

// Provided by TV
accessKeyId     = "<YOUR ACCESS KEY>";
accessKeySecret = "<YOUR SECRET>";

// Request info
method          = "POST"
urlPath         = "/v1/images"
rfc3339date    = "2019-04-21T18:00:15+07:00"

// Create signature
var stringToSign = method + "\n" + urlPath + "\n" + rfc3339date;
var signature = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(stringToSign, accessKeySecret););

// Send request
var myHeaders = new Headers();
myHeaders.append("Content-Type", "multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW");
myHeaders.append("Authorization", "TV " + accessKeyId + ":" + signature);
myHeaders.append("X-TV-Timestamp", rfc3339date);

var formdata = new FormData();
formdata.append("file", fileInput.files[0], "file");
formdata.append("label", "portrait");

var requestOptions = {
  method: 'POST',
  headers: myHeaders,
  body: formdata,
  redirect: 'follow'
};

fetch("https://tv-staging.trustingsocial.com/api/v1/images", requestOptions)
  .then(response => response.text())
  .then(result => console.log(result))
  .catch(error => console.log('error', error));

Try verifying Signature using online tool, check the Base64 result to compare with your own computation.

3. Send request

Sample request detail:

KeyValue
Timestamp2019-04-21T18:00:15+07:00
HTTP VerbPOST
Staging endpointhttps://tv-staging.trustingsocial.com/api
Path/v1/images

Sample code:

Shell
curl -X POST \
https://tv-staging.trustingsocial.com/api/v1/images \
-H 'Authorization: TV <YOUR ACCESS KEY>:<CREATED SIGNATURE>' \
-H 'X-TV-Timestamp: 2019-04-21T18:00:15+07:00' \
-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' \
-F file=@/images/portrait.jpg \
-F label=portrait

4. Server verifies the request signature

To verify the signature, the server first takes the request timestamp from X-TV-Timestamp header, compares it with current timestamp of the server. If the difference between 2 timestamps is more than 15 minutes, it will reject the request and return RequestTimeTooSkewed error to the client. The intention of this restriction is to limit the possibility that intercepted requests could be replayed by an adversary.

If the timestamp is within the limit, the server will then parse value from Authorization header to get AccessKeyID and Signature (separated by :). It looks up AccessKeyID to get the corresponding AccessKeySecret.

After that, the server uses the request timestamp to generate the string to sign, and use the AccessKeySecret to creates the signature with the same method as described before.

Finally, the request is authorized if the generated signature matches the request signature.