Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Store login session cookie in browser using ruby mechanize

I am trying to login to a website and redirect to a secured page from a rails action. My code looks something like this.

 def redirect_to_external 
   agent = Mechanize.new
   page = agent.get('http://example.com/home.asp')
   login_form = page.form_with(:name => "loginForm")
   login_form.login = 'username'
   login_form.password = 'password'
   agent.submit(login_form)

   #cookies = agent.cookie_jar.store.map {|i|  i} #need to store the cookie with a specific in browser
   redirect_to('http://example.com/admin.asp') #page behind password protection
 end

Login is successful in the background, but actual redirection to the admin page is asking again for authentication in the browser, as the session cookie is not stored in the browser. Tried storing the cookies from cookie_jar, but couldn't find the exact way to do that. Can someone help me in this?

like image 637
Vijendra Avatar asked Sep 03 '13 13:09

Vijendra


2 Answers

I struggled with this one for a long time! The other answers on StackOverflow didn't exactly address how to cache the cookies and retrieve them, so I'm combining my experience with the other answers I've read, into one solution here.

(See:

Rails 3 - Log into another site and keep cookie in session

Store login session cookie in browser using ruby mechanize

Get Mechanize to handle cookies from an arbitrary POST (to log into a website programmatically)

keep mechanize page over request boundaries

).

I used this solution to create a custom OAuth2.0 for a website that doesn't support the real OAuth2.0.

  1. The user gave me credentials for the other site. I passed them onto the site via Mechanize in the create method of my Sessions controller and immediately destroyed them (I don't want to touch someone else's secure stuff as much as possible. That's why this all takes place under an SSL as well).

  2. That means my Mechanize instance with the cookies I need will get destroyed once I redirect anywhere else in my app. For example, in my app, I next redirected to the index method of my Sessions Controller. If you're new to rails you might think the same instance variables (like the mechanize agent with those cookies) would be available from create to index, but that's wrong, each redirect will destroy everything! (basically)

  3. So before the redirect, you need to store the cookies. The only way to store something like this between requests is via the cache, and the cache doesn't like to store the whole mechanize instance. Instead you need to store serialized cookies. The only trouble is, Mechanize doesn't have a method for outputting its cookies as a string, it can only save them as a file. What to do?

  4. StringIO to the rescue! You can essentially fake a file with StringIO. After all that talking, here's the code:

    @agent = Mechanize.new
    #handle the sign in stuff
    stringio = StringIO.new
    @agent.cookie_jar.save(stringio, session: true)
    cookies = stringio.string
    session[:login_cookies] = cookies
    

Note that I passed session: true to the save method of cookie_jar. Without that parameter, the cookie will only save non-session cookies.

  1. So now our session cache has a string that has all of the cookies from mechanize. To get them back after a redirect you'll need StringIO again:

    @agent = Mechanize.new
    cookies = session[:login_cookies]
    @agent.cookie_jar.load StringIO.new(cookies)
    
  2. And voila! Your new agent is ready to act just like the old one.

like image 134
KCE Avatar answered Sep 21 '22 09:09

KCE


Please refer following code.This create a code within a block this will maintain authentication,

 def redirect_to_external 
    @agent = Mechanize.new
    @agent.get('http://example.com/home.asp') do | home_page | # Need to pass the others requests into the block
      login_form = home_page.form_with(:name => "loginForm")
      login_form.login = 'username'
      login_form.password = 'password'
      @agent.submit(login_form)
      #cookies = agent.cookie_jar.store.map {|i|  i} #need to store the cookie with a specific in browser
      @agent.get('http://example.com/admin.asp') #page behind password protection
   end  
 end
like image 38
Babasaheb Gosavi Avatar answered Sep 25 '22 09:09

Babasaheb Gosavi