简体   繁体   English

带有Ruby HTTParty的RingCentral OAuth仅服务器密码流

[英]RingCentral OAuth Sever-Only Password Flow with Ruby's HTTParty

I'm currently trying to write a Data Extraction Application for RingCentral to dump CSVs to AWS as part of a Data Warehousing project. 我目前正在尝试为RingCentral编写数据提取应用程序,以将CSV转储到AWS作为数据仓库项目的一部分。 I've reviewed several pieces of their documentation outlining how to authenticate using the Password Flow, but there seems to be some missing pieces based on their examples in the documentation here . 我已经阅读了他们的文档中的一些内容,概述了如何使用密码流进行身份验证,但是根据此处文档中的示例,似乎缺少了一些内容。

In the example listed under "Password Flow" There is an authentication header that is never mentioned and the value that is included is pulled out out of thin air by the author, and then never mentioned in the authentication steps below it. 在“密码流”下面列出的示例中,有一个身份验证标头从未被提及,并且所包含的值被作者凭空拿出,然后在其下面的身份验证步骤中从未提及。 I can validate that my application meets the Private, Server-Only Requirements with scope 'Read Call Logs'. 我可以验证我的应用程序是否满足“读取呼叫日志”范围的“仅服务器专用”要求。 Below is a screenshot of my settings: [Link to Image because I don't have enough reputation...ugh][2] 以下是我的设置的屏幕截图:[链接到图像,因为我的信誉不足...呃] [2]

Using the Sandbox credentials and endpoint for development, here's what I've tried so far: 使用沙盒凭据和端点进行开发,这是到目前为止我尝试过的工作:

url = 'https://platform.devtest.ringcentral.com/restapi/oauth/token'
headers = {'Content-Type'=>'application/x-www-form-urlencoded'}
body = {:grant_type=>"password", :username=>"13133982093", :password=><OUR_SANDBOX_PASSWORD>}
resp = HTTParty.post(url, headers: headers, body: URI.encode_www_form(body))

The printed response: 印刷的回应:

#<HTTParty::Response:0x7ff29588a420 parsed_response={"error"=>"invalid_client", "error_description"=>"Invalid client: ", "errors"=>[{"errorCode"=>"OAU-153", "message"=>"Invalid client: ", "parameters"=>[{"parameterName"=>"client_id", "parameterValue"=>""}]}]}, @response=#<Net::HTTPBadRequest 400 Bad Request readbody=true>, @headers={"server"=>["nginx/1.10.2"], "date"=>["Tue, 20 Jun 2017 22:05:36 GMT"], "content-type"=>["application/json;charset=utf-8"], "transfer-encoding"=>["chunked"], "connection"=>["close"], "x-application-context"=>["application:8080"], "content-language"=>["en"], "www-authenticate"=>["Bearer realm=\"RingCentral REST API\", error=\"invalid_client\", error_description=\"Invalid client: \""], "rcrequestid"=>["96aaacb0-5604-11e7-97a9-005056bb594d"], "aceroutingkey"=>["sjc11-c01-ace01.c83d65c2-46d3-11e7-ab8e-005056a73f60"], "x-server-name"=>["sjc06-c01-hlb02"], "x-request-time"=>["0.010"], "x-upstream-server"=>["10.24.22.193:8080"], "x-upstream-status"=>["400"], "x-upstream-htime"=>["0.010"], "x-upstream-rtime"=>["1497996336.573"], "x-upstream-ctime"=>["0.000"], "x-tcpinfo"=>["1000, 500, 10, 28960"], "routingkey"=>["SJC11P01"]}> 

I've tried Google Searching for the Error Code OAU-153 and it's completely undocumented. 我已经尝试过Google搜索错误代码OAU-153,并且它完全没有记录。 I've even included things like an Authorization Header produced from the client_id and client_secret (aka - app_key and app_secret) like such: auth= {'Authorization': "Basic #{ Base64.encode64("#{client_id}:#{client_secret}") }"} 我什至包括了诸如由client_id和client_secret(又名-app_key和app_secret)产生的授权标头之类的东西: auth= {'Authorization': "Basic #{ Base64.encode64("#{client_id}:#{client_secret}") }"}

Which was included in a call like: resp = HTTParty.post(token_url, headers: headers, body: URI.encode_www_form(token_body), auth: auth) 包括在如下调用中: resp = HTTParty.post(token_url, headers: headers, body: URI.encode_www_form(token_body), auth: auth)

But this still produced the same error as above with error_description "Invalid Client: " , and error_code OAU-153 . 但这仍然产生与error_description "Invalid Client: "和error_code OAU-153相同的错误。

Additionally, due to project requirements the Ring Central Ruby SDK causes dependency conflicts with very important gems in my current application, thus we're having to write new Auth code for this data source. 此外,由于项目要求,Ring Central Ruby SDK导致与当前应用程序中非常重要的gem发生依赖关系冲突,因此我们必须为此数据源编写新的Auth代码。

At this point I'm lost. 在这一点上我迷路了。 I've heavily validated that my keys, username and password are all correct. 我已经充分验证了我的密钥,用户名和密码是否正确。 I've included the username phone number value as a sanity check for formatting. 我已将username电话号码值包含在内,以进行格式化检查。 I'm essentially left with 2 questions I cannot answer: 我基本上只剩下两个我无法回答的问题:

1) Am I approching this correctly? 1)我是否正确地批准了? Have I selected the correct roles and permissions for this application? 我是否为此应用程序选择了正确的角色和权限? Do I need to create a new one with a different Auth Flow and Privacy settings? 我需要使用不同的“身份验证流程”和“隐私”设置来创建一个新的吗?

