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:
- Convert each header name to lower case (e.g., X-TCS-Date becomes x-tcs-date)
- 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.
- Remove any whitespace around the header name, colon, and header value.
- 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}' |