Basic Authentication

Basic Authentication

Created by Alan Baird.

If you try and visit a site that uses basic authentication, this is the box you will appear. This wont appear in any unit tests, and its difficult to show working code, as we need a site that is secure, and we would need to supply passwords etc.

Solution #1

One way to handle this is using WindowHelper.rb. This script is basically just a wrapper around AutoIt to help you deal with pop ups. The following code to implements this in an example using Test::Unit. Also, since you frequently see the Security Alert dialog along with Basic Authentication, this example deals with this pop up as well. You will need to have two other files, handle_logon.rb and handle_security_alert.rb in the same directory as your main script. These scripts are launched in additional threads to deal with the Basic Authentication pop up and the Security Alert pop up.

One problem with this script is that if you leave the Security Alert pop up thread in-tact and the script does not encounter this dialog box, the script will hang waiting for a Security Alert pop up that will never happen. To correct this, simply remove variable b and the b.join statement from main.rb.

main.rb
require 'unittests/setup'
require 'watir'
require 'watir/WindowHelper'

class TC_Logon_Test < Test::Unit::TestCase
  def setup
    @url = 'yoursite.com'
    @login_title = "Connect to #{@url}"
    @username = 'uname'
    @password = 'pass'
  end
  
  def test_logon
    a = Thread.new {
      system("ruby handle_logon.rb \"#{@login_title}\" \"#{@username}\" \"#{@password}\"")
    }

    b = Thread.new {
      system('ruby handle_security_alert.rb')
    }

    $ie.goto(@url)
    
    a.join
    b.join
    
    # continue code here...

  end
  
end
handle_security_alert.rb
require 'watir'
require 'watir/WindowHelper'

helper = WindowHelper.new
helper.push_security_alert_yes
puts "done with security alert" 
handle_logon.rb
require 'watir'
require 'watir/WindowHelper'

# these parameters are passed to the logon method in WindowHelper.rb
login_title = ARGV[0]
username = ARGV[1]
password = ARGV[2]

helper = WindowHelper.new
helper.logon(login_title, username, password)

Solution #2

Added 07/15/2008

Another solution that doesn't require launching new threads.


#if prompted about the security certificate use 'click_no_wait' to be able to deal with the popup
ie.link(:text, 'Continue to this website (not recommended).').click_no_wait
    
