coldfusion从salesforce获取API令牌 - 无效授权

时间:2017-09-12 17:58:34

标签: coldfusion salesforce

我度过了一段可怕的时光......我正在尝试使用coldfusion从salesforce获取令牌,但我仍然坚持以下错误

mergeParams

我试过cfscript

{"error":"invalid_grant","error_description":"authentication failure"}

我已经尝试过cfhttp标签

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();

然而,cUrl在我的本地机器上执行的完全相同的调用完全正常

<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 />     

我确保我的ip范围被列入白名单,我的ip放松设置为放松,allusers可以自我授权,我尝试了不同的用户名和密码参数,我得到的是关于无效拨款的相同错误

非常感谢任何帮助

4 个答案:

答案 0 :(得分:1)

我无法评论,所以我必须回答:)但这只是一个建议。使用<cfhttpparam type="formfield">时,默认情况下,ColdFusion URL会为您编码。 ColdFusion会对字符~.-_进行编码,但根据RFC 3986规范,它实际上不应该这样做(请参阅https://en.wikipedia.org/wiki/Percent-encoding ),因为他们是无保留的人物。如果您的表单字段包含这些字符(并且我怀疑他们这样做,因为您的示例显示了电子邮件地址),那么编码错误的字符可能是导致身份验证失败的原因。

作为快速测试,您可以将encoded="false"添加到<cfhttpparam>代码中,然后使用encodeForUrl()urlEncodedFormat()自行对其值进行编码(具体取决于您的ColdFusion版本) ),然后撤消不正确的编码:

 <cfhttpparam type="formField" encoded="false" name="username" value="#replacelist(urlEncodedFormat('user@email.com'), '%2D,%2E,%5F,%7E', '-,.,_,~')#">

答案 1 :(得分:1)

以下是从我为访问salesforce而创建的CFC中提取的一些CFScript代码。 (不会按原样运行,但逻辑就在那里 - 抱歉复制完整的东西的代码太多了。)希望它会有所帮助。

我主要使用与您相同的方法,但您可能想要窃取一些特定设置(字符集,内容类型,接受)。

我伪造了loginCredentials结构中的值,但它们的格式大致相同(与您自己的格式进行比较)。

这对我们来说在Railo上运行良好。也许还要检查它不是SSL问题 - 您是否需要将SSL证书添加到Coldfusion中以便它可以与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    
);

答案 2 :(得分:0)

结束更改我的coldfusion服务器以使用TLS 1.2,因为不推荐使用TLS 1.0供salesforce使用。希望我的回答和这篇文章中给出的有用答案可以帮助别人

答案 3 :(得分:0)

您的密码表单字段值仅包含密码,因此将显示这种错误:

({"error":"invalid_grant","error_description":"authentication failure"})

必须包含(密码和安全令牌)。

<cfhttpparam type="formField" name="password" value="#arguments.password##arguments.Security_token#"/>