Difference between revisions of "Updox HMAC Authentication"
(→Headers) |
m (→Destination Address) |
||
(33 intermediate revisions by one user not shown) | |||
Line 14: | Line 14: | ||
2. Authorization - "HMAC " + the Base64 encoded HMAC SHA1 hash of the message with the secret key. Note the <SPACE> character following the letters HMAC. | 2. Authorization - "HMAC " + the Base64 encoded HMAC SHA1 hash of the message with the secret key. Note the <SPACE> character following the letters HMAC. | ||
− | The message is defined as: | + | The message is defined as (implementation shall exclude brackets): |
− | [vendorId]:[vendorPassword]''''' | + | [vendorId]:[vendorPassword]:'''''[accountId]''''':'''''[userId]''''':[updox-timestamp] |
− | where <code>''''' | + | where <code>'''''[accountId]'''''</code> and <code>'''''[userId]'''''</code> are required to be part of the string to be hashed for each each request. If either of the <code>accountId</code> or <code>userId</code> are not used or populated, their place-holder in the message to be hashed '''''must still be provided'''''. In other words (excluding the 2 colons in the timestamp value) there should always be five values and four colons in the message to be hashed. |
+ | === Example Messages To Be Hashed === | ||
+ | |||
+ | For the following examples, each uses a timestamp value of <code>2013-11-20 17:36:00 (GMT)</code> | ||
+ | |||
+ | {| class="wikitable" style="width:900px; vertical-align:top; align:left" | ||
+ | ! JSON auth block || Message to be hashed | ||
+ | |- | ||
+ | |<code>applicationId:"appId", | ||
+ | |||
+ | applicationPassword:"appPwd", | ||
+ | |||
+ | accountId:"", | ||
+ | |||
+ | userId:""</code> | ||
+ | |<code>appId:appPwd:::2013-11-20 17:36:00 (GMT)</code> | ||
+ | |- | ||
+ | |<code>applicationId:"appId", | ||
+ | |||
+ | applicationPassword:"appPwd", | ||
+ | |||
+ | accountId:"100", | ||
+ | |||
+ | userId:""</code> | ||
+ | |<code>appId:appPwd:'''100'''::2013-11-20 17:36:00 (GMT)</code> | ||
+ | |- | ||
+ | |<code>applicationId:"appId", | ||
+ | |||
+ | applicationPassword:"appPwd", | ||
+ | |||
+ | accountId:"100", | ||
+ | |||
+ | userId:"200"</code> | ||
+ | |<code>appId:appPwd:'''100''':'''200''':2013-11-20 17:36:00 (GMT)</code> | ||
+ | |||
+ | |} | ||
== Verification == | == Verification == | ||
Updox will verify two things: | Updox will verify two things: | ||
− | 1. The timestamp header (updox-timestamp) is within the minutes defined for the vendor ( | + | 1. The timestamp header (updox-timestamp) is within the minutes defined for the vendor (defaults to 10 minutes). |
2. The hash passed in matches the hash we compute (therefore, the message was signed with the secret key). | 2. The hash passed in matches the hash we compute (therefore, the message was signed with the secret key). | ||
− | |||
− | |||
== Code Samples == | == Code Samples == | ||
Line 50: | Line 83: | ||
=== Destination Address === | === Destination Address === | ||
<div style="width:500px;"> | <div style="width:500px;"> | ||
− | {{Base url api| | + | {{Base url api|pingWithApplicationAuth|pingWithApplicationAuth}} |
</div> | </div> | ||
− | == Request and Response == | + | === Request and Response === |
+ | |||
+ | ==== Headers Construction ==== | ||
+ | The message to be hashed is constructed thusly (note that while the accountId and userId values are not provided to the <code>pingWithAuth</code> API call, ''their placeholders are still present in the message to be hashed''): | ||
+ | |||
+ | <code>applicationId:applicationPassword:::2013-11-20 17:36:00 (GMT)</code> | ||
+ | |||
+ | It is then hashed with the vendor's secret key: | ||
+ | |||
+ | <code>vendorSecretKey</code> applied to message to be hashed results in output (note that this hash string is not the actual result of encrypting the sample data): | ||
+ | |||
+ | <code>fH2JyYwiERQbwXL4XF6ZvtLjRvQ=</code> | ||
+ | |||
+ | |||
+ | HMAC authentication data is delivered to Updox as headers on the JSON request transaction: | ||
==== Headers ==== | ==== Headers ==== | ||
− | <code>updox-timestamp: 2013-11-20 17:36:00 ( | + | <code>updox-timestamp: 2013-11-20 17:36:00 (GMT) |
− | Authorization: HMAC fH2JyYwiERQbwXL4XF6ZvtLjRvQ=</code> | + | Authorization: HMAC fH2JyYwiERQbwXL4XF6ZvtLjRvQ= |
− | + | ||
− | + | Content-type: application/json</code> | |
− | <code> | + | Note that the <code>Content-type</code> header is not part of HMAC encryption, but a standard header required when sending JSON data. |
==== Request ==== | ==== Request ==== | ||
{ | { | ||
"auth": { | "auth": { | ||
− | "applicationId": " | + | "applicationId": "applicationId", |
− | "applicationPassword": " | + | "applicationPassword": "applicationPassword", |
− | "accountId": " | + | "accountId": "", |
− | "userId": " | + | "userId": "" |
} | } | ||
} | } |
Latest revision as of 07:33, 8 July 2014
Contents |
Description
For enhanced security, Updox provides an additional layer of authentication using a keyed-hash message authentication code (HMAC) with SHA1 as the cryptographic hash function. This document outlines how to use the Updox HMAC-SHA1 authentication.
Note: Updox HMAC-SHA1 enhances the Individual and Application Authorization schemes, it does not replace it. The auth header in the body of the post is still required for authorizing as a vendor, account, and user.
Outline
The Updox HMAC-SHA1 authentication layer requires two http header fields for every request:
1. updox-timestamp - the current time in the format "yyyy-MM-dd HH:mm:ss (z)".
2. Authorization - "HMAC " + the Base64 encoded HMAC SHA1 hash of the message with the secret key. Note the <SPACE> character following the letters HMAC.
The message is defined as (implementation shall exclude brackets):
[vendorId]:[vendorPassword]:[accountId]:[userId]:[updox-timestamp]
where [accountId]
and [userId]
are required to be part of the string to be hashed for each each request. If either of the accountId
or userId
are not used or populated, their place-holder in the message to be hashed must still be provided. In other words (excluding the 2 colons in the timestamp value) there should always be five values and four colons in the message to be hashed.
Example Messages To Be Hashed
For the following examples, each uses a timestamp value of 2013-11-20 17:36:00 (GMT)
JSON auth block | Message to be hashed |
---|---|
applicationId:"appId",
|
appId:appPwd:::2013-11-20 17:36:00 (GMT)
|
applicationId:"appId",
|
appId:appPwd:100::2013-11-20 17:36:00 (GMT)
|
applicationId:"appId",
|
appId:appPwd:100:200:2013-11-20 17:36:00 (GMT)
|
Verification
Updox will verify two things:
1. The timestamp header (updox-timestamp) is within the minutes defined for the vendor (defaults to 10 minutes).
2. The hash passed in matches the hash we compute (therefore, the message was signed with the secret key).
Code Samples
Language | Source Code Examples |
---|---|
C# |
public void setHmacHeaders(HttpWebRequest request) { string applicationId = "vendor-id"; string applicationPassword = "vendor-password"; string accountId = "accountId"; string userId = "userId"; string apiSecret = "vendor-private-secret-key"; // Create the date string String timestampString = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") + " (GMT)" // Build authentication string string message = applicationId + ":" + applicationPassword + ":" + accountId + ":" + userId + ":" + timestampString; // Create the athentication hash - note the intentional <space> after HMAC string auth = "HMAC " + hmacSha1ToBase64(message, apiSecret); // // Set the request headers request.Headers.Add("updox-timestamp", timestampString); request.Headers.Add("Authorization", auth); } public string hmacSha1ToBase64(String value, String key) { // Get an hmac_sha1 key from the raw key bytes byte[] keyBytes = Encoding.UTF8.GetBytes(key); byte[] valueBytes = Encoding.UTF8.GetBytes(value); // Get an hmac_sha1 Mac instance and initialize with the signing key HMACSHA1 myhmacsha1 = new HMACSHA1(); myhmacsha1.Key = keyBytes; byte[] final = myhmacsha1.ComputeHash(valueBytes); // Covert array of Hex bytes to a String return Convert.ToBase64String(final); } |
Java |
public static void generateHmacHeaders(HttpURLConnection connection, String applicationId, String applicationPassword, String accountId, String userId) throws Exception{ final SimpleDateFormat d = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss (z)"); d.setTimeZone(TimeZone.getTimeZone("GMT")); final String timestampString = d.format(new Date()); final String message = (applicationId == null ? "" : applicationId) + ":" + (applicationPassword == null ? "" : applicationPassword) + ":" + (accountId == null ? "" : accountId) + ":" + (userId == null ? "" : userId) + ":" + timestampString; final String auth = "HMAC " + hmacSha1ToBase64(message, apiSecret); //note space after HMAC connection.setRequestProperty("updox-timestamp", timestampString); connection.setRequestProperty("Authorization", auth); } public static String hmacSha1ToBase64(String value, String key) throws Exception{ byte[] keyBytes = key.getBytes(); SecretKeySpec signingKey = new SecretKeySpec(keyBytes, "HmacSHA1"); Mac mac = Mac.getInstance("HmacSHA1"); mac.init(signingKey); byte[] rawHmac = mac.doFinal(value.getBytes()); byte[] base64Bytes = Base64.encodeBase64(rawHmac); return new String(base64Bytes, "UTF-8"); } |
Messages (Example)
Destination Address
Request and Response
Headers Construction
The message to be hashed is constructed thusly (note that while the accountId and userId values are not provided to the pingWithAuth
API call, their placeholders are still present in the message to be hashed):
applicationId:applicationPassword:::2013-11-20 17:36:00 (GMT)
It is then hashed with the vendor's secret key:
vendorSecretKey
applied to message to be hashed results in output (note that this hash string is not the actual result of encrypting the sample data):
fH2JyYwiERQbwXL4XF6ZvtLjRvQ=
HMAC authentication data is delivered to Updox as headers on the JSON request transaction:
Headers
updox-timestamp: 2013-11-20 17:36:00 (GMT)
Authorization: HMAC fH2JyYwiERQbwXL4XF6ZvtLjRvQ=
Content-type: application/json
Note that the Content-type
header is not part of HMAC encryption, but a standard header required when sending JSON data.
Request
{ "auth": { "applicationId": "applicationId", "applicationPassword": "applicationPassword", "accountId": "", "userId": "" } }
Response
{ "successful": true, "responseMessage": "OK", "responseCode": 2000 }
Relevant Response Codes
In addition to the General Error Set, this method may return the following values in the responseCode
and responseMessage
fields:
responseCode
|
responseMessage
|
---|---|
4010
|
Unauthorized
|