Request Authentication

Introduction

The Titan REST API uses a custom HTTP scheme based on a keyed HMAC (Hash Message Authentication Code) for authentication. To authenticate a request, you first concatenate selected elements of the request to form a string. You then use your Titan signing key to calculate the HMAC of that string. We call this process "signing the request," and we call the output of the HMAC algorithm the signature, because it simulates the security properties of a real signature. Finally, you add this signature as a parameter of the request by using the syntax described in this section.

When the system receives an authenticated request, it retrieves the credentials that you claim to have and computes a signature for the message it received using the supplied credentials. It then compares the signature it calculated against the signature presented by the requester. If the two signatures match, the system concludes that the requester has access to the Titan API Signing Key and therefore acts with the authority of the principal to whom the key was issued. If the two signatures do not match, the request is rejected and the system responds with an error message.

Authentication Headers

The Titan REST API uses two HTTP headers to convey message authentication information: X-TCS-AccessKeyID and X-TCS-Signature.

Customers are issued an Access Key ID and an API Signing Key as credentials. An API Signing Key must be treated as highly sensitive information. Your API Signing Key is displayed with Base64 encoding, but must be decoded into a byte array for use in the HMAC funtion.

The X-TCS-Signature element is the HMAC-SHA1 or HMAC-SHA256 of selected elements from the request and will vary from request to request. The Access Key issued will specify the HMAC algorithm to use.

StringToSign =
    HTTP-Verb + "\n" +
    Content-MD5 + "\n" +
    Content-Type + "\n" +
    Date + "\n" +
    NormalizedTitanHeaders +
    ResourcePathAndQueryString
        
NormalizedTitanHeaders = <described below>
ResourcePathAndQueryString = <the full path to the resource plus any query string>
if (HMACAlgorithm = "HMACSHA256") {
    Signature = Base64(HMAC-SHA256(APISigningKey, UTF-8-Encoding-Of(StringToSign)))
} else if (HMACAlgorithm = "HMACSHA1") {
    Signature = Base64(HMAC-SHA1(APISigningKey, UTF-8-Encoding-Of(StringToSign)))
}

For Titan request authentication, use your API Signing Key as the key, and the UTF-8 encoding of the StringToSign as the message. The X-TCS-Signature request header value is constructed by Base64 encoding the resulting signature.

Normalized Titan Headers

To normalize Titan headers, order the HTTP headers alphabetically. In the case of multiple entries for the same header name, order the values as well. der beginning with X-TCS- (case insensitive), except for X-TCS-Signature, and do the following:

  1. Convert each header name to lower case (e.g., X-TCS-Date becomes x-tcs-date)
  2. For any duplicate headers, concatenate the ordered values with no whitespace with a single comma as delimiter. Values that contain embedded whitespace (including newlines) must replace the contiguous whitespace with a single space character for signature calculation.
  3. Remove any whitespace around the header name, colon, and header value.
  4. Append a newline (\n)

Concatenate the resulting headers to form NormalizedTitanHeaders.

Date Validation

When X-TCS-Date is supplied, the standard Titan format of milliseconds after UNIX epoch must be used, and this value will be used in place of the standard HTTP Date header when validating the signature.

If the date supplied in the request varies from the Titan servers by more than 60 minutes, the request shall be rejected with a 4XX series HTTP status.

Sample Credentials

The examples below use the following sample credentials. These credentials cannot be used for real access.

Access Key 2KR022LI8RQU8KYC4JY7Q1VNW
API Signing Key

qFRRH37VfFULIEjPFwlV20uM4VW42+p3zdJ+4k+TqDsIlKjfA//ezr9fhv7u8b40yy6+uViT2oWH5zT/Ztpc8g==

This value is Base64 encoded and must be converted to a byte array for signing.

API Signing Algorithm HMACSHA256

Example GET

