尝试将Coldfusion验证为FitBit API OAuth1

时间:2014-06-10 14:29:14

标签: api oauth coldfusion fitbit

这是我的第一个oAuth1项目。我正在尝试连接到FitBit的API。我去了fitbit,注册了一个应用程序并记录了我的密钥和秘密。

我已经下载并尝试设置: http://oauth.riaforge.org/

1)我发现在尝试通过SSL连接时出现连接失败..但我认为这是一个密钥库问题。当我回到http时,它至少尝试连接:

2)我目前正在使用examples_external / google.cfm文件中的代码。这似乎是最接近的比赛。

当我运行代码时,我收到下面提到的响应。我假设oauth客户端发送链接作为获取URL中的所有值,Fitbit想要一个POST,它需要一个身份验证标头。我已经研究过了,但Fitbit和Oauth的CF例子很缺乏。

这是他们正在寻找的东西。 https://wiki.fitbit.com/display/API/OAuth+Authentication+in+the+Fitbit+API

任何指导都将不胜感激。

<!--- set up the parameters --->
<cfset sConsumerKey = "xxxxx"> <!--- FromFit Bit  --->
<cfset sConsumerSecret = "yyyy"> <!--- From FitBit --->
<cfset sTokenEndpoint = "http://api.fitbit.com/oauth/request_token"> <!--- Access Token URL --->
<cfset sAuthorizationEndpoint = "http://www.fitbit.com/oauth/authorize"> <!--- Authorize URL --->
<cfset sCallbackURL = "http://www.example.com/fitbit/callback.cfm"> <!--- where fitbit will redirect to after the user enters their details --->
<cfset sClientToken = ""> <!--- returned after an access token call --->
<cfset sClientTokenSecret = ""> <!--- returned after an access token call --->
<cfset sScope =''> <!--- required for google --->

<!--- set up the required objects including signature method--->
<cfset oReqSigMethodSHA = CreateObject("component", "oauth.oauthsignaturemethod_hmac_sha1")>
<cfset oToken = CreateObject("component", "oauth.oauthtoken").createEmptyToken()>
<cfset oConsumer = CreateObject("component", "oauth.oauthconsumer").init(sKey = sConsumerKey, sSecret = sConsumerSecret)>

<cfset Parameters = structNew()>
<cfset parameters.scope = sScope>

<cfset oReq = CreateObject("component", "oauth.oauthrequest").fromConsumerAndToken(
    oConsumer = oConsumer,
    oToken = oToken,
    sHttpMethod = "GET",
    sHttpURL = sTokenEndpoint,stparameters=Parameters )>

<cfset oReq.signRequest(
    oSignatureMethod = oReqSigMethodSHA,
    oConsumer = oConsumer,
    oToken = oToken)>


<cfhttp url="#oREQ.getString()#" method="get" result="tokenResponse"/>

<!--- grab the token and secret from the response if its there--->
<cfif findNoCase("oauth_token",tokenresponse.filecontent)>
    <cfset sClientToken = listlast(listfirst(tokenResponse.filecontent,"&"),"=")>
    <cfset sClientTokenSecret = listlast(listlast(tokenResponse.filecontent,"&"),"=")>

    <!--- you can add some additional parameters to the callback --->
    <cfset sCallbackURL = sCallbackURL & "?" &
        "key=" & sConsumerKey &
        "&" & "secret=" & sConsumerSecret &
        "&" & "token=" & sClientToken &
        "&" & "token_secret=" & sClientTokenSecret &
        "&" & "endpoint=" & URLEncodedFormat(sAuthorizationEndpoint)>

    <cfset sAuthURL = sAuthorizationEndpoint & "?oauth_token=" & sClientToken & "&" & "oauth_callback=" & URLEncodedFormat(sCallbackURL) >

    <cflocation url="#sAuthURL#">

<cfelse>
    <cfoutput>#tokenResponse.filecontent#</cfoutput>
</cfif>

返回

{"errors":[{"errorType":"oauth","fieldName":"n/a","message":"No Authorization header provided in the request. Each call to Fitbit API should be OAuth signed"}],"success":false}

更新:我能够进一步了解一个例子,我找到了一个与类似问题连接到facebook的人....更新代码:

