Skip to main content

πŸ” HMAC Authentication for API Security

Welcome to the guide for HMAC Authentication in the Token City Blockchain API.

This guide shows you how to generate HMAC signatures to authenticate your API requests.

🌟 Objective: Generate HMAC-SHA256 signatures for secure API authentication.


πŸ“š OpenAPI Documentation​


✨ What is HMAC Authentication?​

HMAC (Hash-based Message Authentication Code) is used to verify that API requests are authentic and haven't been tampered with. Every request to the Token City API must include three headers:

  • Authorization: Your HMAC Key ID
  • Date: RFC 1123 formatted timestamp
  • Signature: HMAC-SHA256 signature of the request

πŸ“‹ HMAC Headers Required​

HeaderDescriptionExample
AuthorizationYour HMAC Key IDTC-API-CLIENT-abc123def456
DateRFC 1123 formatted UTC timestampTue, 10 Jun 2025 14:17:50 GMT
SignatureHMAC-SHA256 signatureTC sha256 base64EncodedSignature==

πŸ“ How to Generate HMAC Signature​

TypeScript/JavaScript Implementation​

function calculateHmacSignature(
hmacKeyId: string,
hmacSecretKey: string,
date: string,
url: string,
payload: string,
method = "POST",
reqQuery?: any[]
) {
let encodedQueryParams;
if (reqQuery) {
const queryParams: { key: string; value: string }[] = [];

for (const query in reqQuery) {
queryParams.push({
key: query,
value: reqQuery[query],
});
}
queryParams.sort((a, b) => {
return a.key.localeCompare(b.key);
});

encodedQueryParams = queryParams.reduce((pv, cv, i) => {
if (i == queryParams.length - 1)
return pv + `${cv.key.toLowerCase()}=${cv.value.trim()}`;
return pv + `${cv.key.toLowerCase()}=${cv.value.trim()}&`;
}, "");
}

const headers: { key: string; value: string }[] = [
{
key: "authorization",
value: hmacKeyId,
},
{
key: "date",
value: date,
},
];

const encodedHeaders = headers.reduce((pv, cv, i) => {
if (i == headers.length - 1)
return pv + `${cv.key.toLowerCase()}:${cv.value.trim()}`;
return pv + `${cv.key.toLowerCase()}:${cv.value.trim()}\n`;
}, "");

const contentBytes = CryptoJS.enc.Utf8.parse(payload);
const contentHash = CryptoJS.SHA256(contentBytes);
const queryParams = encodedQueryParams ?? "";

const canonicalString =
method +
"\n" +
new URL(url).pathname +
"\n" +
queryParams +
"\n" +
encodedHeaders +
"\n" +
contentHash;

const signatureBytes = CryptoJS.HmacSHA256(canonicalString, hmacSecretKey);
const signature = CryptoJS.enc.Base64.stringify(signatureBytes);

return signature;
}

Usage Example​

const hmacKeyId = "TC-API-CLIENT-abc123def456";
const hmacSecretKey = "sk_live_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6";
const date = new Date().toUTCString(); // RFC 1123 format
const url = "https://api.tokencity.com/v2/erc3643/deploy";
const payload = JSON.stringify({
name: "Green Bond Token",
symbol: "GBT",
decimals: 18,
erir: "0xErirAddress...",
issuer: "0xIssuerAddress...",
operator: "0xOperatorAddress...",
maxSupply: 1000000,
});

const signature = calculateHmacSignature(
hmacKeyId,
hmacSecretKey,
date,
url,
payload,
"POST"
);

HTTP Request Example​

POST /v2/erc3643/deploy HTTP/1.1
Host: api.tokencity.com
Content-Type: application/json
Authorization: TC-API-CLIENT-abc123def456
Date: Tue, 10 Jun 2025 14:17:50 GMT
Signature: TC sha256 a3f8c7b2e1d9f4a6c5b8e7d2f1a9c8b6e5d4f3a2c1b9e8==

{
"name": "Green Bond Token",
"symbol": "GBT",
"decimals": 18,
"erir": "0xErirAddress...",
"issuer": "0xIssuerAddress...",
"operator": "0xOperatorAddress...",
"maxSupply": 1000000
}

⚠️ Important Notes​

  1. Secret Key Security: Never expose hmacSecretKey in client-side code, logs, or version control
  2. Date Header Format: Must be RFC 1123 format (new Date().toUTCString() in JavaScript)
  3. Query Parameter Sorting: Query parameters must be sorted alphabetically by key and lowercased
  4. Header Sorting: Include only authorization and date headers in canonical string
  5. Body Hashing: Use SHA256 hash of the raw request body