Can't get access token for ExactOnline with OAuth - ruby

I'm following the OAuth tutorial here to get a access code in order to authenticate my API requests to the online accounting software Exact Online.
However, I'm stuck at step 3, where I use the authorization code returned in step 2 to obtain the access token.
Here's what I'm trying:
require 'httparty'
EXACT_CLIENT_ID = '<REDACTED>'
EXACT_CLIENT_SECRET = '<REDACTED>'
EXACT_SERVER_BASE_URL = 'https://start.exactonline.nl'
EXACT_AUTH_CODE = '<REDACTED>'
response = HTTParty.post("#{EXACT_SERVER_BASE_URL}/api/oauth2/token", headers: {'Content-Type' => 'application/x-www-form-urlencoded'}, query: {code: EXACT_AUTH_CODE, redirect_uri: 'http://<REDACTED>.runscope.net/', grant_type: 'authorization_code', client_id: EXACT_CLIENT_ID, client_secret: EXACT_CLIENT_SECRET})
puts response
# => 'Bad request'
puts response.code
# => 400
I don't understand why this is happening. When looking at the list of response codes here, the code means:
The request could not be understood by the server due to malformed
syntax. The client SHOULD NOT repeat the request without
modifications.
What am I doing wrong?
Update #1:
I've also tried:
response_2 = HTTParty.post("#{EXACT_SERVER_BASE_URL}/api/oauth2/token", :headers => {'Content-Type' => 'application/x-www-form-urlencoded'}, :body => {'code' => EXACT_AUTH_CODE, 'redirect_uri' => 'http://<REDACED>.runscope.net/', 'grant_type' => 'authorization_code', 'client_id' => EXACT_CLIENT_ID, 'client_secret' => EXACT_CLIENT_SECRET})
But the response is the same.

Even though using the HTTP POST method you're providing the values as query parameters by supplying them to the query: parameter to the .post method. Instead you should provide them in the body: parameter, see: How can I implement this POST request using HTTParty?
Also your syntax re. body: :body should be fixed, so it would look like:
response_2 = HTTParty.post("#{EXACT_SERVER_BASE_URL}/api/oauth2/token", :headers => {'Content-Type' => 'application/x-www-form-urlencoded'}, :body => {'code' => EXACT_AUTH_CODE, 'redirect_uri' => 'http://<REDACED>.runscope.net/', 'grant_type' => 'authorization_code', 'client_id' => EXACT_CLIENT_ID, 'client_secret' => EXACT_CLIENT_SECRET})
Last but not least: the code value is one-time usage only and has a short lifetime; make sure you use a freshly obtained one.

Related

How can I get Request Parameter of this below code in JSON Format For Logging it into Db

$result = Http::withHeaders([
'Authorization' => config(''),
])->post($endPoint, [
"username" => '',
"password" => '',
// "username" => $user->username,
// "password" => $user->password,
"days" => 7
]);
In this code I want to save the request and request parameter in JsonFormat for logging into mysql db.
Laravel testing
https://laravel.com/docs/master/testing
or
Postman offers a sleek user interface with which to make HTML requests, without the hassle of writing a bunch of code just to test an API's functionality
https://www.postman.com/

How can I implement this POST request using HTTParty?

I am having difficulty making a POST request to an API endpoint using Ruby's HTTParty library. The API I'm interacting with is the Gittip API and their endpoint requires authentication. I have been able to successfully make an authenticated GET request using HTTParty.
You can see in the example code:
user = "gratitude_test"
api_key = "5962b93a-5bf7-4cb6-ae6f-aa4114c5e4f2"
# I have included real credentials since the above is merely a test account.
HTTParty.get("https://www.gittip.com/#{user}/tips.json",
{ :basic_auth => { :username => api_key } })
That request works and returns the following as expected:
[
{
"amount" => "1.00",
"platform" => "gittip",
"username" => "whit537"
},
{
"amount" => "0.25",
"platform" => "gittip",
"username" => "JohnKellyFerguson"
}
]
However, I have been unable to make a successful POST request using HTTParty. The Gittip API describes making a POST request using curl as follows:
curl https://www.gittip.com/foobar/tips.json \
-u API_KEY: \
-X POST \
-d'[{"username":"bazbuz", "platform":"gittip", "amount": "1.00"}]' \
-H"Content-Type: application/json"
I have tried (unsuccessfully) structuring my code using HTTParty as follows:
user = "gratitude_test"
api_key = "5962b93a-5bf7-4cb6-ae6f-aa4114c5e4f2"
HTTParty.post("https://www.gittip.com/#{user}/tips.json",
{
:body => [ { "amount" => "0.25", "platform" => "gittip", "username" => "whit537" } ],
:basic_auth => { :username => api_key },
:headers => { 'Content-Type' => 'application/json' }
})
The first argument is the url and the second argument is an options hash. When I run the code above, I get the following error:
NoMethodError: undefined method `bytesize' for [{"amount"=>"0.25", "platform"=>"gittip", "username"=>"whit537"}]:Array
from /Users/John/.rvm/rubies/ruby-2.0.0-p247/lib/ruby/2.0.0/net/http/generic_request.rb:179:in `send_request_with_body'
I have tried various other combinations of structuring the API call, but can't figure out how to get it to work. Here's another such example, where I do not user an array as part of the body and convert the contents to_json.
user = "gratitude_test"
api_key = "5962b93a-5bf7-4cb6-ae6f-aa4114c5e4f2"
HTTParty.post("https://www.gittip.com/#{user}/tips.json",
{
:body => { "amount" => "0.25", "platform" => "gittip", "username" => "whit537" }.to_json,
:basic_auth => { :username => api_key },
:headers => { 'Content-Type' => 'application/json' }
})
Which returns the following (a 500 error):
<html>
<head>
<title>500 Internal Server Error</title>
</head>
<body>\n Internal server error, program!\n <pre></pre>
</body>
</html>
I'm not really familiar with curl, so I'm not sure if I am incorrectly translating things to HTTParty.
Any help would be appreciated. Thanks.
Just a guess, but it looks like you're passing a hash in the body when JSON is expected.
Try replacing the :body declaration with:
:body => [{ "amount" => "0.25",
"platform" => "gittip",
"username" => "whit537" }].to_json
Edit:
I suggested the to_json serializer, but misplaced it by putting it after the hash instead of the array and removing the array altogether. The example uses multiple records, so the array is necessary.
After looking at this thread, it looks like Gittip is picky about the accept header.
:headers => { 'Content-Type' => 'application/json', 'Accept' => 'application/json'}
So, the full suggestion is:
HTTParty.post("https://www.gittip.com/#{user}/tips.json",
{
:body => [ { "amount" => "0.25", "platform" => "gittip", "username" => "whit537" } ].to_json,
:basic_auth => { :username => api_key },
:headers => { 'Content-Type' => 'application/json', 'Accept' => 'application/json'}
})