#use autoit to work with the authentication popup
Watir.autoit.WinWait('Connect to ')
Watir.autoit.Send('username')
Watir.autoit.Send('{TAB}')
Watir.autoit.Send('password')
Watir.autoit.Send('{ENTER}')

Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.
  1. Feb 18, 2009

    Robert Papesch says:

    Here is a single method that works without having to make a kludgy system call.....

    Here is a single method that works without having to make a kludgy system call..

    def basic_auth(secure_site_url)
      # Internet Explorer instance is called $ie, initialized elsewhere like so:
      # $ie = Watir::IE.new
       
      @user = 'my_username_example'
      @pass = 'my_password_example'
      @url = secure_site_url
      
      a = Thread.new {
        $ie.goto(@url)
      }
      sleep 2
      $ie.send_keys(@user)
      $ie.send_keys('{TAB}')
      $ie.send_keys(@pass)
      $ie.send_keys('{ENTER}')
      a.join
    end
    

    //
    Note, if the following error crops up, there are a couple of things to try...

    c:/apps/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie.rb:113:in `initialize': failed to create WIN32OLE object from `AutoItX3.Control' (WIN32OLERuntimeError)

    Solution 1: Add this to the top of your script

    require 'win32ole'

    Solution 2: Register AutoIt via MS-DOS

    >cd "C:\apps\ruby\lib\ruby\gems\1.8\gems\watir-1.6.2\lib\watir"
    >regsvr32 AutoItX3.dll

    Now it oughta work...

  2. Jun 11, 2009

    Aaron OBrien says:

    I got the above script to work for internet explorer, that is: require "wati...

    I got the above script to work for internet explorer, that is:

    require "watir"
    # To get this script to work:
    # Solution 1 (didn't work
    #require 'win32ole'
    #
    # Solution 2 (did work), enter:
    # cd "C:\ruby\lib\ruby\gems\1.8\gems\watir-1.6.2\lib\watir"
    # regsvr32 AutoItX3.dll
    
    
    class Login   
    	def basic_auth(secure_site_url)
    	  @user = 'myusername'
    	  @pass = 'mypassword'
    	  @url = secure_site_url
    	  
    	  a = Thread.new {
    	    $ie.goto(@url)
    	  }
    	  sleep 2
    	  $ie.send_keys(@user)
    	  $ie.send_keys('{TAB}')
    	  $ie.send_keys(@pass)
    	  $ie.send_keys('{ENTER}')
    	  a.join
    	end
    end
    
    $ie = Watir::IE.new
    url = "http://www.someplace.com"
    login = Login.new
    login.basic_auth(url)
    

    However if I use firewatir, with:

    Watir::Browser.default='firefox'
    $browser=Watir::Browser.new
    

    It doesn't work, I get the following error:

    C:\svn\ruby\scrap>ruby 03.rb
    03.rb:22:in `basic_auth': undefined method `send_keys' for #<FireWatir::Firefox:
    0x3221174> (NoMethodError)
            from 03.rb:34
    
    C:\svn\ruby\scrap>ruby 03.rb
    03.rb:22:in `basic_auth': undefined method `send_keys' for #<FireWatir::Firefox:
    0x3221174> (NoMethodError)
            from 03.rb:34
    

    Any help will be really appreciated, I am a newby here and am really keen to use firefox instead of ie.

  3. Jun 11, 2009

    Aaron OBrien says:

    With the help of some other forums, I got the following to work as an alternativ...

    With the help of some other forums, I got the following to work as an alternative, but again, it is only for IE, any ideas to get this working with firefox would be greatly appreciated.

    require "watir"
    require 'watir/ie'
    
    
    Watir::Browser.default='ie'
    browser=Watir::Browser.new
    url = "http://www.someplace.com"
    
    Thread.new{
          sleep(1)      # put appropriate sleep time
    			Watir.autoit.WinWait('Connect to ')
    			Watir.autoit.Send('myusername')
    			Watir.autoit.Send('{TAB}')
    			Watir.autoit.Send('mypassword')
    			Watir.autoit.Send('{ENTER}')
    }
    browser.goto(url)
    
  4. Oct 15

    Rick Herrick says:

    I can get both of these solutions to work on their own. The issue I ran into was...

    I can get both of these solutions to work on their own. The issue I ran into was detecting the presence of the basic auth pop-up dialog. Everything works fine with these solutions (and the variations suggested in the comments) as long as the pop-up dialog appears!

    But sometimes the pop-up doesn't appear (usually this is due to an instance of IE that has already authenticated being open on the desktop). In that case, the solution using the handle_logon.rb script just hangs, waiting, I guess, for something to happen. The solution using the browser.send_keys calls just pushes ahead, sending keys willy nilly regardless of their appropriateness.

    The solution I came up with was using the Watir.autoit.WinWait call to get the window, as shown in Solution #2, but adding a timeout to the call. Once that returns, you can check the return value. The WinWait function returns 0 if it can't locate the indicated window within the specified timeout period.

    If the window was found, I call Watir.autoit.WinActivate to bring the window to the front and Watir.autoit.Send as shown. I added one extra line to make sure the username text box is selected before sending the keystrokes (the ! represents the Alt key to the Send function, meaning that !u is Alt-U).

    Of course, if the window wasn't found, we just continue on our way.

    test_base.rb
    # Opens the given URL in the browser and clears basic authentication.
    def open_url
      a = Thread.new { @browser.goto(@url) }
      sleep 2
    
      win_exists = Watir.autoit.WinWait(@login_title, "", 5)
    
      if (win_exists > 0)
        Watir.autoit.WinActivate(@login_title)
        Watir.autoit.Send('!u')
        Watir.autoit.Send(@username)
        Watir.autoit.Send('{TAB}')
        Watir.autoit.Send(@password.gsub(/!/, '{!}'))
        Watir.autoit.Send('{ENTER}')
      end
      a.join
    end
    

    Hope this helps someone!