π 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 IDDate: RFC 1123 formatted timestampSignature: HMAC-SHA256 signature of the request
π HMAC Headers Requiredβ
| Header | Description | Example |
|---|---|---|
| Authorization | Your HMAC Key ID | TC-API-CLIENT-abc123def456 |
| Date | RFC 1123 formatted UTC timestamp | Tue, 10 Jun 2025 14:17:50 GMT |
| Signature | HMAC-SHA256 signature | TC 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β
- Secret Key Security: Never expose
hmacSecretKeyin client-side code, logs, or version control - Date Header Format: Must be RFC 1123 format (
new Date().toUTCString()in JavaScript) - Query Parameter Sorting: Query parameters must be sorted alphabetically by key and lowercased
- Header Sorting: Include only
authorizationanddateheaders in canonical string - Body Hashing: Use SHA256 hash of the raw request body