API Authorization Overview

The Issuetrak API requires specific, custom authorization headers to be added to each HTTP request targeting an API operation endpoint. The following custom authorization headers must be defined.

Issuetrak API Authorization Header Name Issuetrak API Authorization Header Purpose
X-Issuetrak-API-Request-ID Provides a unique request ID to mitigate the risk of cache-replay attacks.
X-Issuetrak-API-Timestamp Provides a timestamp to mitigate the risk of replay attacks.
X-Issuetrak-API-Authorization Provides an HMAC hash of specific data representing the request.


 

Overview of Authorization Header Steps

Consider the following raw HTTP request made to a local development server running the Issuetrak API with the Issuetrak API authorization headers highlighted.

POST http://local.issuetrakapi.com/api/v1/attachments HTTP/1.1
Accept-Language: en-US
Accept: application/json 
X-IssueTrak-API-Request-ID: c3838d04-46f8-43d6-92fd-62b3d0b59f3e
X-IssueTrak-API-Timestamp: 2014-09-10T17:28:08.3227351Z
X-IssueTrak-API-Authorization: SkFHCIWKyF2DXEOvrpyJzAHH52/RL3OhJGFsqFau6A7oMx5JUVmm3oC9lJFzLpISsU2Vngk56xayygSsd5WmKw==
Content-Type: application/json; charset=utf-8
Host: local.issuetrakapi.com
Content-Length: 111
Expect: 100-continue
Connection: Keep-Alive

{"IssueNumber":0,"FileName":null,"CreatedBy":null,"CreatedDate":null,"FileSizeInBytes":null,"FileContent":null}

Ignoring the JSON data transmitted in the request body (in this example, the data are invalid and will generate an error response from the API) and instead focusing on how the authorization headers were constructed, the headers were created in four steps.


Step 0: Identify the Current API Key

The API key is a 32-byte length, base-64 encoded byte array (example: wV4JA/59PUf6XjiMF1om+Eg+D4rQlE8WGRTybNIkdrs=) unique to each Issuetrak API deployment. The API key is generated using the Issuetrak.API.KeyTool application and is produced using a cryptographically-strong random number generation algorithm. Once generated, the API Key is stored within the Issuetrak database as an application parameter.

The API Key should never be transmitted in any API HTTP request. Instead, the API key is only used to generate an HMAC hash for an API request. The API server-using the same API key retrieved from the application parameters-will then compute an HMAC hash for the request to be authorized and will compare the computed hash to the transmitted hash to determine the validity of the authorization headers. In this manner, the API key is never exposed as plaintext in any HTTP request or HTTP response.


Step 1: Generate a Unique Request ID

The API expects to receive a request ID in the form of a Globally Unique Identifier (GUID) 1. GUIDs are trivial to generate in a variety of programming languages 2. For example, in Microsoft .NET Framework languages, the System.Guid.NewGuid 3 method may be used as in the following C# code fragment:

String requestID = Guid.NewGuid().ToString();

The generated request GUID value is submitted with the HTTP request as the value for the
X-Issuetrak-API- Request-ID HTTP header. This same value will be used in Step 3, the generation of the SHA512 HMAC hash for the request.


Step 2: Generate a Request Timestamp

The API will examine and attempt to parse the request timestamp to a valid datetime value. When specifying the request timestamp text representation, regardless of the API consumer’s local time zone, generate the timestamp using Coordinated Universal Time (UTC) 4. This timestamp value should resemble the following example: 2014-09-10T17:57:27.7766148Z Notice that the seconds portion contains seven decimal digits.

The API will attempt to parse the request timestamp to a UTC datetime representation and will compare the timestamp to a request time boundary window to determine if the request’s timestamp falls within the acceptable boundary. This time validation step attempts to reduce the chance that a replay attack 5 is issued against the server.

As an example of how to generate an appropriate request timestamp header value, consider the following C# code fragment:

// The “O” or “o” standard format specifier represents a custom date and time 
// format string using a pattern that preserves time zone information and  string that
// emits a resultcomplies with ISO 8601.
String requestTimestamp = DateTime.UtcNow.ToString(“O”);

The generated request timestamp value is submitted with the HTTP request as the value for the
X-IssueTrak-API- Timestamp HTTP header.


Step 3: Generate a SHA512 HMAC Hash for the Request

To generate an HMAC hash, the message to be hashed will be formed using a combination of data relevant to the particular request. In particular, to generate the message, include the following concatenated message elements delimited by newline characters (“\n”):

  1. The uppercase HTTP verb for the request e.g., “GET”, “POST”, or “PUT”.
  2. The lowercase unique GUID 6 for the request (see Step 1).
  3. The timestamp for the request is submitted in the request timestamp header of Step 2.
  4. The lowercase URL-decoded absolute path 7 of the request. Please note that the absolute path does not include the scheme, hostname, or query portion of the URL.
  5. The URL-encoded request query 8 or a blank string if the query URI element is not present.
  6. The text-serialized version of any request content 9 submitted with the request with the serialization format selected based on the request encoding used for the request.

