Authentication
As all server-side APIs of the platform are stateless HTTP services, all requests made against it have to be authenticated individually. This is done by signing all request with the Tenant-specific admin key with the special scheme described below.
Signing procedure
The signing procedure has 4 major steps. In the first step the request should be assembled completely but without the signature. In the second step the request is analyzed and canonicalized to a string which will be the subject of the signing. The third step is the signature calculation itself, and in the final step we amend the original request with the computed signature header(s).
Step 1. - Assemble the request
Assemble the request according to the API description and also provide the following headers:
Required headers:
Content-Type
Please fill this header according of the API description. Do not provide it with GET calls. (In the case of POST calls the value should be "application/json", otherwise it should be omitted.)
| Example |
Content-Type: application/json
|
Content-SHA256
If the request has a body (typically POST requests), always provide the Content-SHA256 header with the proper value. (The value should be the SHA256 fingerprint of the contents converted into a lower-case hex string.)
| Example* |
Content-SHA256: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
|
*Note: in the example above the hash is the hash of the empty string.
TresoritDate
Always provide this header and populate it with the current UTC timestamp in ISO-8601 format. The request is accepted only when the value of this header is within a 15 minute range from the server clock.
| Example* |
TresoritDate: 2014-05-05T05:05:05Z
|
*Note: Please always use the "Z" time-zone specifier in the date for indicating the UTC zone.
UserId
Always provide this header for all administrative calls and fill the value with the admin user ID of your tenant. The admin user id is always computed with the following format string:
"admin@{TenantId}.tresorit.io" where {TenantId} is the placeholder for your tenant's ID.
| Example* |
UserId: [email protected]
|
*Note: in the example above the Tenant ID is "exampletenant"
HMACHeaders header
To indicate the list of signed header to the platform server, please construct and add an additional header, called "HMACHeaders" to the request. The HMACHeaders header value is the comma separated list of the names of the signed headers. (This header itself can also be signed, but its not necessary. Note, that there should be no whitespaces in the list.)
The rules to assemble the list of the signed headers can be read below, in Step 2.
| Example |
HMACHeaders: Content-Type,Content-SHA256,TresoritDate,UserId
|
Request examples
Here you can see two examples for API calls. One for a GET and one for a POST call.
Get call example (listing userbase)
| Example |
GET [https://exampletenant.api.tresorit.io/api/v1/users/admin/listusers](https://exampletenant.api.tresorit.io/api/v1/users/admin/listusers) HTTP/1.1Host: [exampletenant.api.tresorit.io](http://exampletenant.api.tresorit.io)TresoritDate: 2014-05-05T05:05:05ZUserId: [email protected]: TresoritDate,UserId
|
Post call example (setting user state)
| Example | <body> |
Step 2. - Canonicalize request
In this step a canonical request string should be assembled, which will be the subject of the signing. For this, the list of headers to sign should be determined.
When constructing the signature string, keep the following in mind:
- The VERB portion of the string is the HTTP verb, such as GET or PUT, and must be uppercase.
- All new-line characters (\n) shown are required within the signature string.
- The following headers must be signed if present. You can sign any other header too.
- Content-Type, Content-SHA256, TresoritDate, UserId
- Please note, that the order of the header names in the HMACHeaders header must be the same as they appear in the canonical string.
- Also note, that this procedure is case-sensitive because of the cryptographic signature, so leave any text casing unchanged, as the texts appear in the HTTP request.
Construction of the canonical string:
- In the first line write the HTTP request method with uppercase letters, and terminate the line with a single "\n" character (line feed).
- In the second line insert the request combined request path and query string of the request URI. (this is the part that follows the domain after a forward slash, but not containing the slash). For example, the request path and query of the following address https://sub.example.com/part1/part2?value=42 is "part1/part2?value=42". terminate the line with a line feed (\n) character.
- In the next lines populate the headers listed in the HMACHeaders header in the same order, exactly one-header in each line. The format is {HeaderName}:{HeaderValue} where {HeaderName} stands for the header name and {HeaderValue} is the value of the header. Note, that there is only a semicolon between the header name and value, and there are no white spaces. terminate each line with a "\n" char, EXCEPT the last one.
| Example | Original HTTP request |
|---|---|
| <body> | |
| Assembling canonical request string | |
"POST" + "\n" +"api/v1/users/admin/setuserstate" + "\n" +"Content-Type" + ":" + "application/json" +"Content-SHA256" + ":" + "b11b56c53beb010850dbc00bf8f0ea12cdc9343075d7756efff556ea5163f43f" + "\n" +"TresoritDate" + ":" + "2014-05-05T05:05:05Z" + "\n" +"UserId" + ":" + "[email protected]"
| | Canonical request string | | POSTapi/v1/users/admin/setuserstateContent-Type:application/jsonContent-SHA256:b11b56c53beb010850dbc00bf8f0ea12cdc9343075d7756efff556ea5163f43fTresoritDate:2014-05-05T05:05:05ZUserId:[email protected] |
Step 3. - Signing
In this step the canonical request will be signed. The signing algorithm is the following:
BASE64ENCODE( HMACSHA256( key = HEXTOBIN( AdminKey ), data = UTF8TOBINARY( CanonicalString ) ) )
Where:
- AdminKey is any of the the primary or secondary admin keys provided at subscription time. (See part Administrative API for more information on primary and secondary admin keys.)
- CanonicalString is the canonicalized request string assembled in the previous step
- BASE64ENCODE() is a function which transforms binary data to a Base64 encoded string.
- HEXTOBIN() is a function which converts a hex encoded string to binary data.
- UTF8TOBINRAY() is a function which encodes all the characters in the specified string into a sequence of bytes using the UTF8 text codec
- HMACSHA256(key, data) is a function to compute the keyed-hash message authentication code (HMAC) of the input data, keyed with the binary input key key and using the SHA256 algorithm as hash function.
Note: Please note, that the binary-ascii conversions are needed because the cryptographical functions are usually take their inputs (key and data) in binary form.
| Example
| AdminKey |
|---|
| AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |
| Canonical string |
| <body> |
| Signature |
Lb/UORGQAGEh8BnqKKtJ5yYdMa009yhQAxFjE/24JYg=
|
Example code for such signing algorithm:
C# signing example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace Rextester
{
public class Program
{
public static byte[] StringToByteArray(string hex) {
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
public static void Main(string[] args)
{
var key = ""; // Your hexadecimal key
var text = ""; // Your string to sign
using(var hash = new System.Security.Cryptography.HMACSHA256(StringToByteArray(key)))
{
var signature = hash.ComputeHash(System.Text.Encoding.UTF8.GetBytes(text));
Console.WriteLine(System.Convert.ToBase64String(signature));
}
}
}
}
PHP signing example
<?php
$key = ""; // Your hexadecimal key
$text = ""; // Your string to sign
echo base64_encode(hash_hmac('sha256', $text, hex2bin($key), true));
?>
JS signing example (browser)
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/core.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/hmac-sha256.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/enc-hex.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/enc-base64.min.js"></script> <script> var key= ""; // Your hexadecimal key var text = ""; // Text to hash var hash = CryptoJS.HmacSHA256(text, CryptoJS.enc.Hex.parse(key)); document.write(CryptoJS.enc.Base64.stringify(hash)); </script>
Step 4. - Adding authorization header
The last step is where the Authorization header is assembled and added to the prepared request.The header value is assembled according to the following format: AdminKey {SignatureBase64}
Note, that the value always starts with the constant string "AdminKey" followed by a single space and then with the base64 encoded value of the previously computed signature.
| Example |
Authorization: AdminKey Lb/UORGQAGEh8BnqKKtJ5yYdMa009yhQAxFjE/24JYg=
|
The assembled final query:
| Example | <body> |