# Authentication

WARNING

  • Code examples within this document are based on NodeJS using the Axios HTTP client and CryptoJS packages.
  • You need only use this HMAC shared secret if you’re accessing CLS remotely. If you’re using the Report API from within CLS (eg via a Custom Module Page) this step is not required.

# Introduction

To make a valid request to the Report API a special hash will need to be transported in the payload. This hash is generated in part with the request and the shared secret (as generated in Configuring Report API keys).

# What is HMAC Authentication

HMAC (Hash-based Message Authentication Code) is a type of message authentication code (MAC) that is used to verify the integrity and authenticity of a message. It involves a cryptographic hash function and a secret shared key. The hash function is used to generate a fixed-size output from an arbitrary-size input, while the secret key is used to authenticate the message. HMAC can be used for both data integrity and authentication, and it is often used in combination with other security protocols such as SSL/TLS, SSH, and IPsec1.

HMAC provides several benefits over other types of MACs. For example, it can be used to verify both the data integrity and authenticity of a message simultaneously. It also provides authentication using a shared secret instead of using digital signatures with asymmetric cryptography.

# Janison's use of HMAC Authentication

Janison CLS requires the following headers to be set in order to work (examples are based on NodeJS using the Axios Http client):

const axios_options = {
    // ...,
    headers : {
        "Authorization" : `JanisonAPI {{user_id}}:{{generated_hash}}`,
        "Date" : `{{utc_timestamp}}`, // RFC1123 Format
        "Method" :  // or 'POST'
    },
    // ...,
}

Looking at the above exmple there are a few things to unpack, see below for a breakdown of each header and how you can create the above object.

# Authorization Header

This header consists of a user_id (which is the API Username that needs to be generated within the Janison CLS); and the generated_hash which is a SHA256 encoded string generated by completing the following steps

  1. Converting the Janison API Key into a Base64 String.
const base_64_api_key = CryptoJS.enc.Base64.parse(api_key);
  1. Combining a string using the following template
const hash_data = `${http_method}\n${uri}\n${user_id}\n${utc_timestamp}\n`; 

In production you would be aiming to generate an output that looks like this:

console.log(hash_data)
/** 
 * GET
 * https://example.canopi.com.au/api/reports/runreport/example-report
 * apiuser
 * Sun, 01 Jan 2023 00:00:00 GMT
 */

process.stdout.write(hash_data)
/** 
 * GET\nhttps://example.canopi.com.au/api/reports/runreport/example-report\napiuser\nSun, 01 Jan 2023 00:00:00 GMT\n
 */
  1. Creation of the generated_hash using a HMACSHA265 Method by combining the hash_data and api_key
  const hash_data__utf_array = CryptoJS.enc.Utf8.parse(hash_data);
  const hashed_message__sha256 = CryptoJS.HmacSHA256(hash_data__utf_array, base_64_api_key);
  const hased_message__string = hasedMessage.toString(CryptoJS.enc.Base64);
  1. Combining the user_id and generated_hash together
const axios_options = {
    // ...,
    headers : {
        "Authorization" : `JanisonAPI {{user_id}}:{{generated_hash}}`,
        // ...
    },
    // ...,
}

# Date Header

The date header is just a UTC Timestamp based on the RFC2616 ISO Standard, Section 14.18.

Using NodeJS you can lean on the built-in Date class to generate this using the Date .toUTCString() method.

const utc_timestamp = new Date().toUTCString();

const axios_options = {
    // ...,
    headers : {
        // ...
        "Date" : utc_timestamp,
    },
    // ...,
}

# Method Header

The method header is just a string consisting of the HTTP method you are using to connect to the Janison CLS API. Generally this will be using the GET method, however, you are also able to use POST with the Janison CLS API.

const axios_options = {
    // ...,
    headers : {
        // ...
        "Method" : `GET` // or 'POST'
    },
    // ...,
}