I need to get a here-API token to use it in HERE Matrix Routing API but I can't get it. the response from the server always return the below
"{"errorId":"ERROR-b877e827-1ed6-4a2d-bed8-
546d1b9b3bd6","httpStatus":401,"errorCode":401205,"message":"Unsupported
signature method in the header. Require HMAC-
SHA256","error":"invalid_request","error_description":"errorCode:
'401205'. Unsupported signature method in the header. Require HMAC-
SHA256"}"
here is my code :
var grant_type = 'client_credentials';
var oauth_consumer_key = 'koauth_consumer_key';
var access_key_secret = 'access_key_secret';
var oauth_nonce = DateTime.now().millisecondsSinceEpoch.toString();
var oauth_timestamp = (new DateTime.now().toUtc().millisecondsSinceEpoch / 100).toString();
var oauth_signature_method = 'HMAC-SHA256';
var oauth_version = '1.0';
var url = 'https://account.api.here.com/oauth2/token';
create_signature(secret_key, signature_base_string) {
var temp = Hmac(sha256, utf8.encode(secret_key)).convert(utf8.encode(signature_base_string));
var hmacBase64 = base64Encode(temp.bytes);
print(hmacBase64);
return hmacBase64;
}
create_parameter_string(grant_type, oauth_consumer_key, oauth_nonce, oauth_signature_method, oauth_timestamp, oauth_version) {
parameter_string = '';
parameter_string = parameter_string + 'grant_type=' + grant_type;
parameter_string = parameter_string + '&oauth_consumer_key=' + oauth_consumer_key;
parameter_string = parameter_string + '&oauth_nonce=' + oauth_nonce;
parameter_string = parameter_string + '&oauth_signature_method=' + oauth_signature_method;
parameter_string = parameter_string + '&oauth_timestamp=' + oauth_timestamp;
parameter_string = parameter_string + '&oauth_version=' + oauth_version;
return parameter_string;
}
create encoded_oauth_signature
var parameter_string = create_parameter_string(grant_type, oauth_consumer_key, oauth_nonce, oauth_signature_method, oauth_timestamp, oauth_version);
var encoded_parameter_string = Uri.encodeComponent(parameter_string);
var encoded_base_string = 'POST' + '&' + Uri.encodeComponent(url) + '&' + encoded_parameter_string;
var signing_key = access_key_secret + '&';
var oauth_signature = create_signature(signing_key, encoded_base_string);
var encoded_oauth_signature = Uri.encodeComponent(oauth_signature);
// #---------------------Requesting Token---------------------
var body = {
'grant_type': '$grant_type'
};
preparing body and header
var headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'OAuth oauth_consumer_key="$oauth_consumer_key",oauth_nonce="$oauth_nonce",oauth_signature_method="HMAC-SHA256",oauth_timestamp="$oauth_timestamp",oauth_version="1.0",oauth_signature="$encoded_oauth_signature"'
};
get token:
gettokenpy() async {
final response = await http.post(
Uri.parse(url),
body: body,
headers: headers,
);
return response.body.toString();
}
The error message indicates that input signature method is not supported. It is supposed to be HMAC-SHA256. The following guide can help you to understand how to get the OAuth 2.0 token.
https://developer.here.com/documentation/identity-access-management/dev_guide/topics/sdk.html#step-3-request-a-token
Related
here is my code if anyone can help me this I would be grateful
Map<String, String> signRequest(String param) {
var method = "POST";
var uri = endpoint;
var secretKey = secretKey;
var accessKey = accessKey;
var region = awsRegion;
var service = serviceType;
var host = baseUrl;
var date = DateFormat("yyyyMMdd'T'HHmmss'Z'").format(DateTime.now().toUtc());
var date2 = DateFormat("yyyyMMdd").format(DateTime.now().toUtc());
var requestBody = utf8.encode(json.encode(param.toLowerCase()));
var hashedPayloads = sha256.convert(requestBody).toString().toLowerCase();
var canonicalUri = uri;
var canonicalQuerystring = "";
var canonicalHeaders =
"content-type:application/json\nhost:$host\nx-amz-content-sha256:$hashedPayloads\nx-amz-date:$date\n";
var signedHeaders = "content-type;host;x-amz-content-sha256;x-amz-date";
var canonicalRequest =
"$method\n$canonicalUri\n$canonicalQuerystring\n$canonicalHeaders\n$signedHeaders\n$hashedPayloads";
var credentialScope = "$date2/$region/$service/aws4_request";
var stringToSign =
"${ApiConstants.hmacShaTypeString}\n$date\n$credentialScope\n${sha256.convert(utf8.encode(canonicalRequest))}";
var kSecret = "AWS4$secretKey";
var kDate = Hmac(sha256, utf8.encode(kSecret))
.convert(utf8.encode(date2))
.toString();
var kRegion = Hmac(sha256, utf8.encode(kDate))
.convert(utf8.encode(region))
.toString();
var kService = Hmac(sha256, utf8.encode(kRegion))
.convert(utf8.encode(service))
.toString();
var kSigning = Hmac(sha256, utf8.encode(kService))
.convert(utf8.encode("aws4_request"))
.toString();
var signature = Hmac(sha256, utf8.encode(kSigning))
.convert(utf8.encode(stringToSign))
.toString();
var authorizationHeader =
"${ApiConstants.hmacShaTypeString} Credential=$accessKey/$credentialScope, SignedHeaders=$signedHeaders, Signature=$signature";
Map<String, String> headers = {
"Content-Type": "application/json",
"X-Amz-Date": date,
"X-Amz-Content-Sha256": hashedPayloads,
"Authorization": authorizationHeader
};
return headers;
}
Status code: 403
Got this message in response:
{"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been"}
I'm trying to call a SageMaker API in flutter but the header has some issues related to Signature.
Map<String, String> signRequest(String param) {
var method = "POST";
var uri = endpoint;
var secretKey = secretKey;
var accessKey = accessKey;
var region = awsRegion;
var service = serviceType;
var host = baseUrl;
var date = DateFormat("yyyyMMdd'T'HHmmss'Z'").format(DateTime.now().toUtc());
var date2 = DateFormat("yyyyMMdd").format(DateTime.now().toUtc());
var requestBody = utf8.encode(json.encode(param.toLowerCase()));
var hashedPayloads = sha256.convert(requestBody).toString().toLowerCase();
var canonicalUri = uri;
var canonicalQuerystring = "";
var canonicalHeaders =
"content-type:application/json\nhost:$host\nx-amz-content-sha256:$hashedPayloads\nx-amz-date:$date\n";
var signedHeaders = "content-type;host;x-amz-content-sha256;x-amz-date";
var canonicalRequest =
"$method\n$canonicalUri\n$canonicalQuerystring\n$canonicalHeaders\n$signedHeaders\n$hashedPayloads";
var credentialScope = "$date2/$region/$service/aws4_request";
var stringToSign =
"${ApiConstants.hmacShaTypeString}\n$date\n$credentialScope\n${sha256.convert(utf8.encode(canonicalRequest))}";
var kSecret = "AWS4$secretKey";
var kDate = Hmac(sha256, utf8.encode(kSecret))
.convert(utf8.encode(date2))
.toString();
var kRegion = Hmac(sha256, utf8.encode(kDate))
.convert(utf8.encode(region))
.toString();
var kService = Hmac(sha256, utf8.encode(kRegion))
.convert(utf8.encode(service))
.toString();
var kSigning = Hmac(sha256, utf8.encode(kService))
.convert(utf8.encode("aws4_request"))
.toString();
var signature = Hmac(sha256, utf8.encode(kSigning))
.convert(utf8.encode(stringToSign))
.toString();
var authorizationHeader =
"${ApiConstants.hmacShaTypeString} Credential=$accessKey/$credentialScope, SignedHeaders=$signedHeaders, Signature=$signature";
Map<String, String> headers = {
"Content-Type": "application/json",
"X-Amz-Date": date,
"X-Amz-Content-Sha256": hashedPayloads,
"Authorization": authorizationHeader
};
return headers;
}
Status code: 403
Got this message in response:
{"message":"The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.\n\nThe Canonical String for this request should have been"}
I want to reduce the throughput value of existing azure cosmos db collection using this rest API and it's giving a bad/unauthorized error. Kindly help me calling the API with proper input.
https://learn.microsoft.com/en-us/rest/api/cosmos-db/replace-an-offer
You need to provide authorization header
type={typeoftoken}&ver={tokenversion}&sig={hashsignature}
To start from replaceThroughput method
const replaceThroughput = async(req, res, next) => {
let collectionName = _.get(req, 'headers.collectionname');
let offerThroughput = _.get(req, 'headers.offerthroughput');
const container = await cosmosClient.database(process.env.COSMOS_DB_NAME).container(collectionName);
let containerResponse = await container.read().catch((error)=>{
let err = new Error();
err.statusCode = 404;
err.message = 'Collection not found';
next(err);
return;
});
let resourceId = _.get(containerResponse, 'body._rid', '');
console.log(resourceId)
let offerPayload = await getOfferPayload(resourceId);
_.set(offerPayload, 'content.offerThroughput', offerThroughput);
let offerResponse = await replaceOfferThroughput(offerPayload.id, offerPayload);
if (offerResponse.error) {
let err = new Error();
err.statusCode = 500;
err.message = 'Replace resource offer failed';
err.data = offerResponse.error;
next(err);
return;
} else {
res.end(JSON.stringify({'result': 'success', 'message': 'throughput updated', 'data': offerResponse}));
}
next();
};
const getOfferPayload = async (resourceId) => {
var dateString = new Date().toUTCString();
let authString = getAuthorizationTokenUsingMasterKey('GET','offers', '', dateString, process.env.COSMOS_DB_KEY);
const options = {
method: 'GET',
rejectUnauthorized: false,
uri: 'https://' + process.env.COSMOS_DB_NAME + '.documents.azure.com/offers',
headers: {
'x-ms-version': '2018-06-18',
'Authorization': authString,
'x-ms-date': dateString
}
};
try{
let response = await request(options);
response = JSON.parse(response);
response = _.filter(response.Offers, {offerResourceId: resourceId});
return response[0];
}catch(err){
return err;
}
};
const replaceOfferThroughput = async (offerResourceId, offerPayload) => {
var dateString = new Date().toUTCString();
let authString = getAuthorizationTokenUsingMasterKey('PUT','offers', offerResourceId, dateString, process.env.COSMOS_DB_KEY);
const options = {
method: 'PUT',
body: offerPayload,
json: true,
rejectUnauthorized: false,
uri: 'https://' + process.env.COSMOS_DB_NAME + '.documents.azure.com/offers/'+ offerResourceId,
headers: {
'x-ms-version': '2018-06-18',
'Authorization': authString,
'x-ms-date': dateString
}
};
try{
return await request(options);
}catch(err){
return err;
}
};
const getAuthorizationTokenUsingMasterKey = (verb, resourceType, resourceId, date, masterKey) => {
var key = Buffer.from(masterKey, "base64");
var text = (verb || "").toLowerCase() + "\n" +
(resourceType || "").toLowerCase() + "\n" +
(resourceId || "").toLowerCase() + "\n" +
date.toLowerCase() + "\n" +
"" + "\n";
var body = Buffer.from(text, "utf8");
var signature = crypto.createHmac("sha256", key).update(body).digest("base64");
var MasterToken = "master";
var TokenVersion = "1.0";
return encodeURIComponent("type=" + MasterToken + "&ver=" + TokenVersion + "&sig=" + signature);
}
To Create Connection
const CosmosClient = require("#azure/cosmos").CosmosClient;
cosmosClient = new CosmosClient({
endpoint: process.env.COSMOS_DB_URL,
auth: {
masterKey: process.env.COSMOS_DB_KEY
}
});
What I need to do to circumvent this issue, because when I request data for 2 months I already receive this error, when there is a break per day, I have the following call. With Little data works perfect, but when I increase the period the server brings me
User request limit reached","type":"OAuthException","is_transient":true,"code":17,"error_subcode":2446079,"fbtrace_id":"...
function solicitacaoAssicrona(){
var service = getService()
var batch = [{"method": "GET", "relative_url":"v3.2/act_1125789557444919/insights/impressions,reach,frequency,spend,campaign_name,account_name,clicks,cost_per_10_sec_video_view,cpm,cpp?level=campaign&since=2016-03-03&until=2019-03-04&time_increment=1&limit=100"}]
// var batchUrl = encodeURIComponent(JSON.stringify(batch));
// Logger.log(batchUrl);
var url = "https://graph.facebook.com?include_headers=false&batch=" + encodeURIComponent(JSON.stringify(batch))
var response = UrlFetchApp.fetch(url, {
method: 'POST',
headers: {
Authorization: 'Bearer ' + service.getAccessToken()
}
});
var result = JSON.parse(response.getContentText());
Logger.log(result)
// response.forEach(function(resp){
// var resp = JSON.parse(resp.body);
// //Logger.log(JSON.stringify(resp, null, 2));
//
//// resp.data[0].values.forEach(function(response){
////
////
//// })
////
// })
}
I'Ve looked at the documentation, but to the moment without success!
https://developers.facebook.com/docs/marketing-api/insights/best-practices/
That's the call I have
var metricas = [
'impressions',
'reach',
'unique_clicks',
'account_currency',
'account_id',
'account_name',
'ad_id',
'ad_name',
'adset_id',
'adset_name',
'buying_type',
'campaign_id',
'campaign_name',
'clicks',
'cost_per_inline_link_click',
'cost_per_inline_post_engagement',
'cost_per_unique_click',
'cost_per_unique_inline_link_click',
'cpc',
'cpm',
'cpp',
'ctr',
'date_start',
//'date_stop',
'frequency',
'inline_link_click_ctr',
'inline_link_clicks',
'inline_post_engagement',
'objective',
'relevance_score',
'social_spend',
'spend',
'unique_ctr',
'unique_inline_link_click_ctr',
'unique_inline_link_clicks',
'unique_link_clicks_ctr',
//'website_ctr',
'video_10_sec_watched_actions',
'cost_per_10_sec_video_view',
'video_30_sec_watched_actions',
'video_avg_percent_watched_actions',
'video_avg_time_watched_actions',
'video_p100_watched_actions',
'video_p25_watched_actions',
'video_p50_watched_actions',
'video_p75_watched_actions',
'video_play_actions',
'video_thruplay_watched_actions',
'video_p95_watched_actions',
]
var parameters = metricas.join(',');
var url = 'https://graph.facebook.com/v3.2/act_xxxxxxxxxx/insights?fields= + parameters + '&level=ad&time_range[since]=2019-02-05&time_range[until]=2019-04-05&time_increment=1&limit=200'
It's to do with how much data you can retrieve with batch requests. For longer periods, you should divide it into smaller chunks, sequential to each other, thus retrieving the data needed in multiple requests. Have a look at this example:
Code.gs
From line 88 of the file, you can see how it can be divided in multiple requests.
https://github.com/halsandr/Facebook_Connector/blob/master/Code.gs
function dateDelta(dObj, num) {
if (isNaN(num)) {
var dateStart = new Date(dObj);
} else {
var dateStart = new Date(dObj);
var dateStart = new Date(dateStart.setDate(dateStart.getDate() + num));
}
var dd = dateStart.getDate();
var mm = dateStart.getMonth()+1; //January is 0!
var yyyy = dateStart.getFullYear();
if(dd<10){
dd='0'+dd;
}
if(mm<10){
mm='0'+mm;
}
var dateStart = yyyy + "-" + mm + "-" + dd;
return dateStart;
}
var gStartDate = new Date(request.dateRange.startDate);
var gStartDate = new Date(dateDelta(gStartDate, -1));
var gEndDate = new Date(request.dateRange.endDate);
var gEndDate = new Date(dateDelta(gEndDate, +1));
var gRange = Math.ceil(Math.abs(gEndDate - gStartDate) / (1000 * 3600 * 24));
var gBatches = Math.ceil(gRange / 92);
if (gBatches < 2) {
var batch = [{"method": "GET", "relative_url": request.configParams.pageID + "/insights/page_fans,page_impressions,page_post_engagements?since=" + dateDelta(gStartDate) + "&until=" + dateDelta(gEndDate)}];
//console.log(batch);
} else {
batch = [];
var iterRanges = gRange / gBatches;
for (i = 0; i < gBatches; i++) {
var iterStart = dateDelta(gStartDate, (iterRanges * i));
if (i == (gBatches - 1)) {
var iterEnd = dateDelta(gEndDate);
} else {
var iterEnd = dateDelta(gStartDate, (iterRanges * (i + 1)) + 1);
}
batch.push({"method": "GET", "relative_url": request.configParams.pageID + "/insights/page_fans,page_impressions,page_post_engagements?since=" + iterStart + "&until=" + iterEnd})
}
//console.log(batch);
}
// Fetch the data with UrlFetchApp
var url = "https://graph.facebook.com?include_headers=false&batch=" + encodeURIComponent(JSON.stringify(batch))
I'm using graph api v2.1. AS3-code generates data, calls JS-code via ExternalInterface, JS-code calls FB API
I'm able to upload photo via {image-url}, but getting error when trying to upload photo via {image-data}:
{message: "(#324) Requires upload file", type: "OAuthException", code:
324}
I guess, i'm formatting {image-data} wrong. here is my code:
AS3:
var id:int = Math.random()*10000;
var stream:ByteArray = new ByteArray();
var imageName:String = id.toString() + ".png";
var boundary:String = "I" + id.toString();
stream.writeUTFBytes(
'Content-Type: multipart/form-data; boundary=' + boundary +
'\r\n\r\n--' + boundary +
'\r\nContent-Disposition: file; filename="' + imageName + '"' +
'\r\nContent-Type: image/png' +
'\r\nContent-Transfer-Encoding: binary' +
'\r\n\r\n');
stream.writeBytes(picture);
stream.writeUTFBytes("\r\n--" + boundary + '--\r\n');
if (ExternalInterface.available)
{
ExternalInterface.call('savePhoto', stream, null, id);
}
JS:
function savePhoto(bytes, url, requestId)
{
var data;
if (bytes != null)
data = {"source": bytes, "no_story":true}; //getting error
else
data = {"url": url, "no_story":true}; //works fine
FB.api(
"/me/photos",
"POST",
data,
function (response)
{
//handle response
}
);
}
UPD:
Here is how picture initialised:
[Embed(source="../res/logo_2.png", mimeType="image/png")]
private var testImage:Class;
<...>
var data:Bitmap = new testImage() as Bitmap;
var picture:ByteArray = PNGEncoder.encode(data.bitmapData);
Did you try base64?
var params: Object = new Object;
var encoder:JPGEncoder = new JPGEncoder(75);
var bytes:ByteArray = encoder.encode(bmp.bitmapData);
params.message = message;
params.image = bytes;
params.fileName = "image.jpg";
Facebook.api("/me/photos",null,params,"POST");
https://code.google.com/p/as3corelib/
Try this code to prepare data:
var pngData:ByteArray = PNGEncoder.encode(image.bitmapData);
var strForStart:String = "\r\n--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"photo\"; filename=\"file1.png\"\r\n" + "Content-Type: image/png\r\n\r\n" + "";
var strForEnd:String = "--" + boundary + "\r\n" + "Content-Disposition: form-data; name=\"Upload\"\r\n\r\n" + "Submit Query\r\n" + "--" + boundary + "--";
var beginBA:ByteArray = new ByteArray();
beginBA.writeMultiByte(strForStart, "ascii");
var endBA:ByteArray = new ByteArray();
endBA.writeMultiByte(strForEnd, "ascii");
var resultBytes:ByteArray = new ByteArray();
resultBytes.writeBytes(beginBA, 0, beginBA.length);
resultBytes.writeBytes(pngData, 0, pngData.length);
resultBytes.writeBytes(endBA, 0, endBA.length);