How do I do basic authentication with RestClient? - ruby

Does anyone know how to do basic authentication with RestClient?
I need to create a private repository on GitHub through their RESTful API.

The easiest way is to embed the details in the URL:
RestClient.get "http://username:password#example.com"

Here is an example of working code where I support optional basicauth but don't require the user and password be embedded in the URL:
def get_collection(path)
response = RestClient::Request.new(
:method => :get,
:url => "#{#my_url}/#{path}",
:user => #my_user,
:password => #my_pass,
:headers => { :accept => :json, :content_type => :json }
).execute
results = JSON.parse(response.to_str)
end
Do note if #my_user and #mypass are not instantiated, it works fine without basicauth.

From the source it looks like you can just specify user and password as part of your request object.
Have you tried something like:
r = Request.new({:user => "username", :password => "password"})
Also if you look down in the Shell section of the ReadMe it has an example of specifying it as part of restshell.
$ restclient https://example.com user pass
>> delete '/private/resource'

This works and follows RFC 7617 for Http Basic Authentication:
RestClient::Request.execute(
method: :post,
url: "https://example.com",
headers: { "Authorization" => "Basic " + Base64::encode64(auth_details) },
payload: { "foo" => "bar"}
)
def auth_details
ENV.fetch("HTTP_AUTH_USERNAME") + ":" + ENV.fetch("HTTP_AUTH_PASSWORD")
end

Thanks to Kelsey Hannan:
RestClient.get("https://example.com",
{
Authorization: "Basic #{Base64::encode64('guest:guest')}"
}
)
RestClient.post("https://example.com",
{ }.to_json,
{
Authorization: "Basic #{Base64::encode64('guest:guest')}"
}
)

Related

Authentication headers using Rest Client Ruby Gem

I have already created a basic authentication key, now I am just trying to utilize it. I have tried a few different variations, but none seem to show Authorization in the request headers.
$auth = 'Basic cmFtZXNoQHVzYW1hLmNvbTpyYW1lc2h1JEBtcA=='
#response = resource.post('Authorization' => $auth)
nor
#response = resource.post(:authorization => $auth)
nor
#response = resource.post(:Authorization => $auth)
nor
#response = resource.post(:content_type => :json, :accept => :json, :headers => { 'Authorization:' => $auth })
Unfortunately I am not finding a lot of info in the rdoc that can help me solve this. Does anyone have experience adding auth headers using the Rest Client gem?
For Basic Auth, you should be able to set the user and password in plaintext when you create the resource:
resource = RestClient::Resource.new( 'http://example.com', 'user', 'password' )
But if you really need to set the header directly per request:
#response = resource.post( request_payload, :Authorization => $auth )
should work. If it does not, then you may have set $auth incorrectly. However, I think you just missed adding the request payload, so it was using the hash you supplied for that required param, and not setting any headers at all.
Here's a complete and working example using get (I don't have a test service available with Basic Auth and POST)
require 'rest-client'
require 'base64'
$auth = 'Basic ' + Base64.encode64( 'user:passwd' ).chomp
$url = 'http://httpbin.org/basic-auth/user/passwd'
#resource = RestClient::Resource.new( $url )
#response = #resource.get( :Authorization => $auth )
# => "{\n \"authenticated\": true,\n \"user\": \"user\"\n}"
Note: Though this works, I recommend you use the first and simplest method of supplying user and password to the constructor unless you have good reason not to.
Even though I didn't have a payload to send I was trying to send one without. This ended up being the cause. So I included:
json_str = ''
#response = resource.post(json_str, :content_type => :json, :accept => :json, :Authorization => $auth)
And this worked.
If you don't want to use RestClient::Resource, you can include basic auth in a request like this:
RestClient::Request.execute method: :get, url: url, user: 'username', password: 'secret'
The trick is not to use the RestClient.get (or .post, .put etc.) methods since all options you pass in there are used as headers.
This worked great for me, in case anyone wants to use username/password
RestClient.post("https://USERNAME:PASSWORD#yoursite.com/something", { some: "payload data" })

Setting Request Headers in Ruby

I have the rest client gem and I am defining a request like this:
url = 'http://someurl'
request = {"data" => data}.to_json
response = RestClient.post(url,request,:content_type => :json, :accept => :json)
However I need to set the HTTP header to something. For example an API key. Which could be done in curl as:
curl -XHEAD -H x-auth-user: myusername -H x-auth-key: mykey "url"
Whats the best way to do this in ruby? Using this gem? Or can I do it manually to have more control.
The third parameter is the headers hash.
You can do what you want by:
response = RestClient.post(
url,
request,
:content_type => :json, :accept => :json, :'x-auth-key' => "mykey")
You can also do this
RestClient::Request.execute(
:method => :get or :post,
:url => your_url,
:headers => {key => value}
)
I had the same problem with Rest-Client (1.7.2) I need to put both params and HTTP headers.
I solved with this syntax:
params = {id: id, device: device, status: status}
headers = {myheader: "giorgio"}
RestClient.put url, params, headers
I hate RestClient :-)
If PUT isn't allowed we can pass it in the header of POST. Headers in bold. This worked for me:
act_resp = RestClient.post url, req_param, **:content_type => :json, :method => :put**

