{
"errors": [
{
"message": "<below>",
"code": "InvalidSignature"
}
]
}
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. The Canonical String for this request should have been [[redacted]]
However my inputs are
<cfscript>
// define a struct for arguments
args={}
// Input fields
args.requestMethod='GET'
args.hostName='[[hostname]]'
args.requestURI='[[requestURL]]'
args.requestBody=""
args.requestHeaders={}
args.requestParams={}
args.signedPayload=true
args.excludeHeaders=[]
args.regionName='us-east-1'
args.serviceName='execute-api'
args.amzDate=aDate
args.dateStamp=dateStamp
args.signatureData={}
args.tokenData={}
</cfscript>
<cfhttp method="put" url="[[URL]]" result="result">
<cfhttpparam type="header" name="Authorization" value="#signatureData.AUTHORIZATIONHEADER#">
<cfhttpparam type="header" name="x-amz-access-token" value="#tokenData.access_token#">
<cfhttpparam type="header" name="X-Amz-Date" value="#aDate#">
</cfhttp>
I am using ColdFusion to call the ReportCloud API which does a mail merge on the fly based on parameters I send it via cfhttp.
The response from the documentation says:
On success, the HTTP status code in the response header is 200 (OK). The response body contains an array of the created documents encoded as Base64 encoded strings.
Can someone help me with how to turn that response into a downloadable file, either a link or just a straight download? I probably should know this but I don't unfortunately.
Added comments:
Thanks for your help and guidance with this question. I'm using StackOverflow as a poster for the first time, my apologies if the question is vague.
I have put together a code example also to view cffiddle
<!--- Must replace "Authorization" header below with a real key --->
<cfset variables.jsonReq = '{
"mergeData": [
{
"Given_Name": "Mike",
"Surname": "Smith",
"Year_Group": "11"
},
{
"Given_Name": "Sally",
"Surname": "Smith",
"Year_Group": "12"
}
],
"template": null,
"mergeSettings": null
}'>
<cfhttp url="https://api.reporting.cloud/v1/document/merge?returnFormat=DOC&templateName=parentletter.docx" method="post" timeout="20" result="response" file="/www/something.docx">
<cfhttpparam type="header" name="Content-Type" value="application/json">
<cfhttpparam type="header" name="Authorization" value="ReportingCloud-APIKey oMDM4MrAqL9QEOpyzupnQW5NjvCNtvE5cVDaaLqxI">
<cfhttpparam type="body" name="mergeData" value="#jsonReq#">
</cfhttp>
<cfdump var="#response#">
The response is coming back in what I think is a JSON array. I'm not sure how to go about reading that JSON array and making the contents into a downloadable file.
I'm having a terrible time...I am trying to get coldfusion to get a token from salesforce, but I am stuck on the following error
{"error":"invalid_grant","error_description":"authentication failure"}
ive tried cfscript
local.http = new Http(url='https://test.salesforce.com/services/oauth2/token',method='post');
local.http.addParam(type='header',name='content-type', value='application/x-www-form-urlencoded');
local.http.addParam(type='formField',name='grant_type', value='password');
local.http.addParam(type='formField',name='client_id', value='client_id');
local.http.addParam(type='formField',name='client_secret', value='client_password_string');
local.http.addParam(type='formField',name='username', value='user#email.com');
local.http.addParam(type='formField',name='password', value='userspassword');
local.http.addParam(type='formField',name='format', value='json');
local.httpSendResult = local.http.send();
rc.httpResult = httpSendResult.getPrefix();
ive tried cfhttp tags
<cfhttp url="https://test.salesforce.com/services/oauth2/token" method="POST">
<cfhttpparam type="header" name="Content-Type" value="application/x-www-form-urlencoded" />
<cfhttpparam type="formField" name="grant_type" value="password" />
<cfhttpparam type="formField" name="client_id" value="client_id" />
<cfhttpparam type="formField" name="client_secret" value="client_password_string" />
<cfhttpparam type="formField" name="username" value="user#email.com" />
<cfhttpparam type="formField" name="password" value="userspassword" />
</cfhttp>
<cfset rc.result = cfhttp.fileContent />
however the same exact call executed by cUrl on my local machine works perfectly fine
curl -d "grant_type=password"
-d "client_id=client_id"
-d "client_secret=client_secret_string"
-d "username=user#email.com.dev"
-d "password=userpassword" https://test.salesforce.com/services/oauth2/token
ive made sure that my ip range is whitelisted, my ip relaxation is set to relax, allusers may self authorize, ive tried different username and password parameters, all i get is the same error about invalid grants
any help is very appreciated
I am not able to comment, so I have to answer :) But this is really just a suggestion. When you use <cfhttpparam type="formfield">, by default ColdFusion URL encodes that for you. ColdFusion will encode the characters ~, ., -, and _, but it should not actually do that according to the RFC 3986 spec (see https://en.wikipedia.org/wiki/Percent-encoding), since they are unreserved characters. If your formfields contain those characters (and I suspect they do since your example shows an email address), it is possible that those characters being encoded incorrectly is what is causing the authentication failure.
As a quick test you could add encoded="false" to your <cfhttpparam> tags and then url encode their values yourself using either encodeForUrl() or urlEncodedFormat() (depending on your version of ColdFusion), and then undo the incorrect encoding:
<cfhttpparam type="formField" encoded="false" name="username" value="#replacelist(urlEncodedFormat('user#email.com'), '%2D,%2E,%5F,%7E', '-,.,_,~')#">
Below is some CFScript code pulled out of a CFC I created for accessing salesforce. (won't run as is, but the logic is there - sorry it was too much code to copy the complete thing). Hoping it will help.
I'm using predominantly the same approach as you, but you might want to steal some of the specific settings (charset, content type, accept).
I've faked the values in the loginCredentials struct, but they are roughly the same kind of format (to compare with your own).
This runs fine for us on Railo. Maybe also check that it's not a SSL issue - do you need to add the SSL certs into Coldfusion so it can talk to Salesforce?
variables.sfAuthDomain = "https://login.salesforce.com";
variables.authServiceURL = variables.sfAuthDomain & "/services/oauth2/token";
variables.accessToken = "xxxxx" // The access token returned by SF, used on future logins
variables.loginCredentials = {
"grant_type": "password",
"client_id": "3MVG9Fkjshdkfjvshd ckjfhjkch.blkjlkjlkjkljl.wkjhgkjhkjhds.mVk84TRzhm_pXxK6_786786",
"client_secret": "3887687686868668727",
"username": "huge.duck#monkey.com.icom.icomqa",
"password": "Bungerloo!PPkjhj324ij45bQGyymmd"
};
/**
* MAKE SERVICE CALL
* Makes HTTP service call
**/
public Struct function makeServiceCall(String serviceUrl, String method="GET", Boolean sfAuth=true, Struct headers={}, Struct formFields) {
var httpService = new http(); // create new http service
var httpResponse = {};
var fieldName = "";
var bodyData = "";
/* set attributes using implicit setters */
httpService.setMethod(arguments.method);
httpService.setCharset("utf-8");
httpService.setUrl(Trim(arguments.serviceURL));
httpService.setTimeOut(variables.timeoutValue);
/* add httpparams using addParam() */
for(fieldName in arguments.headers) {
httpService.addParam(type="header", name="#fieldName#", value="#arguments.headers[fieldName]#");
}
if(arguments.sfAuth){
httpService.addParam(type="header", name="Authorization", value="OAuth #variables.accessToken#");
}
if(StructKeyExists(arguments, "formFields")) {
loop collection="#arguments.formFields#" item="fieldName" {
bodyData = ListAppend(bodyData, "#fieldName#=#formFields[fieldName]#", "&");
}
}
if(bodyData is not "") {
httpService.addParam(type="body", name="post", encoded="no", value="#bodyData#");
}
/* make the http call to the URL using send() */
httpResponse = httpService.send().getPrefix();
//dump(httpResponse, false, "modern", "", 500, "httpResponse");
return httpResponse;
}
httpResponse = makeServiceCall(
serviceUrl = serviceURL,
method = "POST",
sfAuth = false,
headers = {
"Content-Type": "application/x-www-form-urlencoded",
"accept": "text/json"
},
formFields = loginCredentials
);
Ended up changing my coldfusion server to use TLS 1.2, as TLS 1.0 was deprecated for use by salesforce. Hope my answer and the helpful answers given on this post help someone else
Your password formfield value is contain only password, so that kind of error is shown:
({"error":"invalid_grant","error_description":"authentication failure"}).
That must be contain(password and security token).
<cfhttpparam type="formField" name="password" value="#arguments.password##arguments.Security_token#"/>
I have been hearing a lot about some new encryption needed for submitting transactions to Authorize.net but cannot find anything that explains it.
The AIM instructions for 2015 describe what I am already using except the post address has changed.
When I just submitted a transaction to the new address it was rejected.
Here is my code:
<cflock timeout="30" throwontimeout="No" name="12345">
<cfhttp url="https://secure.anetsgateway.net/gateway/transact.dll" method="post">
<cfoutput>
<cfhttpparam type="Formfield" name="x_login" value="myclient12345">
<cfhttpparam type="Formfield" name="x_tran_key" value="myxtrankey12345">
<cfhttpparam type="Formfield" name="x_version" value="3.1">
<cfhttpparam type="Formfield" name="x_test_request" value="TRUE">
The "x_tran_key" and "x_login" are hard-coded in my submission page.
Can someone explain where the issue is and examples of what special encryption I need.
It looks like you are using the wrong URL to talk to Authorize.Net. You should consult the documentation for the correct URL and proper method for integrating.
I would also like to add that placing your transaction key in the form is not a very good idea. It should be treated like a password.
I'm trying to obtain credentials from ning network using Coldfusion 9, so first this is the curl syntax to test the api :
curl -k https://external.ningapis.com/xn/rest/mbdevsite/1.0/Token?xn_pretty=true -u devshare#megabase.tn:mbdev2011 -d "oauth_signature_method=PLAINTEXT&
oauth_consumer_key=741ab68b-63fb-4949-891c-9e88f5143034&oauth_signature=36da2ea8
-10fb-48cc-aaa4-c17c551c6b87%26"
and it returns :
{
"success" : true,
"entry" : {
"author" : "1o0butfek0b3p",
"oauthConsumerKey" : "741ab68b-63fb-4949-891c-9e88f5143034",
"oauthToken" : "46f1e137-549a-4d9d-ae05-62782debfd3d",
"oauthTokenSecret" : "9f778ab5-db8e-4f3e-b17f-61d249b91f0a"
},
"resources" : {
}
then i translated it to coldfusion like this :
<cfhttp
method="post"
url="https://external.ningapis.com/xn/rest/mbdevsite/1.0/Token"
username="devshare#megabase.tn"
password="mbdev2011">
<cfhttpparam type="header" name="content-type" value="application/x-www-form-urlencoded">
<cfhttpparam name="oauth_signature_method" type="FormField" value="PLAINTEXT"/>
<cfhttpparam name="oauth_consumer_key" type="FormField" value="741ab68b-63fb-4949-891c-9e88f5143034"/>
<cfhttpparam name="oauth_signature" type="FormField" value="36da2ea8-10fb-48cc-aaa4-c17c551c6b87%26"/>
</cfhttp>
<cfoutput>
#cfhttp.fileContent#
</cfoutput>
and the response is always :
{"success":false,"reason":"The oauth_signature is invalid. That is, it doesn't match the signature computed by the Service Provider.","status":401,"code":1,"subcode":12,"trace":"3d874587-072b-4877-b27e-b84ee2e2b537"}
does somebody have idea about what could be this error ??
url and login info are real for who wants to help by testing
Thank you..
Don't disclose your username & password in public forums. Better you change this user name & password after this issue completion :)
Your oauth_signature is 36da2ea8-10fb-48cc-aaa4-c17c551c6b87& not "36da2ea8-10fb-48cc-aaa4-c17c551c6b87%26"
I got the success response & it is working perfectly.
<cfhttp
method="post"
url="https://external.ningapis.com/xn/rest/mbdevsite/1.0/Token"
username="devshare#megabase.tn"
password="mbdev2011">
<cfhttpparam type="header" name="content-type" value="application/x-www-form-urlencoded">
<cfhttpparam name="oauth_signature_method" type="FormField" value="PLAINTEXT"/>
<cfhttpparam name="oauth_consumer_key" type="FormField" value="741ab68b-63fb-4949-891c-9e88f5143034"/>
<cfhttpparam name="oauth_signature" type="FormField" value="36da2ea8-10fb-48cc-aaa4-c17c551c6b87&"/>
</cfhttp>
Any specific reason why you're using cURL instead of cfhttp?
There's a nice library on RIAForge:
OAuth
that will help you with dealing with OAuth. The issue is probably with the parameters encoding.
Oh - and you shouldn't be posting your OAuth credentials.
UPDATE:
I'm afraid using OAuth isn't as simple as just calling cfhttp with params.
The parameters need to be in certain order, you need to sign the whole request using appropriate method (plain text in your case). The signing process also includes time stamp so you can't test your code with the values from the example as they definitely won't work.
If you download the RIAForge libraries there's an "\examples_external" folder there and twitter.cfm - you'll find all that I've mentioned there.
A bit of code from there to show what I mean:
<!--- Create empty token --->
<cfset oReq = CreateObject("component", "oauth.oauthrequest").fromConsumerAndToken(
oConsumer = oConsumer,
oToken = oToken,
sHttpMethod = "GET",
sHttpURL = sTokenEndpoint,stparameters= Parameters )>
<!--- Sign the request --->
<cfset oReq.signRequest(
oSignatureMethod = oReqSigMethodSHA,
oConsumer = oConsumer,
oToken = oToken)>
<!--- Get the request token --->
<cfhttp url="#oREQ.getString()#" method="get" result="tokenResponse"/>
Of course there's lots of bits missing before and after it.
You might check out Ben Nadel's blog post on OAuth. He covers some of the things you may be running into.