2) Am I using the right tools for this? 2)我是否为此使用了正确的工具? Is HTTParty possibly a culprit in how it's sending my requests? HTTParty可能是导致其发送请求的罪魁祸首吗? Digging in the Repository hasn't brought much to light in the time I've spent. 在我度过的时间里,在存储库中挖掘并没有带来太多启发。

EDIT: 编辑:

We made changes to the project which allowed us to use the SDK for authentication like this: 我们对项目进行了更改,使我们可以使用SDK进行身份验证,如下所示:

client = RingCentralSdk::REST::Client.new do | config |
    config.app_key = ENV['RC_CLIENT_ID']
    config.app_secret = ENV['RC_CLIENT_SECRET']
    config.server_url = @server_url
    config.username = @account_num
    config.password = @password
    config.extension = @extension_id

Then we store token info as a hash by doing: token_hash = client.token.to_hash 然后,我们通过执行以下token_hash = client.token.to_hash将令牌信息存储为哈希: token_hash = client.token.to_hash

An example of the hash can be seen below: 哈希的示例如下所示:

{"token_type"=>"bearer", "refresh_token_expires_in"=>604800, 
 "scope"=>"ReadCallLog", "owner_id"=>[COMPANY's OWNER_ID], 
 "endpoint_id"=>"N0UV835BQ2C_Bz2ofJA1Eg", 
 :access_token=> [REMOVED FOR SECURITY],
 :refresh_token=> [REMOVED FOR SECURITY], 
 :expires_at=>1498081681} 

However, now I cannot perform 2 operations: a simple authenticated request or a token Refresh. 但是,现在我无法执行2个操作:简单的身份验证请求或令牌刷新。

Attempting simple call-log request: 尝试简单的call-log请求:

uri = "https://platform.devtest.ringcentral.com/restapi/v1.0/account/<phone_num_with_pre_+>/extension/101/call-log"
headers = {"Accept"=>"application/json", "Authorization"=> "#{ token_hash[:access_token] }"} 
resp = HTTParty.get(uri, headers: headers)

This sort of request earns me an error: 这种请求使我出错:

 #<HTTParty::Response:0x7fdf2b0ae800 parsed_response={"errorCode"=>"InvalidParameter", "message"=>"Resource for parameter [accountId] is not found", "errors"=>[{"errorCode"=>"CMN-102", "message"=>"Resource for parameter [accountId] is not found", "parameterName"=>"accountId"}], "parameterName"=>"accountId"}, @response=#<Net::HTTPNotFound 404 Not Found readbody=true>, @headers={"server"=>["nginx/1.10.2"], "date"=>["Wed, 21 Jun 2017 21:39:58 GMT"], "content-type"=>["application/json;charset=UTF-8"], "content-length"=>["290"], "connection"=>["close"], "rcrequestid"=>["2b66c9d6-56ca-11e7-b418-005056bb26b9"], "routingkey"=>["SJC11P01PAS02"], "x-error-id"=>["2b66c9d6-56ca-11e7-b418-005056bb26b9"], "content-language"=>["en-US"], "x-rate-limit-group"=>["heavy"], "x-rate-limit-limit"=>["10"], "x-rate-limit-remaining"=>["9"], "x-rate-limit-window"=>["60"]}>

This error suggests 2 things, 1) My account_id parameter is input wrong -- however, I copied the Sandbox number directly from the RC Developer Portal for my application, both with the prepended + and without, and the same error occurred, 2) There are no call-log records, and thus the API server thinks that the Resource doesn't exists and throws the error. 此错误表明有两件事,1)我的account_id参数输入错误-但是,我直接从RC开发人员门户为我的应用程序复制了沙箱编号,同时带前置+和不带,并且发生了相同的错误,2)没有call-log记录,因此API服务器认为资源不存在并引发错误。

So, I guess my question is? 所以,我想我的问题是? How can I even develop against this Sandbox when there is no data for me to query? 当没有可供我查询的数据时,我该如何甚至针对此沙箱进行开发? Is there an easy way to make data for this account? 有没有简单的方法可以为该帐户制作数据?

Attempting Refresh Token Flow: 尝试刷新令牌流:

NOTE: I just sign-in again every time I need a token at the moment. 注意:目前,每次需要令牌时,我都会再次登录。 Clunky but not terrible. 笨拙但并不可怕。