Route v1/Time
HTTP Verb GET
Example HTTP Request
GET /v1/Time HTTP/1.1
Host: api.mytitan.net
Accept: application/json
Date: Thu, 03 Dec 2015 22:49:34 GMT
X-TCS-Date: 1449182974202
X-TCS-AccessKeyID: 2KR022LI8RQU8KYC4JY7Q1VNW
X-TCS-Signature: otR/3gPJRMNu8RuG0B5/6gP3paSZi66QWUD5BXuVl00=
Constructing the Signature
HTTP-Verb = "GET"
Content-MD5 = ""
Content-Type = ""
Date = "1449182974202"
NormalizedTitanHeaders = "x-tcs-accesskeyid:2KR022LI8RQU8KYC4JY7Q1VNW\nx-tcs-date:1449182974202\n"
ResourcePathAndQueryString = "/v1/Time"
Signing Algorithm = "HMACSHA256"
StringToSign = "GET\n\n\n1449182974202\nx-tcs-accesskeyid:2KR022LI8RQU8KYC4JY7Q1VNW\nx-tcs-date:1449182974202\n/v1/Time"
Signature Bytes = 0xA2D47FDE03C944C36EF11B86D01E7FEA03F7A5A4998BAE905940F9057B95974D
Signature = "otR/3gPJRMNu8RuG0B5/6gP3paSZi66QWUD5BXuVl00="
Sample cURL call
curl
    -X GET
    -H "Host: api.mytitan.net"
    -H "Accept: application/json"
    -H "Date: Thu, 03 Dec 2015 22:49:34 GMT"
    -H "X-TCS-Date: 1449182974202"
    -H "X-TCS-AccessKeyID: 2KR022LI8RQU8KYC4JY7Q1VNW"
    -H "X-TCS-Signature: otR/3gPJRMNu8RuG0B5/6gP3paSZi66QWUD5BXuVl00="
    https://api.mytitan.net/v1/Time

Example POST

Route v2/Clients/{clientId}/EFiles
HTTP Verb POST
Example HTTP Request
POST /v2/Clients/9b1fd489-e23a-4815-9827-bde1b437911b/EFiles HTTP/1.1
Host: api.mytitan.net
Accept: application/json
Date: Fri, 30 Dec 2022 11:05:22 GMT
X-TCS-Date: 1672398322096
X-TCS-AccessKeyID: 5HLR98YILJ8IS04QRYYSW0E40
X-TCS-Signature: zkAH0sudTfydSZ64JGNG//qwony5dqA2jsLzR1dpRY4=
Content-Type: application/json
Content-MD5: b5xj8MRBhWnb6R6hnft3WQ==
{"FacilityId":10000,"EFileApplicationReferenceId":5555,"FileName":"Test file Name","DateOfFile":"2022-12-30T13:04:51.0663212+02:00","Bytes":"","Description":"Test","Tags":["test tag"],"SkipDuplicateFileName":true,"FolderId":null,"FilePath":null}
Constructing the Signature
HTTP-Verb = "POST"
Content-MD5 = "b5xj8MRBhWnb6R6hnft3WQ=="
Content-Type = "application/json"
Date = "1672398322096"
NormalizedTitanHeaders = "x-tcs-accesskeyid:5HLR98YILJ8IS04QRYYSW0E40\x-tcs-date:1672398322096\n"
ResourcePathAndQueryString = "/v2/Clients/9b1fd489-e23a-4815-9827-bde1b437911b/EFiles"
Signing Algorithm = "HMACSHA256"
StringToSign = "POST\nb5xj8MRBhWnb6R6hnft3WQ==\napplication/json\n1672398322096\nx-tcs-accesskeyid:5HLR98YILJ8IS04QRYYSW0E40\nx-tcs-date:1672398322096\n/v2/Clients/9b1fd489-e23a-4815-9827-bde1b437911b/EFiles"
Signature = "zkAH0sudTfydSZ64JGNG//qwony5dqA2jsLzR1dpRY4="
Sample cURL call
curl
    -X POST
    -H "Host: api.mytitan.net"
    -H "Accept: application/json"
    -H "Date: Fri, 30 Dec 2022 11:05:22 GMT"
    -H "X-TCS-Date: 1672398322096"
    -H "X-TCS-AccessKeyID: 5HLR98YILJ8IS04QRYYSW0E40"
    -H "X-TCS-Signature: zkAH0sudTfydSZ64JGNG//qwony5dqA2jsLzR1dpRY4="
    -H "Content-Type: application/json"
    -H "Content-MD5: b5xj8MRBhWnb6R6hnft3WQ=="
    https://api.mytitan.net/v2/Clients/9b1fd489-e23a-4815-9827-bde1b437911b/EFiles
    --data-binary '{"FacilityId":10000,"EFileApplicationReferenceId":5555,"FileName":"Test file Name","DateOfFile":"2022-12-30T13:04:51.0663212+02:00","Bytes":"","Description":"Test","Tags":["test tag"],"SkipDuplicateFileName":true,"FolderId":null,"FilePath":null}'