Correct syntax for get requests with rest-client

Right now I can make a request as follows:
user = 'xxx'
token = 'xxx'
survey_id = 'xxx'
response = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php?Request=getLegacyResponseData&User=#{user}&Token=#{token}&Version=2.0&SurveyID=#{survey_id}&Format=XML"
But there should be some nicer way to do this. I've tried things like:
response = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php", :Request => 'getLegacyResponseData', :User => user, :Token => token, :Version => '2.0', :SurveyID => survey_id, :Format => 'XML'</code>
and variations thereof (strings instead of symbols for keys, including { and }, making the keys lower case, etc.) but none of the combinations I tried seemed to work. What's the correct syntax here?
I tried the first suggestion below. It didn't work. For the record, this works:
surveys_from_api = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php?Request=getSurveys&User=#{user}&Token=#{token}&Version=#{version}&Format=JSON"
but this doesn't:
surveys_from_api = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php", :params => {:Request => 'getSurveys', :User => user, :Token => token, :Version => version, :Format => 'JSON'}
(where I've set version = '2.0').
You need to specify query strings parameters with the symbol :params. Otherwise they will be used as headers.
Example with params:
response = RestClient.get "https://survey.qualtrics.com/WRAPI/ControlPanel/api.php", :params => {:Request => 'getLegacyResponseData', :User => user, :Token => token, :Version => '2.0', :SurveyID => survey_id, :Format => 'XML'}
I had the same problem with Rest-Client (1.7.2)
I need to put both params and HTTP headers.
I solved with this syntax:
params = {id: id, device: device, status: status}
headers = {myheader: "giorgio"}
RestClient.put url, params, headers
I hate RestClient :-)
In rest-client api docs I see that headers is a Hash and if you want to provide both - headers and params, then you need to use a :params key inside the headers Hash. e.g.
headers = { h1 => v1, h2 => v2, :params => {my params} }
What you really need is URI.encode_www_form() method.
uri = URI("https://survey.qualtrics.com/WRAPI/ControlPanel/api.php")
request_params = {
Request: 'getLegacyResponseData',
...
}
uri.query = URI.encode_www_form(request_params)
response = RestClient.get(uri.to_s)

OAuth2 with intridea ruby gem

I have the following code:
token = client.auth_code.get_token(code, :redirect_uri => 'http://localhost:3000')
response = token.get('https://api.foursquare.com/v2/users/self/checkins', {:mode => :query})
The problem is that no matter what :mode I specify I always get a Bearer token in Authorization header. The code in question is a private set_token which always depends on the default :mode which is always :header.
Am I using it wrong?
Thanks!
There seems to be a problem how the oauth2 gem passes variabels inside the objects so mode and param_name seems to be lost on the way. A solution to the problem would be to create a new AccessToken object with the correct parameters instead of using the shorthand. This example is tested against Foursquares api and it works.
require "oauth2"
client = OAuth2::Client.new(
"CLIENT_ID",
"CLIENT_SECRET",
:authorize_url => "/oauth2/authorize",
:token_url => "/oauth2/access_token",
:site => "https://foursquare.com/"
)
puts client.auth_code.authorize_url(:redirect_uri => "http://localhost:4000")
code = gets.chomp
token = client.auth_code.get_token(code, :redirect_uri => "http://localhost:4000")
token = OAuth2::AccessToken.new(client, token.token, {
:mode => :query,
:param_name => "oauth_token",
})
response = token.get('https://api.foursquare.com/v2/users/self/checkins')
puts response.body

Can I use rest-client to POST a binary file to HTTP without multipart?

I have tried to do the following, but the web-service is NOT REST and does not take multi-part. What do I do in order to POST the image?
#response = RestClient.post('http://www.postful.com/service/upload',
{:upload => {
:file => File.new("#{#postalcard.postalimage.path}",'rb')
}
},
{"Content-Type" => #postalcard.postalimage.content_type,
"Content-Length" => #postalcard.postalimage.size,
"Authorization" => 'Basic xxxxxx'
} # end headers
) #close arguments to Restclient.post
Got the answer: use I/O to stream as a string instead of using File.new....
:file => IO.read("#{#postalcard.postalimage.path}")

Resources