.. _api_authentication_hmac: HMACSHA256 Authentication ========================= Introduction ------------ The HMAC stands for Hash-based Message Authentication Code. It involves two key ideas: Message Authentication Code and Hash-Based processing. HMAC is a mechanism to create a Message Authentication Code using a Hash function. For generating the Message Authentication Code using a Hash function, a **Shared Secret Key** is used. This Shared Secret Key must be securely shared between the Client and the Server. Keys Used in HMAC Authentication in Web API -------------------------------------------- The server (Mobilum) generates two keys: - **API Key** (already provided to the partner) - **Private Secret Key** These keys must be provided to the Partner securely (e.g., via email). Once the Partner obtains the private secret key, they must generate a unique **HMAC signature** (hash) containing both the request data and necessary metadata for the server to process the request. The HMAC Flow ------------- The Partner creates a **MAC (Message Authentication Code)** string containing: #. API Key #. HTTP method (POST) #. Request URI (lowercased) #. Request timestamp (UTC Now) #. Nonce - **Request URI**: Must be in lowercase. - **Request Timestamp**: Calculated using UNIX time (seconds since Jan 1, 1970). - **Nonce**: Random string (using a GUID), unique per request. Example URI: :: https://api.mobilum.com/s2s/health?arg1=test1 The Partner then generates a **HASH (unique signature)** using the SHA256 algorithm and the Private Secret Key. Example signature construction: :: var signatureRawData = "{ApiKey}{RequestHTTPMethod}{RequestUri}{RequestTimeStamp}{Nonce}" Without braces: :: 16de9f8b-b414-4c50-b3c8-cf8355683a42POSThttps://api.mobilum.com/s2s/health?arg1=test1167474201375293d8ca0e6453f823fe87315e9483b“ Authorization Header Format: :: Authorization: HMAC-SHA256 ApiKey:Signature:Nonce:Timestamp Example: :: Header Key: Authorization Header Value: HMAC-SHA256 16de9f8b-b414-4c50-b3c8-cf8355683a42:mlf8nvpV2WQ2eOJpdKJ7g3Sl0an9Xhc4PlAzdMihJO8=:85b9ceacde384490825e3b2153bc7684:1674227388 HMAC Implementation Example in C# ---------------------------------- .. code-block:: csharp using System.Net.Http.Headers; using System.Security.Cryptography; using System.Text; using System.Web; class Program { static void Main(string[] args) { RunAsync().Wait(); Console.ReadLine(); } static async Task RunAsync() { Console.WriteLine("Calling the back-end API"); string apiBaseAddress = "https://api.mobilum.com/"; HMACDelegatingHandler customDelegatingHandler = new HMACDelegatingHandler(); HttpClient client = HttpClientFactory.Create(customDelegatingHandler); HttpResponseMessage response = await client.PostAsJsonAsync(apiBaseAddress + "s2s/health"); if (response.IsSuccessStatusCode) { string responseString = await response.Content.ReadAsStringAsync(); Console.WriteLine(responseString); Console.WriteLine("HTTP Status: {0}, Reason {1}. Press ENTER to exit", response.StatusCode, response.ReasonPhrase); } else { string responseString = await response.Content.ReadAsStringAsync(); Console.WriteLine("Failed to call the API. HTTP Status: {0}, Reason {1}", response.StatusCode, response.ReasonPhrase); } } } public class HMACDelegatingHandler : DelegatingHandler { private string ApiKey = "16de9f8b-b414-4c50-b3c8-cf8355683a42"; private string SecretKey = "HtDiRYMtBLmyq7snk2xvh3mO0PrO3HBxVWm85FaQ2CZ7eLqnYYG3gMYz9esmHx8I7m5LTQa5zVnGo3pM"; protected async override Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { try { HttpResponseMessage response = null; string requestUri = request.RequestUri.AbsoluteUri.ToLower(); string requestHttpMethod = request.Method.Method; DateTime epochStart = new DateTime(1970, 01, 01, 0, 0, 0, 0, DateTimeKind.Utc); TimeSpan timeSpan = DateTime.UtcNow - epochStart; string requestTimeStamp = Convert.ToUInt64(timeSpan.TotalSeconds).ToString(); string nonce = Guid.NewGuid().ToString("N"); string signatureRawData = String.Format("{0}{1}{2}{3}{4}", ApiKey, requestHttpMethod, requestUri, requestTimeStamp, nonce); var secretKeyByteArray = Convert.FromBase64String(SecretKey); byte[] signature = Encoding.UTF8.GetBytes(signatureRawData); using (HMACSHA256 hmac = new HMACSHA256(secretKeyByteArray)) { byte[] signatureBytes = hmac.ComputeHash(signature); string requestSignatureBase64String = Convert.ToBase64String(signatureBytes); request.Headers.Authorization = new AuthenticationHeaderValue("HMAC-SHA256", string.Format("{0}:{1}:{2}:{3}", ApiKey, requestSignatureBase64String, nonce, requestTimeStamp)); } request.Headers.Add("apikey", ApiKey); response = await base.SendAsync(request, cancellationToken); return response; } catch (HttpRequestException ex) { return null; } } } HMAC Implementation Example in PHP ----------------------------------- .. code-block:: php setKey(base64_decode($SecretKey)); $signature = $hmac->hash($signatureRawData); $serverSignature = base64_encode($signature); $signatureHeader = sprintf("%s:%s:%s:%s", $ApiKey, $serverSignature, $guid, $requestTimeStamp); curl_setopt($ch, CURLOPT_URL, $baseUrl); $body = array(); $payload = json_encode($body); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_POSTFIELDS, $body); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type:application/json', 'ApiKey:' . $ApiKey, 'Authorization: HMAC-SHA256 ' . $signatureHeader )); curl_setopt($ch, CURLINFO_HEADER_OUT, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $response = curl_exec($ch); $result = json_decode($response); curl_close($ch); ?>