API3
luca at October 6th, 2017 03:28 — #1
Hi,
I'm trying to make Sign in using Node for retrieving contacts from API but i've always 401 error.
i've seen your javascript code in your API documentation but the version of Crypto is outdated and is not even a way to make a test with those code.
Is it possibile to receive an updated code in javascript to make a correct signature?
This is my code based on the PHP script, login works correctly.
/**
* Run Command
*
* @param args
* @param options
* @returns {Promise.<void>}
*/
async handle (args, options) {
this.info('Login Into OnePage')
// Auth With onePage;
let login = await this.onePageApiCall('login.json', 'POST', {
'login': Env.get('API_ONEPAGE_USERNAME'),
'password': Env.get('API_ONEPAGE_PASSWORD')
})
if (login.data.status === 0) {
this.success('Logged')
let url = 'contacts.json?team=1&per_page=100&page=1'
let signature = await this.onePageApiCall(url, 'GET', [], login.data.data.user_id, new Buffer(login.data.data.auth_key, 'base64').toString())
}
}
/**
* Make One page API Call
* @param url
* @param requestMethod
* @param postData
* @param uid
* @param key
* @returns {Promise.<*>}
*/
async onePageApiCall (url, requestMethod, postData = [], uid = null, key = null) {
let fullUrl = Env.get('API_ONEPAGE_ENDPOINT') + url
let timestamp = moment().unix()
let authData = [uid, timestamp, requestMethod, CryptoJs.SHA1(fullUrl).toString()]
let request_header
let data = null
// For POST and PUT requests we will send data as JSON
// as with regular "form data" request we won't be able
// to send more complex structures
if (requestMethod === 'POST' || requestMethod === 'PUT') {
request_header = {'Content-Type': 'application/json'}
let jsonData = JSON.stringify(postData)
data = jsonData
authData.push(CryptoJs.SHA1(jsonData).toString())
}
// Set auth headers if we are logged in
if (key !== null) {
let hash = CryptoJs.HmacSHA256(authData.join('.'), key)
request_header = {
'X-OnePageCRM-UID': uid,
'X-OnePageCRM-TS': timestamp,
'X-OnePageCRM-Auth': hash.toString()
}
}
return await axios({
method: requestMethod.toUpperCase(),
url: fullUrl,
headers: request_header,
data
})
}
Thanks
vladimir at October 6th, 2017 14:45 — #2
Hi Luca!
Thanks for the code snippet attached. Here's a method that creates signature value which works fine
onepagecrmSignature = function (UID, APIKey, timestamp, requestMethod, requestURL, requestBody) { // auth headers for requests
var decodedAPIKey,
requestURLHash,
requestBodyHash,
signatureMessage,
ts;
decodedAPIKey =CryptoJS.enc.Base64.parse(APIKey);
requestURLHash = CryptoJS.SHA1(requestURL);
ts = Math.floor(timestamp)
signatureMessage = UID + "." + ts + "." + requestMethod + "." + requestURLHash;
if (requestBody && requestBody !== ''){
requestBodyHash = CryptoJS.SHA1(requestBody);
signatureMessage += "." + requestBodyHash;
}
return CryptoJS.HmacSHA256(signatureMessage, CryptoJS.enc.Base64.parse(APIKey) );
}
where
-
UID
is user_id value from the response to login request
-
APIKey
input var is the 'auth_key' value returned to you from server in the response to login request, it is returned Base64-encoded.
-
Timestamp
value that is passed to the function equals
timestamp = Math.round(new Date().getTime()/1000)
-
requestMethod
is 'GET', 'POST', etc. For 'contacts.json' request it's 'GET'
-
requestURL
is endpoint + '/api/v3/contacts.json', I don't know what protocol you have set into your env. variables: http or https
-
requestBody
is the body for POST request, for 'contacts.json' request it's empty
So now you have all values for successful server call:
-
user_id
from login server response
- timestamp which is
timestamp = Math.round(new Date().getTime()/1000)
- and
signature = onepagecrmSignature(user_id, api_key, timestamp, request_type, request_url, request_body);
Now you can make a request to endpointURL + '/contacts.json' having set the following headers with the values calculated on the previous step:
- X-OnePageCRM-UID = {user_id}
- X-OnePageCRM-TS = {timestamp}
- X-OnePageCRM-Auth = {signature}
Try this code, it works alright (no 401 error code in response) and good luck! Please respond and tell me if you succeded with querying the endpoint.
Vladimir
luca at October 9th, 2017 06:26 — #3
Hi Vladimir Thanks for your reply! Thanks now it's work correctly.
I'll post my code that make login and other calls hoping it will be useful to other users.
const Env = use('Env')
const CryptoJs = require('crypto-js')
const axios = require('axios')
async onePageApiCall (url, requestMethod, postData = [], uid = null, key = null) {
let fullUrl = Env.get('API_ONEPAGE_ENDPOINT') + url
let timestamp = Math.round(new Date().getTime() / 1000)
let authData = [uid, timestamp, requestMethod, CryptoJs.SHA1(fullUrl).toString()]
let requestHeader
let data = null
// For POST and PUT requests we will send data as JSON
// as with regular "form data" request we won't be able
// to send more complex structures
if (requestMethod === 'POST' || requestMethod === 'PUT') {
requestHeader = {'Content-Type': 'application/json'}
let jsonData = JSON.stringify(postData)
data = jsonData
authData.push(CryptoJs.SHA1(jsonData).toString())
}
// Set auth headers if we are logged in
if (key !== null) {
let hash = CryptoJs.HmacSHA256(authData.join('.'), CryptoJs.enc.Base64.parse(key))
requestHeader = {
'X-OnePageCRM-UID': uid,
'X-OnePageCRM-TS': timestamp,
'X-OnePageCRM-Auth': hash
}
}
return await axios({
method: requestMethod.toUpperCase(),
url: fullUrl,
headers: requestHeader,
data
})
}
Powered by Discourse, best viewed with JavaScript enabled