The API offers a way to retrieve the configuration file, which contains the settings edited through the administrative dashboard. In order to obtain the configuration, the API client must prove that it holds the site secret. To do this the client must provide a response to a challenge issued by the API server. The API server would never ask for the client to send the plaintext site secret over the network, nor would it ever send the secret to the client.
Challenges are 128 random bytes encoded as lowercase hex digits resulting in a 256 character string. The response to a challenge is calculated using the following formula: sha512(sha512(sha512(sha512(sha512(secret + challenge))))) Or in other words, first concatenate the site secret and challenge strings (in that order), then apply the sha512 hashing algorithm to the combined string 5 times. The result of the last hashing is the challenge response.
Below are the steps that must be carried out to receive and answer a challenge:
First the API client makes an HTTP GET request to https://api.getnitropack.com/config/getchallenge/:site_id
The API will return a JSON structure as follows:
{ "cid": "...", // Challenge ID (64 character string) "sc0": "...", // Server challenge 0 (256 character string) "sc1": "...", // Server challenge 1 (256 character string) "resp": "..." // Response to server challenge 0 (128 character string) }
The challenge ID is to be submitted along with the challenge response. Server challenge 0 is used for the client to verify that the challenge came from the API server. The client should calculate the expected response for server challenge 0 using the site secret and the formula above and compare the result with the "resp" key using a cryptographically secure string comparison algorithm (ex. PHP's hash_equals function).
If this comparison fails, the client should terminate its attempt to fetch the configuration and notify the administrator managing the site running the client.
Once the client has established that the challenge came from the API server, it can proceed with calculating the response to server challenge 1, again using the site secret and the formula above.
Then the client should make a second HTTP GET request, this time to https://api.getnitropack.com/config/get/:site_id where :site_id
matches the :site_id
from the first request.
This request should include two additional headers:
X-Challenge-ID: The challenge ID from the JSON response of the previous request
X-Challenge-Response: The challenge response calculated from Server challenge 1
The response to this request will always be JSON formatted. If the challenge response was correct, then the response will have an HTTP status 200 and the body will contain the configuration for the given :site_id. If something went wrong, then the response will have an HTTP status 403 and the body will be {"error":"Invalid request"} Note that by design the API will return the same error with no specific explanation for all issues, including wrong a site_id, wrong or expired challenge id, or incorrect challenge response.
Challenges expire 30 seconds after they are created, after which even a correct challenge response will not be accepted.
API requests which deal with non-public data have to be signed by clients with the site secret. Additionally, for those requests it is strongly recommended for the client to verify the signature that the server returns along with the response to ensure the data is coming from api.getnitropack.com
Both request and response signatures are keyed-hash message authentication codes (HMAC) generated using SHA512 as the underlying hashing algorithm.
For requests, the signed data includes:
Headers are included in the signed data as a comma separated list of header:value entries, where the header name and its value are separated by a single colon (:) character, without any spaces. The header names are included in lower case, with any "-" characters converted to "_". The signature header(X-Nitro-Signature) should not (and realistically cannot) be included in this list. The headers need to be sorted alphabetically by header name. For example - for a request with the following two headers: X-Nitro-Visitor-Addr: 1.2.3.4, X-Nitro-Url: https://example.com/ the header section of the signed data will look as follows: x_nitro_url:https://example.com/,x_nitro_visitor_addr:1.2.3.4
Query parameters and POST data parameters are treated the same way. If there is a POST parameter that has the same key name as a query parameter it is ignored in favor of the query parameter. The format of this section of the signed data is the same as the one for headers - key:value pairs (with the key and value separated by a colon) in a comma separated list, sorted alphabetically by the parameter name. Note that the parameter values used when building the data for signing must not be URL encoded. For example - for a POST request to https://api.getnitropack.com/some/endpoint?queryparam1=queryvalue1&queryparam2=queryvalue2 with a POST body postdata1=postvalue1&postdata2=postvalue2 the parameters section of the signed data will look as follows: postdata1:postvalue1,postdata2:postvalue2,queryparam1:queryvalue1,queryparam2:queryvalue2
Altogether the signed data comprises of the url path, headers and parameters sections separated by the pipe (|) character.
Putting the above three examples together, the entire data for signing looks as follows:
Let :site_id
be hKExPwq2RgVKjierq, API path /tags/get/, headers in alphabetical order and converted to lower case x_nitro_url:https://example.com/,x_nitro_visitor_addr:1.2.3.4, POST and query data postdata1:postvalue1,postdata2:postvalue2,queryparam1:queryvalue1,queryparam2:queryvalue2.
Result:
/tags/get/hKExPwq2RgVKjierq|x_nitro_url:https://example.com/,x_nitro_visitor_addr:1.2.3.4|postdata1:postvalue1,postdata2:postvalue2,queryparam1:queryvalue1,queryparam2:queryvalue2
If nitro headers are not present then we still have to include the divider (|).
Example:
/tags/get/hKExPwq2RgVKjierq||postdata1:postvalue1,postdata2:postvalue2,queryparam1:queryvalue1,queryparam2:queryvalue2
If there are no nitro headers and post/query parameters:
/tags/get/hKExPwq2RgVKjierq||
Generating the signature involves calculating the HMAC of the above data string using SHA512 as the hashing algorithm and the site secret as the shared secret key. An example in PHP (if site ID is hKExPwq2RgVKjierq and site secret is hKExPwq2RgVKjierqhKExPwq2RgVKjierq): $signature = hash_hmac('SHA512', '/tags/get/hKExPwq2RgVKjierq|x_nitro_url:https://example.com/,x_nitro_visitor_addr:1.2.3.4|postdata1:postvalue1,postdata2:postvalue2,queryparam1:queryvalue1,queryparam2:queryvalue2', 'hKExPwq2RgVKjierqhKExPwq2RgVKjierq');
The resulting signature should be placed in the X-Nitro-Signature header of the HTTP request.
Upon receiving a response with HTTP status 200, the API client needs to verify its signature. Non-200 responses indicate an error and are not signed. The API server will return a signature in the X-Nitro-Signature header of the response. To verify it, calculate the HMAC of the entire response body (and only the body, do not include the headers) using again SHA512 as the hashing algorithm and the site secret as the shared secret key. If the signature the client computes and the one provided by the server do not match, the client should discard the response and alert the administrator managing the site running the client.
PHP and curl examples:
Values of $siteID and $siteSecret can be obtained via Nitropack.com->Dashboard->Connect Your Website.
Values used in the examples below are fictional and just for illustration purposes.
$siteID = 'hKExPwq2RgVKjierq'; $siteSecret = 'hKExPwq2RgVKjierqhKExPwq2RgVKjierq'; // Purge URL cache
$signature = hash_hmac('SHA512', "/cache/purge/$siteID||url:https://example.com/page/", $siteSecret); Calculated signature is: 9113876a4742c214b686af4e4f1f46c097fa31b2739fff40b8d9c3bd6d0b6661f598efacb860ab76435ef0cfb2cc0ef041f76c7c3077be88b04f6a63e4517ac6 Curl request with the above calculated signature(as per documentation /cache/purge is a POST request): curl -H "X-Nitro-Signature: 9113876a4742c214b686af4e4f1f46c097fa31b2739fff40b8d9c3bd6d0b6661f598efacb860ab76435ef0cfb2cc0ef041f76c7c3077be88b04f6a63e4517ac6" -d "url=https://example.com/page/" -X POST https://api.getnitropack.com/cache/purge/hKExPwq2RgVKjierq On success and if purge by tag was performed, a list of purged URLs in JSON format will be returned. // Count processed URLs(regardless of state) $signature = hash_hmac('SHA512', "/urls/count/$siteID||", $siteSecret); Calculated signature is: 1f54f22730cd8b363e9eaa1df79152e2159ee0a8bbcfd193f618fe340f091170701fae894c098798993136dfd5fa735280cb6da3e02048c9231ca9b2def3d91e Curl request with the above calculated signature(as per documentation /urls/count is a GET request, but POST request can also be used): curl -H "X-Nitro-Signature: 1f54f22730cd8b363e9eaa1df79152e2159ee0a8bbcfd193f618fe340f091170701fae894c098798993136dfd5fa735280cb6da3e02048c9231ca9b2def3d91e" https://api.getnitropack.com/urls/count/hKExPwq2RgVKjierq On success URL count in JSON format will be returned. // Retrieve tags for a given url $signature = hash_hmac('SHA512', "/tags/get/$siteID||url:https://example.com/page/", $siteSecret); Calculated signature is: e6867e8b0fef9c48afed65f03a9de9ce93e3faf51ff053264ca435c89db36f81bfaecd2a679fe0f94356095c6b91d43a4bae879b380c00dd459bd93cc0e55455 Curl request with the above calculated signature(as per documentation /tags/get is a GET request): curl -H "X-Nitro-Signature: e6867e8b0fef9c48afed65f03a9de9ce93e3faf51ff053264ca435c89db36f81bfaecd2a679fe0f94356095c6b91d43a4bae879b380c00dd459bd93cc0e55455" https://api.getnitropack.com/tags/get/hKExPwq2RgVKjierq?url=https://example.com/page/ On success tags names and values in JSON format will be returned.
Loading...