<!--- set up the parameters --->
<cfset sConsumerKey = "xxxxx"> <!--- FromFit Bit  --->
<cfset sConsumerSecret = "xxxxxxxx"> <!--- From FitBit --->
<cfset sTokenEndpoint = "http://api.fitbit.com/oauth/request_token"> <!--- Access Token URL --->
<cfset sAuthorizationEndpoint = "http://api.fitbit.com/oauth/authorize"> <!--- Authorize URL --->
<cfset sCallbackURL = "http://www.example.com/fitbit/callback.cfm"> <!--- where fitbit will redirect to after the user enters their details --->
<cfset sClientToken = ""> <!--- returned after an access token call --->
<cfset sClientTokenSecret = ""> <!--- returned after an access token call --->


<!--- set up the required objects including signature method--->
<cfset oReqSigMethodSHA = CreateObject("component", "oauth.oauthsignaturemethod_hmac_sha1")>
<cfset oToken = CreateObject("component", "oauth.oauthtoken").createEmptyToken()>
<cfset oConsumer = CreateObject("component", "oauth.oauthconsumer").init(sKey = sConsumerKey, sSecret = sConsumerSecret)>

<cfset Parameters = structNew()>

<cfset oReq = CreateObject("component", "oauth.oauthrequest").fromConsumerAndToken(
    oConsumer = oConsumer,
    oToken = oToken,
    sHttpMethod = "POST",
    sHttpURL = sTokenEndpoint,stparameters=Parameters )>

<cfset oReq.signRequest(
    oSignatureMethod = oReqSigMethodSHA,
    oConsumer = oConsumer,
    oToken = oToken)>


<cfhttp url="#oReq.GETNORMALIZEDHTTPURL()#" method="post" result="tokenresponse">
    <cfhttpparam type="header" name="Authorization" value="#oReq.TOHEADER()#" />
</cfhttp>

<!--- 
FROM HERE DOWN IS ALL FROM EXAMPLE FILE

grab the token and secret from the response if its there--->
<cfif findNoCase("oauth_token",tokenresponse.filecontent)>
    <cfset sClientToken = listlast(listfirst(tokenResponse.filecontent,"&"),"=")>
    <cfset sClientTokenSecret = listlast(listlast(tokenResponse.filecontent,"&"),"=")>

    <!--- you can add some additional parameters to the callback --->
    <cfset sCallbackURL = sCallbackURL & "?" &
        "key=" & sConsumerKey &
        "&" & "secret=" & sConsumerSecret &
        "&" & "token=" & sClientToken &
        "&" & "token_secret=" & sClientTokenSecret &
        "&" & "endpoint=" & URLEncodedFormat(sAuthorizationEndpoint)>

    <cfset sAuthURL = sAuthorizationEndpoint & "?oauth_token=" & sClientToken & "&" & "oauth_callback=" & URLEncodedFormat(sCallbackURL) >

    <cflocation url="#sAuthURL#">

<cfelse>
    <cfoutput>#tokenResponse.filecontent#</cfoutput>
</cfif>

然而,现在我正在回调....我认为它看起来很相似,但只是附加了2个值,但我似乎无法正确追加它。

<cfset sConsumerKey = ""> <!--- FromFit Bit  --->
<cfset sConsumerSecret = ""> <!--- From FitBit --->
<cfset sTokenEndpoint = "http://api.fitbit.com/oauth/request_token"> <!--- Access Token URL --->
<cfset sAuthorizationEndpoint = "http://api.fitbit.com/oauth/authorize"> <!--- Authorize URL --->
<cfset sCallbackURL = "http://www.example.com/fitbit/callback.cfm"> <!--- where fitbit will redirect to after the user enters their details --->
<cfset sClientToken = "#url.oauth_token#"> <!--- returned after an access token call --->
<cfset sClientTokenSecret = "#url.oauth_verifier#"> <!--- returned after an access token call --->


<!--- set up the required objects including signature method--->
<cfset oReqSigMethodSHA = CreateObject("component", "oauth.oauthsignaturemethod_hmac_sha1")>
<cfset oToken = CreateObject("component", "oauth.oauthtoken").createEmptyToken()>
<cfset oConsumer = CreateObject("component", "oauth.oauthconsumer").init(sKey = sConsumerKey, sSecret = sConsumerSecret)>

