0

I have an application with client-certificate based authentication which I have been trying to automate. By selecting different certificates the user can get different application rights. The idea is to use watir-webdriver based script and rautomation gem and login into the application. In Chrome web browser it looks pretty much like this:

client-certificate

The basic idea is the following:

require 'watir-webdriver'
require 'rautomation'

b = Watir::Browser.new :chrome  
b.goto 'https://example.com' 

# Get the Chrome window
window = RAutomation::Window.new(:title => /Chrome/i)
# Select client certificate     
window.send_keys :return

However, when the script executes and reaches b.goto 'https://example.com' it is stuck because the page is not loaded until certificate is selected. After 60 seconds this results in client timeout and I get a Net::ReadTimeout exception. Thus, the code for certificate selection is never reached.

I have solved this by catching the Net::ReadTimeout exception:

begin
 b.goto 'https://example.com' 
rescue      
  window = RAutomation::Window.new(:title => /Chrome/i)   
  window.send_keys :return
end

This solution is far from optimal as the script has to wait 60 seconds to start the execution. The timeout can be lowered to reasonable wait times with the following piece of code:

client = Selenium::WebDriver::Remote::Http::Default.new
client.timeout = 5 # seconds – default is 60
b = Watir::Browser.new :chrome, :http_client => client

But for the rest of the script client.timeout of 5 seconds would be far too low.

I thought the problem was with goto so I've tried other methods but it seems they all behave in the same way:

b.driver.navigate.to 'https://example.com' # => Net::ReadTimeout
b.execute_script('window.location.href = "https://example.com"') # => Net::ReadTimeout

Can anyone provide me with an optimization advice or some other optimal way to handle the mentioned client certificates?

fing
  • 358
  • 2
  • 7

2 Answers2

3

Wouldn't Thread help you out in here? Not sure if it would, because it depends on Ruby's GIL (global interpreter lock) and underlying Webdriver's technicalities, but you could give it a try.

Something along in these lines could work (not tested):

t = Thread.start { b.goto }

# Not sure if getting handle works or not, but if it does
# then it should be a better way to locate the browser window
window = RAutomation::Window.new(:hwnd => b.window.handle)

# Wait until client certificate window exists
RAutomation::WaitHelper.wait_until { window.windows.any? { |w| w.text =~ /Select a certificate/ }}

# Select client certificate     
window.send_keys :return

# Wait for the page load to finish
t.join
Jarmo Pertman
  • 1,905
  • 1
  • 12
  • 19
  • Yes, you were right! However, it takes a bit for the certificate selection window to appear, so after `t = Thread.start { b.goto }` I had to put a short _sleep_ time: `sleep(2)`. Thanks! I didn't use your window handle code though but my original with window title. – fing Jan 05 '16 at 09:16
  • Using handle instead of a title is better since this means you will operate with a browser window, which Watir uses and not some other one you might have open. Also `sleep` is never a good solution because you do not know what's the magic time it has to wait (or it might wait too long, e.g. waste valuable time). I've updated my answer with a possible better solution. – Jarmo Pertman Jan 05 '16 at 16:55
  • Well, I completely agree with all your points, however, `b.window.handle` says: `NoMethodError: protected method 'handle' called`, maybe this worked in _watir-classic_? I have also tried `b.window.inspect`, `b.driver.window_handle`, `b.window.hash` but RAutomation couldn't locate the window with this. As for the second part with `RAutomation::WaitHelper.wait_until`, I'm afraid it doesn't work. I think the problem is that "_Select a certificate_" is not really a text on the parent window, but on some kind of submodal window. I couldn't reach it and check if it exits in any way I tried... – fing Jan 07 '16 at 07:50
0

Watir only works on browser rendered pages. Try ignoring the certificate completely. http://watirwebdriver.com/browser-certificates/

titusfortner
  • 4,099
  • 2
  • 15
  • 29
  • It doesn't seem to me that you understood my question. I am talking about client certificates which are used for application login. Your advice is about server certificates. Also, it's clear that Watir alone cannot deal with Chrome certificates, that's why I'm using **rautomation** gem which does the job quite nicely. – fing Dec 02 '15 at 18:28
  • Currently Watir is blocking while a page is loading. When browsers begin to adopt the new WebDriver W3C standard, you will be able to set a page load strategy of none (https://w3c.github.io/webdriver/webdriver-spec.html#dfn-page-loading-strategy). Until then you're stuck with rescuing the exception if you want to do something before the page finishes loading. Would creating a Firefox Profile with the certificates pre-imported work? http://stackoverflow.com/questions/10889085/automating-ssl-client-side-certificates-in-firefox-and-selenium-testing – titusfortner Dec 02 '15 at 22:37
  • Thanks @titusfortner, the new WebDriver certainly seems interesting. The _Firefox_ solution might work, however that browser is not the focus of my automation efforts as nobody is using it to access the mentioned application (it's not easy for end users to make _Firefox_ work with Smart card certificates). There are some _IE_ users though and certificate selection behavior is different there so I can even get it to work, but my main focus remains _Google Chrome_. – fing Dec 03 '15 at 07:09