HMAC Authentication

The SmartStore.Net Web API uses the HMAC authentication method to protect data from unauthorized access.

HMAC (hash-based message authentication code) is a session-less authentication method, where the integrity of a resource request is guaranteed through a code representing the request (called message representation) and a cryptological hash function. The procedure is considered to be very safe. It is used, for example, by Amazon to protect their S3 Web services.

SmartStore.Net uses SHA-256 as a hash function, which is why this authentication procedure is often called HMAC-SHA256.

The consumer must transmit a timestamp with each request which may not differ too far from the server time, otherwise the authentication will fail. The storekeeper can configure this time window in the plugin configuration. The default value is 15 minutes. To prevent replay attacks the timestamp must be younger than the one of a previous request.

Message representation

The message representation is a concatenation of various data separated by newline characters. All values are required but can be empty (in case of Content-MD5). It must be built as follows:

HTTP method\n
Content-MD5\n
Response content type (accept header)\n
Canonicalized URI\n
ISO-8601 UTC timestamp\n
Public key


HTTP method
: In lower case. Example: post

Content-MD5: The base64 encoded MD5 hash of the HTTP body, so base64(md5Hash(content)). For GET requests, this field is empty. For example, the MD5 hash for the content is as follows:

{"OrderId":152,"Note":"Hello world!","DisplayToCustomer":false,"CreatedOnUtc":"2013-11-09T11:15:00"}

is lgifXydL3FhffpTIilkwOw==.

The storekeeper can control (by a configuration setting) whether empty values can be passed as MD5 hash.

Response content type: The value of the Accept header field in lower case. Example: application/json, text/javascript, */*

Canonicalized URI: The complete URI of the requested resource (including query string) in lower case and in decoded format. Example: http://localhost:1260/odata/v1/ordernotes

ISO-8601 UTC timestamp: Current UTC date and time including optional milliseconds. Must be equal to the request header field SmartStore-Net-Api-Date. Examples: 2013-11-09T11:37:21.1918793Z, 2013-11-09T11:37:21.191Z, 2013-11-09T11:37:21Z. Can be created in C# as follows: string timestamp = DateTime.UtcNow.ToString("o");

Public key: The public key of the user in lower case. Example: 0c6b33651708eb09c8a8d6036b79d739

A complete message representation might look like this:

post
lgifXydL3FhffpTIilkwOw==
application/json
http://localhost:1260/odata/v1/ordernotes
2013-11-09T11:42:48.4715986Z
0c6b33651708eb09c8a8d6036b79d739

HMAC signature

The signature is the computed hash of the message representation by using SHA-256 and the user's secret key. Always UTF8 encode the secret key and the message representation while calculating the hash. Example of creating the HMAC signature:

public string CreateSignature(string secretKey, string messageRepresentation)
{
   	if (string.IsNullOrWhiteSpace(secretKey) || string.IsNullOrWhiteSpace(messageRepresentation))
   		return "";
    
   	string signature;
   	var secretBytes = Encoding.UTF8.GetBytes(secretKey);
   	var valueBytes = Encoding.UTF8.GetBytes(messageRepresentation);
    
   	using (var hmac = new HMACSHA256(secretBytes))
   	{
   		var hash = hmac.ComputeHash(valueBytes);
   		signature = Convert.ToBase64String(hash);
   	}
   	return signature;
}

The signature is transmitted as a base64 encoded string together with the schema using the authorization header field. For the above message representation and the secret key 3025c89ebaab20b71e0e42744239bf50, the authorization header field is

Authorization: SmNetHmac1 +yvONYvJmQl19omu1uE3HVlQ7afd7Qqkk8DrNrfUbe8=