<cfset Parameters = structNew()>
<cfset parameters.oauth_token=url.oauth_token>
<cfset parameters.oauth_verifier=url.oauth_verifier>

<cfset oReq = CreateObject("component", "oauth.oauthrequest").fromConsumerAndToken(
    oConsumer = oConsumer,
    oToken = oToken,
    sHttpMethod = "POST",
    sHttpURL = sTokenEndpoint,stparameters=Parameters )>

<cfset oReq.signRequest(
    oSignatureMethod = oReqSigMethodSHA,
    oConsumer = oConsumer,
    oToken = oToken)>

Header:<Cfdump var="#oreq.toheader()#"><br>


<cfhttp url="http://api.fitbit.com/oauth/access_token" method="post" result="tokenresponse">
    <cfhttpparam type="header" name="Authorization" value="#oReq.TOHEADER()#" />
</cfhttp>

我将返回以下错误:

{"errors":[{"errorType":"oauth","fieldName":"oauth_access_token","message":"Invalid signature or token 'xxxxxxxxxxxxxxxxxxxxxxx' or token 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'"}],"success":false}

这似乎是因为验证者和令牌没有出现在标题内(或任何地方)......

所以基本上我认为一个好的oauth回调文件示例会让我走上正轨。

1 个答案:

答案 0 :(得分:1)

让我先说明我没有使用FitBit API。从您收到的错误和您提供的链接,API要求授权标头包含在请求中。以下是如何在ColdFusion cfhttp调用中包含HTTP标头的示例。

您引用的API文档提到请求需要以下授权标头参数:

  
      
  • oauth_callback - 回调网址。服务器存储此URL,并在用户授权客户端时重定向到该URL。
  •   
  • oauth_consumer_key - 注册时同意的客户密钥。
  •   
  • oauth_nonce - 客户端唯一生成的随机字符串,用于允许服务器验证请求的唯一性。
  •   
  • oauth_signature - 根据OAuth 1.0协议第3.4节:签名计算的签名。
  •   
  • oauth_signature_method - 签名方法:HMAC-SHA1
  •   
  • oauth_timestamp - 时间戳
  •   
  • oauth_version - 1.0
  •   

从他们的示例中,您的ColdFusion代码看起来像这样:

<cfhttp url="#oREQ.getString()#" method="get" result="tokenResponse">
    <cfhttpparam type="header" name="oauth_callback" value="http%3A%2F%2Fexample.fitbit.com%2Fapp%2FcompleteAuthorization" />
    <cfhttpparam type="header" name="oauth_consumer_key" value="fitbit-example-client-application" />
    <cfhttpparam type="header" name="oauth_nonce" value="161822064" />
    <cfhttpparam type="header" name="oauth_signature" value="Omf%2Bls2gn%2BDlghq245LRIyfMdd8%3D" />
    <cfhttpparam type="header" name="oauth_signature_method" value="HMAC-SHA1" />
    <cfhttpparam type="header" name="oauth_timestamp" value="1270248082" />
    <cfhttpparam type="header" name="oauth_version" value="1.0" />
</cfhttp>

希望这足以让你更进一步。

更新
我确实遇到了一些传递参数的other oauth examples。如果前一个方法不起作用,以下是该方法的示例:

<cfhttp url="#oREQ.getString()#" method="get" result="tokenResponse">
    <cfhttpparam type="header" name="content-type" value="application/x-www-form-urlencoded">
    <cfhttpparam type="oauth_callback" name="FormField" value="http%3A%2F%2Fexample.fitbit.com%2Fapp%2FcompleteAuthorization" />
    <cfhttpparam type="oauth_consumer_key" name="FormField" value="fitbit-example-client-application" />
    <cfhttpparam type="oauth_nonce" name="FormField" value="161822064" />
    <cfhttpparam type="oauth_signature" name="FormField" value="Omf%2Bls2gn%2BDlghq245LRIyfMdd8%3D" />
    <cfhttpparam type="oauth_signature_method" name="FormField" value="HMAC-SHA1" />
    <cfhttpparam type="oauth_timestamp" name="FormField" value="1270248082" />
    <cfhttpparam type="oauth_version" name="FormField" value="1.0" />
</cfhttp>