ruby httpclient & NTLM - ruby

I am trying to do what look simple but clearly isn't - authenticate with NTLM.
The example in the documentation (http://www.rubydoc.info/gems/httpclient/2.1.5.2/HTTPClient) looks straightforward, but when I try it I always get a 401.
I created a simple website in IIS whch requires NTLM. I tested this works in IE & chrome.
I then
require 'httpclient'
require 'pp'
require 'kconv' #seemed to be needed due to a bug..
require 'rubyntlm' # probably not needed directly?
domain = 'http://qvcluster1/'
url = 'http://qvcluster1/default.htm'
user = 'testuser'
password = 'testpassword'
client = HTTPClient.new
client.set_auth(nil ,user,password)
r = client.get("http://qvcluster1/default.htm")
pp r
From my understanding there is not much more to it, yet it is failing
this is the tail end of what I get from the last line:
#reason_phrase="Unauthorized",
#request_absolute_uri=nil,
#request_method="GET",
#request_query=nil,
#request_uri=#<URI::HTTP http://qvcluster1/default.htm>,
#status_code=401>,
Any suggestions are appreciated !
As an aside, I just tested from curl and this works fine:
"C:\Program Files\cURL\bin\curl.exe" --ntlm -u testuser:testpassword http://qvcluster1/default.htm

False Alarm - as it turns out there were problems with the web server communicating with the domain controller so it was messing up authentication. I removed and re-added it to the domain and all is fine now!

Related

Requesting An Access Token from Google API Returns 302

I'm trying to get an access token from Google API in my Ruby on Rails app, as part of an overall goal of setting up a raketask. I am able to get an Auth Code fine, but when I make a post request to get an access token, I am getting a 302 error. I'll describe my current code first, and afterward list how I've tried to solve the problem so far.
Current code:
#users_controller
def auth_access
client = Signet::OAuth2::Client.new(
:authorization_uri => 'https://accounts.google.com/o/oauth2/auth',
:token_endpoint_uri => 'https://accounts.google.com/o/oauth2/token',
:client_id => ENV['OAUTH_CLIENT_ID'],
:client_secret => ENV['OAUTH_CLIENT_SECRET'],
:scope => 'https://www.googleapis.com/auth/analytics.readonly',
:redirect_uri => 'http://localhost:3000/google/auth_callback'
)
redirect_to client.authorization_uri.to_s
end
This part works fine so far. It redirects to the consent page, and when the user agrees it then redirects them to the page with the auth code in the url parameters. Next I take that auth code and try to make a POST request to API for an access token:
#users_controller
def auth_callback
http = Net::HTTP.new('accounts.google.com')
path = '/o/oauth2/token'
data = "code=#{params['code']}&client_id=#{ENV['OAUTH_CLIENT_ID']}&client_secret=#{ENV['OAUTH_CLIENT_SECRET']}&redirect_uri=http://localhost:3000/auth_final&grant_type=authorization_code"
response = http.post(path, data)
end
This when I run into a problem. The Google API returns a 302, and includes a message saying something akin to "we moved to 'https://accounts.google.com/o/oauth2/token'".
Here's how I've tried to fix the problem so far:
I assumed that the problem was that the http.post method is making a call to an http and not https.
I've tried including
http.use_ssl = true
http.ssl_version = :SSLv3
This returns the error "SSL_connect returned=1 errno=0 state=SSLv3 read server hello A: wrong version number".
I can take a guess at what this means, but I am still unsure of what the actual problem is and how to solve it. Googling the error message has not been a help.
In a similar vein, I tried using gems to make the https call for me, in particular HTTParty and Typheous, although I was not able to make any progress with them (and am still not even sure that it's an http/https problem).
I've tried using the Signet-Rails gem. This was the most productive method by far, making a successful API call and returning the information. However, it either wasn't saving the refresh token or I cannot find where it is being saved. As I need access to that token to run the rake tasks, I gave up on Signet-Rails.
I tried using Legato, and was constantly running into various problems. Overall, Legato left me with the impression that it did not integrate getting the auth code, consent and tokens into the app, instead requiring the developer to set those up in advance outside of the app's scope. I want to be able to set up the auth code as part of the app. If I am understanding Legato properly, then it is not the gem I need.
I've also tried other various odds and ends but to no avail. The above solutions were the tactics I kept coming back to. Primarily I'm looking for an answer to what is going wrong in my code, and what is the best avenue to fix it (and if I was going down the right track with any of my attempted solutions above, which one?)
Thanks for taking the time to read this and answer!
(on a complete sidenote, those last three list items should be 2, 3, 4, but the stackoverflow text editor thinks it knows better than me...)
Specify the port:
http = Net::HTTP.new('accounts.google.com', 443)
Source: SSL Error on HTTP POST (Unknown Protocol)

How to use SOCKSify proxy

I try to proxy traffic of a ruby application over a SOCKS proxy using ruby 2.0 and SOCKSify 1.5.0.
require 'socksify/http'
uri = URI.parse("www.example.org")
proxy_addr = "127.0.0.1"
proxy_port = 14000
puts Net::HTTP.SOCKSProxy(proxy_addr, proxy_port).get(uri)
This is the minimal working example. Obviously it doesn't work but I think it should. I receive no error messages executing the file, it doesn't stop so I have to abort it manually. I have tried the solution after I found it in this answer (the code in that answer is different, but as mentioned above I first adapted it to my match my existing non-proxy-code and afterwards reduced it)
The proxies work, I tested both tor and ssh -D connection on my own webserver and other websites.
As rubyforge seems to be no longer existing, I can't access the SOCKSify documentation on it. I think the version might be outdated, does not work with ruby 2.0 or something like that.
What am I doing wrong here? Or is there an alternative to SOCKSify?
Checking the documentation for Net::HTTP#Proxies gives an example we can base our code on. Also note the addition of the .body method, also found in the documentation.
Try this code:
require 'socksify/http'
uri = URI.parse('http://www.example.org/')
proxy_addr = '127.0.0.1'
proxy_port = 1400
Net::HTTP.SOCKSProxy(proxy_addr, proxy_port).start(uri.host, uri.port) do |http|
puts http.get(uri.path).body
end

Dropbox SDK for Ruby and not requiring reauthorization

It seems like I must be missing something here. I'm working on a simple app and I'm starting with Dropbox's tutorial:
# Install this the SDK with "gem install dropbox-sdk"
require 'dropbox_sdk'
# Get your app key and secret from the Dropbox developer website
APP_KEY = 'XXXXXXXXXXXXXXX'
APP_SECRET = 'XXXXXXXXXXXXXXX'
CODE = 'QEL2VDUKRj4AAAAAAAAAAcBT_U9GoEvKF2UCXp3h4UA'
flow = DropboxOAuth2FlowNoRedirect.new(APP_KEY, APP_SECRET)
puts flow.start()
access_token, user_id = flow.finish(CODE)
client = DropboxClient.new(access_token)
file = open('working-draft.txt')
response = client.put_file('/magnum-opus.txt', file)
puts "uploaded:", response.inspect
The code only seems to work for one request (or at least one run of the script), and then I get an error:
E:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/dropbox-sdk-1.6.2/lib/dropbox_sdk.rb:69:in `parse_response': invalid_grant (DropboxError)
What do I have to do in order to get this to work without authorizing every single time?
Just store the access token somewhere and reuse it as much as you want.
To try this manually, just print out the value of access_token and then modify your code to just be:
access_token = '<value from previous run>'
client = DropboxClient.new(access_token)

ruby multipart post image with digest auth

Given I have this, using Ruby 1.9.3p194
Authentication is digestauth
require 'json'
require 'httpclient'
API_URL= "https://api.somewhere.com/upload"
API_KEY='blahblah'
API_SECRET ='blahlbah'
IMAGE ='someimage.png'
h=HTTPClient.new
h.set_auth(API_URL, API_KEY, API_SECRET)
File.open(IMAGE) do |file|
body = { 'image' => file}
res = h.post(API_URL, body)
p res.inspect
end
I get errors
Ive tried Typheous, Patron, Mechanize, Curl but want to find a way that is simple and works
e.g.
curl --digest -u myusrname:password -F "image=#image.png" "https://api.somewhere.com/upload"
Curl posts nothing and doesnt work as expected. Ive been assured that the API accepts posts, I have a simple web page that does what I need to do via a simple form and it works fine
Any one know what the easiest way ahead is?
Thanks
Solved it, went back to Curb. It is a RESTful API, RestClient was doing something funky with the digest. HttpClient too was posting blank files. Curb did it.

Testing login in a page

I have to access some pages at work and then log into them to report any problems. I was thinking of writing a program to do this.
First, I have to be able to access the pages, then I have to locate the login form and send the info. Currently, I plan on printing true/false for each test (accessibility and login) and then filling the forms myself. I'm hoping to be able to write something to automate this later.
I was thinking of using Ruby, although I haven't coded in it yet, it seems like it'd make the whole thing easier. I've worked the most with Java, though I have some experience with C++ and a bit of experience with C.
Any advice?
You can use Selenium IDE. It is a record and playback tool for simple web tests, which you can then save as test for Selenium RC in any language you want. I hope it helps
The Python urllib2 module easily permit you to interact with an HTTP server. You can use urrlib2 to read the page to verify the content. You can do a POST with the urlencoded form data and verify the content.
Further, Python has a simple unittest library that will help you structure your tests.
class TestForm( unittest.TestCase ):
def testFillInForm( self ):
data= urllib.urlencode( { field1="value", field2="value" } )
response= urllib2.urlopen( "http://localhost/path/to/form", data )
# check the response
if __name__ == "__main__":
unittest.main()
Ruby, PHP and Python all have easy to use HTTP libraries which make this kind of an operation pretty easy. Any of these languages would work fine.
If you want to do this is ruby, The Mechanize gem would be perfect for this
`
require 'mechanize'
agent = WWW::MECHANIZE.new
page = agent.get('localhost/path/to/form')
login_form = page.forms.first #assuming the first form is the one we want
login_form.username = 'myusername'
login_form.password = 'mypassword'
page = agent.submit(login_form)
puts page.body # just to see the results
`
I have found CURL to be really useful and easy to use as well under PHP. Easy to learn.
Handles cookies, HTTPS, etc.
All good.

Resources