Authentication (HMAC)
HMAC-based authentication is the single preferred way of authentication to Recombee APIs.
Thanks to the nature of our APIs, authentication can reuse simple
shared-secret approach with signature generated according to the
HMAC-SHA1 standard. To be able to use HMAC based auth, you will need a
token
, which you can obtain in the Recombee Admin UI.
In case of server side implementation use the private token
(which
needs to remain secret and known only to you and Recombee) and in case
of client side implementation (e.g. in a mobile app) use the
public token
(see this section for
details).
There are two params you need to attach to every API call:
hmac_timestamp
- is a current UTC unix timestamp (integer)hmac_sign
- is signature computed from your request URI without protocol and host
Every signature has limited lifetime (currently 10s). Therefore it is important that you have your server time synchronized via ntp or other source of precise time.
For example you want to make a call to the following URL
http://rapi.recombee.com/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7
Initial input to the signing method does not contain protocol and host
parts. And the hmac_timestamp
is added:
/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7&hmac_timestamp=1396859079
you sign this and finally append the signature:
/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7&hmac_timestamp=1396859079&hmac_sign=c608b597456d0760aee0e5a95017c63a8a24b4eb
Hash examples#
To see whether you are hashing properly, you can try hash these strings and verify the results.
TOKEN = "gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G"
String | Hash |
---|---|
Hello world | 1291b164d8332792233dcc8ce94e1c9ea6113fb8 |
/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7&hmac_timestamp=1398463889 | 090eafba456488622a6d6f0dc37d3a1508536338 |
During implementation you only need to hash the address with the
hmac_timestamp
, without domain or protocol:
Right hash string:
/recombee/items/9346/recomms/?count=5
&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7
&hmac_timestamp=1398463889
Wrong hash string:
https://rapi.recombee.com/recombee/items/9346/recomms/?count=5
&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7
&hmac_timestamp=1398463889
Authentication of Client-Side Requests#
The same authentication method is used also for client side (frontend) requests.
The differences are:
- use the
public token
for signing - different names of the params: use
frontend_timestamp
instead ofhmac_timestamp
andfrontend_sign
instead ofhmac_sign
- the RAPI endpoint is at
client-rapi.recombee.com
See this example.
Postman#
If you are using the Postman for making some API calls, you can use the following script for authentication of your requests: https://github.com/Pazekal90/recombee-SHA1-HMAC-Postman-Pre-request-Script.
Example Implementations#
Description itself can be a bit cumbersome, but the actual implementations are very simple and straightforward.
Python#
import time
import hmac
from hashlib import sha1
key = 'gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G'
url = '/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7'\
'&hmac_timestamp=%s' % int(time.time())
sign = hmac.new(str.encode(key), str.encode(url), sha1).hexdigest()
print('%s&hmac_sign=%s' % (url, sign))
Ruby#
require 'securerandom'
require 'digest/hmac'
KEY = "gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G"
url = '/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7' +
"&hmac_timestamp=#{Time.now.utc.to_i}"
sign = Digest::HMAC.hexdigest(url, KEY, Digest::SHA1)
puts "#{url}&hmac_sign=#{sign}"
PHP#
<?php
$key = 'gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G';
$url = '/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7';
$url = $url . '&hmac_timestamp=' . time();
$sign = hash_hmac("sha1", $url, $key);
echo $url . "&hmac_sign=" . $sign;
?>
Java#
import org.apache.commons.codec.binary.Hex;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
String key = "gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G";
String url = "/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7"+
"&hmac_timestamp="+System.currentTimeMillis() / 1000;
Mac mac = Mac.getInstance("HmacSHA1");
SecretKeySpec secret = new SecretKeySpec(key.getBytes(),"HmacSHA1");
mac.init(secret);
byte[] rawHmac = mac.doFinal(url.getBytes());
String sign = Hex.encodeHexString(rawHmac);
System.out.println(url+"&hmac_sign="+sign);
JavaScript#
Using sha1.js
from jsSHA.
<head>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/jsSHA/2.4.2/sha.js"
integrity="sha512-aNuJL9dGmxptdarUqHqErH4MhgsJR0exQrlTRvCWWfZVwtB8El4iHpr6v+1ftov/7RAczXGCTDQQteAEaOzj6w=="
crossorigin="anonymous"
></script>
</head>
<body>
<script type="text/JavaScript">
var key = 'gahpiev6eighaig1aek4ujietheiXeengae3Ohqu9iecutheof5rooxeigheel8G';
var url =
'/recombee/items/9346/recomms/?count=5&targetUserId=fb2fbe12-9f69-45a1-9fc0-df0c1592e4c7';
url =
url +
(url.indexOf('?') == -1 ? '?' : '&') +
'frontend_timestamp=' +
parseInt(new Date().getTime() / 1000);
var shaObj = new jsSHA('SHA-1', 'TEXT');
shaObj.setHMACKey(key, 'TEXT');
shaObj.update(url);
url = url + '&frontend_sign=' + shaObj.getHMAC('HEX');
document.write(url);
</script>
</body>