Perform the request: 执行请求:

uri = "https://platform.devtest.ringcentral.com/restapi/oauth/token"
refresh_headers = {"Accept"=>"application/json", "Content-Type"=>"application/x-www-form-urlencoded", 
                   "Authentication"=>"Basic [BASE64_ENCODED_APP_KEY:APP_SECRET_DELIMITED_COMBO]}
refresh_body = {:grant_type=>"refresh_token", :refresh_token=>"#{token_hash[:refresh_token]}"} 
resp = HTTParty.post(uri, headers: refresh_headers, body: URI.www_encode_form(refresh_body))

Earn an error: 产生错误:

#<HTTParty::Response:0x7fdf3055d8d8 parsed_response={"error"=>"invalid_client", "error_description"=>"Invalid client: ", "errors"=>[{"errorCode"=>"OAU-153", "message"=>"Invalid client: ", "parameters"=>[{"parameterName"=>"client_id", "parameterValue"=>""}]}]}, @response=#<Net::HTTPBadRequest 400 Bad Request readbody=true>, @headers={"server"=>["nginx/1.10.2"], "date"=>["Wed, 21 Jun 2017 22:16:07 GMT"], "content-type"=>["application/json;charset=utf-8"], "transfer-encoding"=>["chunked"], "connection"=>["close"], "x-application-context"=>["application:8080"], "content-language"=>["en"], "www-authenticate"=>["Bearer realm=\"RingCentral REST API\", error=\"invalid_client\", error_description=\"Invalid client: \""], "rcrequestid"=>["3958edb2-56cf-11e7-8758-005056bb26b9"], "aceroutingkey"=>["sjc11-c01-ace01.c83d65c2-46d3-11e7-ab8e-005056a73f60"], "x-server-name"=>["sjc06-c01-hlb01"], "x-request-time"=>["0.000"], "x-upstream-server"=>["10.24.22.193:8080"], "x-upstream-status"=>["400"], "x-upstream-htime"=>["0.000"], "x-upstream-rtime"=>["1498083367.846"], "x-upstream-ctime"=>["0.000"], "x-tcpinfo"=>["1000, 500, 10, 28960"], "routingkey"=>["SJC11P01"]}> 

Weep silently to yourself... 对自己默默哭泣...

:'-(

Frustratingly the documentation for the RingCentral Ruby SDK have no documented method for refreshing these tokens, and nebulously mentions something about "Manual Refreshes". 令人沮丧的是,RingCentral Ruby SDK的文档中没有记录这些令牌刷新的方法,并且含糊地提到了有关“手动刷新”的内容。 Any ideas or thoughts on my requests or the SDK would be appreciated. 我的要求或SDK的任何想法或想法,将不胜感激。 I would prefer to perform refreshes than re-auth over and over again. 我宁愿执行刷新,而不是一遍又一遍地重新验证。

Frustratingly the documentation for the RingCentral Ruby SDK have no documented method for refreshing these tokens, and nebulously mentions something about "Manual Refreshes". 令人沮丧的是,RingCentral Ruby SDK的文档中没有记录这些令牌刷新的方法,并且含糊地提到了有关“手动刷新”的内容。 Any ideas or thoughts on my requests or the SDK would be appreciated. 我的要求或SDK的任何想法或想法,将不胜感激。 I would prefer to perform refreshes than re-auth over and over again. 我宁愿执行刷新,而不是一遍又一遍地重新验证。

Token refresh is in the detailed documentation in the /docs folder of the repo and also posted on the Ruby SDK's Read the Docs . 令牌刷新位于/docs/docs文件夹中的详细文档中,并且还发布在Ruby SDK的Read the Docs上 I'll look to make those docs more evident. 我将使这些文档更加明显。

The Token Refresh section of the docs is available here: 可在此处找到文档的令牌刷新部分:

http://ringcentral-sdk-ruby.readthedocs.io/en/latest/usage/authorization/Authorization/#token-refresh http://ringcentral-sdk-ruby.readthedocs.io/en/latest/usage/authorization/Authorization/#token-refresh

Regarding the call log request, you can make it directly using the SDK with the API call below. 关于呼叫日志请求,您可以直接使用带有以下API调用的SDK进行请求。

client = RingCentralSdk::REST::Client.new do | config |
  # ...
end

client.http.get 'account/~/extension/~/call-log'

For the accountId and extensionId path parameters, you can use ~ to indicate the account and extension for the currently logged in user. 对于accountIdextensionId路径参数,可以使用~指示当前登录用户的帐户和扩展名。 If you want to specify the accountId and extensionId , be aware that these are backend id values and do not correspond to the main company phone number or extensionNumber that a user dials. 如果要指定accountIdextensionId ,请注意这些是后端ID值,并且与用户拨打的主要公司电话号码或extensionNumber不对应。 You can retrieve the accountId and extensionId for your logged in user by calling the account/~/extension API endpoint. 您可以通过调用account/~/extension API端点来检索已登录用户的accountIdextensionId

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM