HMAC Authentication in Salesforce
Being a salesforce developer, it was very challenging task for me to compute HMAC using algorithm, to
create a signature that would help external system to verify the sent request to store Lead information from
salesforce org.
HMAC is Hash-based message authentication code. Which is used to convert data into a bit string. This
bit string is called cryptographic string.
Why to use HMAC?
HMAC protects the quality, legality and validity of the message. It should be known by both the sender
and the receiver of the message. So when the sender sends the request, it will not only protect the data but also
maintain and assure the accuracy and consistency of data. Receiver has the secret key to detect any changes in
the message content.
How to use HMAC?
To generate HMAC I used SHA1 algorithm, secret key, Content-MD5 header (if using POST request).
Using these parameters I have created a signature which was base64 encoded.
Where to use HMAC?
HMAC is used for web service callouts to secure the data while sending from one system to another
system through internet.
Step 1:
Create a global class with @future(callout=true) annotation
public class HMACGenearatorHandler{ // method to create JSON and post it to the endpoint URL public void createJson(list<sObject> sObjectList){ String jsonString; // create json here sendRequest(jsonString); } // end method @future (callout=true) public static void sendRequest(String jsonString){ DateTime dtNow= System.Now(); String dateFormat= dtNow.format('E, dd MMM yyyy kk:mm:ss z','GMT'); // date format as per the timezone of org HttpRequest req = new HttpRequest(); req.setEndpoint(System.Label.EndPoint); // endpoint URL
Step 2:
Pass jsonString to the generate md5 content to post request.
MD5 is a message digest algorithm used to produce a 128-bit (16-byte) hash value in text format as a 32 digit
hexadecimal number to verify data integrity.
String strMd5= EncodingUtil.base64Encode (Crypto.generateDigest('MD5', Blob.valueOf(jsonString)));
Step 3:
Create a canonical string (the format of this string may different for different scenario).
In my case, it is as below:
canonical_string = ‘content-type,content-MD5,request URI,date’
String strCanonical = 'application/json' + ',' + strMd5 + ',' + request URL + ',' +dateFormat;
Step 4:
Pass the canonical string and the secret key to generate HMAC using SHA1 algorithm. In the code
snippet generate HmacSHA1Signature is a method which uses canonical string and the secret key to encrypt the
message and return the value in blob format.
String strSignature = EncodingUtil.base64Encode(generateHmacSHA1Signature(strCanonical, system.label.Secret_Key));
// method to generate SHA 1 public static blob generateHmacSHA1Signature(String canonical_str, String secreteKey){ Blob mac = Crypto.generateMac('HMacSHA1', blob.valueof(canonical_str),blob.valueof(secreteKey)); return mac; }// End generateHmacSHA1Signature method
String looks like:
application/json,1B2M2Y8RugTpgAm788jk==,/api/patient,Wed, 24 Sep 2014 19:18:44 GMT
Step 5:
The signature string is encoded in base64 format and I have used this string to authenticate the request.
String strSignature = EncodingUtil.base64Encode(generateHmacSHA1Signature(strCanonical, system.label.Secret_Key)); String authorizationHeader = system.label.APIAuth + ' ' + System.Label.Access_Id + ':' + strSignature;req.setMethod('POST'); req.setHeader('ACCEPT',System.label.Accept_Header); // accept headers req.setHeader('Authorization', authorizationHeader); req.setHeader('Content-Type', System.label.Content_Type); // content Type req.setHeader('DATE',dateFormat); req.setHeader('CONTENT_MD5',strMd5); req.setHeader('request_uri',System.Label.EndPoint); req.setBody(jsonString); Http http = new Http(); if(!test.isRunningTest()){ HTTPResponse res = http.send(req); } // end if } // end sendRequest method } // end class
This way you can authenticate your request using HMAC.
WISHING YOU ALL THE BEST. Happy Coding!!!!!