Consider the sample HTTP request from the beginning of the article:

  • The HTTP verb for the sample request is “POST”.
  • The lowercase, unique GUID for the sample request is: “c3838d04-46f8-43d6-92fd-62b3d0b59f3e”.
  • The timestamp for the sample request is: “2014-09-10T17:57:27.7766148Z”.
  • The lowercase, URL-decoded absolute path for the request is “/api/v1/attachments”.
  • There is no query for the request URL, so a blank string is substituted: “”.

Note that the request text is a combined total of 6 lines, if there is no query or body, for example searching for an issue by issue number. These lines should be still included as blank lines, to allow the HMAC hash to be generated correctly.

Since the “Accept” HTTP header for the request is Accept: application/json, the serialization of the requested content is performed using a JSON serializer 10. Concatenating these elements with “\n” (New Line) characters produces the following text block. Do not include a “\n” sequence after the JSON representation.

POST
c3838d04-46f8-43d6-92fd-62b3d0b59f3e
2014-09-10T17:57:27.7766148Z
/api/v1/attachments

{"IssueNumber":0,"FileName":null,"CreatedBy":null,"CreatedDate":null,"FileSizeInBytes":null,"FileContent":null}

A Hash-based Message Authentication Code (HMAC) 11 should now be generated for this request using the SHA512 12 hash function. When calculating the hash, use a UTF-8 13 text encoding for any string-to-byte array transformations.

A sample C# function for generating an SHA-512 HMAC hash is presented below.

String ComputeHMACHash(String hashKey, String messageToBeHashed) 
{
     String hashText = null; 
     Byte[] hashKeyBytes = Encoding.UTF8.GetBytes(hashKey);
     using (HMACSHA512 hmacHashGenerator = new HMACSHA512(hashKeyBytes)) 
     { 
          Byte[] messageToBeHashedBytes = Encoding.UTF8.GetBytes(messageToBeHashed); 
          Byte[] hashedMessageBytes = hmacHashGenerator.ComputeHash(messageToBeHashedBytes); 
          hashText = Convert.ToBase64String(hashedMessageBytes); 
     }
     return hashText;
}

As an example of the output, if the “ComputeHMACHash” in the example above were called using the sample API key and the sample request text representation from the previous examples, the resulting base-64 encoded byte array representing the SHA-512 HMAC hash would be:

SkFHCIWKyF2DXEOvrpyJzAHH52/RL3OhJGFsqFau6A7oMx5JUVmm3oC9lJFzLpISsU2Vngk56xayygSsd5WmKw==

The length of the base-64 encoded representation of the hash byte array is 88 characters. This is the expected value since the SHA-512 hash algorithm will produce a 64-byte array, and, in a base-64 14 encoding, 4 × (𝑛/3) characters will be used to represent n bytes with padding added so that the resulting base-64 encoded text has a length that is a multiple of 4.

Total Base-64 Encoded Characters for SHA-512 Hash (n = 64) = (4 × (64/3)) = 85.33…
Rounded to the nearest multiple of 4 yields 88 characters.

This computed hash text is submitted with the HTTP request as the value for the X-IssueTrak-API-Authorization HTTP header.


 

More Information

1 See the “GUID” Wikipedia article at: http://goo.gl/yfnR53
2 For example, see the “com_create_guid” PHP function reference at: http://goo.gl/gnmg6r
3 See the “Guid.NewGuid” MSDN reference at: http://goo.gl/5c3wCp
4 See the “Coordinated Universal Time” Wikipedia article at: http://goo.gl/QGpQCU
5 See the “Replay Attack” Wikipedia article at: http://goo.gl/j84RQT
6 The lowercase formatting for the GUID value is an attempt to standardize the many different formatting styles across platforms, e.g., Windows OS Registry format wherein a GUID may have a form similar to the following sample: {22FBF9A9-226B-43A5-8BAC-11AF6DBA5C6B}
7 See the “Uri.AbsolutePath Property” MSDN reference at: http://goo.gl/59ZyiA
In particular, note, “The path information does not include the scheme, hostname, or query portion of the URI."
8 See the “Uri.Query Property” MSDN reference at: http://goo.gl/s0hBul
9 This serialized request content should be the same as any request payload submitted in the request body for a POST or PUT request.
10 If the “Accept” header value were “text/xml”, an XML serializer would need to be applied.
11 See the “Hash-based message authentication code” Wikipedia article at: http://goo.gl/e21VV
12 See the “SHA-2” Wikipedia article at: http://goo.gl/JbNoX
13 See the “UTF8Encoding Class” MSDN article at: http://goo.gl/ftqqD8
14 See the “Base64” Wikipedia article at: http://goo.gl/8MMwK In particular, note the padding rules for Base-64 encoding.