Using webmock to stub partial headers

I am creating tests using webmock. I want to test that a particular header field is set, but I don't care about other header fields. When I use this:
stub_request(:get, "https://myhost.com/api").
with(:headers => {:user_agent => 'Custom user agent'}).
to_return(:status => 200, :body => '')
I get an error because I am not stubbing all the headers:
Unregistered request: GET https://myhost.com/api with headers {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Custom user agent'}
You can stub this request with the following snippet:
stub_request(:get, "https://myhost.com/api").
with(:headers => {'Accept'=>'application/json', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent'=>'Custom user agent'}).
to_return(:status => 200, :body => "", :headers => {})
I don't care about the Accept and Accept-Encoding headers - how do I stub so they are ignored?
Web mock does partial matching by default. In your case, the :user_agent key is a symbol which won't match the string 'User-Agent'. Converting to a string should work:
'User-Agent'=>'Custom user agent'
You can use hash_including:
stub_request(:get, "https://myhost.com/api").
with(:headers => hash_including({:user_agent => 'Custom user agent'})).
to_return(:status => 200, :body => '')

Ruby rest-client file upload as multipart form data with basic authenticaion

I understand how to make an http request using basic authentication with Ruby's rest-client
response = RestClient::Request.new(:method => :get, :url => #base_url + path, :user => #sid, :password => #token).execute
and how to post a file as multipart form data
RestClient.post '/data', :myfile => File.new("/path/to/image.jpg", 'rb')
but I can't seem to figure out how to combine the two in order to post a file to a server which requires basic authentication. Does anyone know what is the best way to create this request?
How about using a RestClient::Payload with RestClient::Request...
For an example:
request = RestClient::Request.new(
:method => :post,
:url => '/data',
:user => #sid,
:password => #token,
:payload => {
:multipart => true,
:file => File.new("/path/to/image.jpg", 'rb')
})
response = request.execute
RestClient API seems to have changed. Here's the latest way to upload a file using basic auth:
response = RestClient::Request.execute(
method: :post,
url: url,
user: 'username',
password: 'password',
timeout: 600, # Optional
payload: {
multipart: true,
file: File.new('/path/to/file, 'rb')
}
)
The newest best way may be that:
the link is enter link description here
RestClient.post( url,
{
:transfer => {
:path => '/foo/bar',
:owner => 'that_guy',
:group => 'those_guys'
},
:upload => {
:file => File.new(path, 'rb')
}
})
Here is an example with a file and some json data:
require 'rest-client'
payload = {
:multipart => true,
:file => File.new('/path/to/file', 'rb'),
:data => {foo: {bar: true}}.to_json
}
r = RestClient.post(url, payload, :authorization => token)

Using Typhoeus to POST an array to a URL

I'm using Typhoeus to post a hash to my API url. It's actually an array containing a set of hashes. Here's effectively what I'm doing:
companies = Array.new
company = { 'name' => 'Company 1' , 'company_url' => 'http://company.com' }
companies.push(company)
company2 = {'name' => 'Company 2' , 'company_url' => 'http://company2.com' }
companies.push(company2)
request = Typhoeus::Request.post("http://myapi.com/1.0/startups/create_batch",
:username => 'user',
:password => 'password',
:auth_method => :basic,
:params => {'companies' => companies} )
print "Create_batch response "+request.body
Once I run the script I get the output which states "Create_batch response Disallowed Key Characters.". I'm not sure what it's referencing at this point. I've looked over the text output of what print companies shows up but I don't see any strange code.
Anybody have any insights on what I should do?

Resources