I spent a couple days searching for a solution for this.
I have a project I am attempting to create a Selenium WebDriver test suite for. This site is intended to be protected by 2-factor authentication. The 2-factors would be use to deliver a certificate which would authenticate with the server.
At the moment, we have have it so that we access the server with a url beginning with "https://". When we go the url (in firefox) we see a pop-up labeled "User Identification Request" with a dropdown with the label "Choose a certificate to present as identification:".
Earlier, I added the certificate (labeled "client1.p12") by going to Options->Privacy & Security->Certificates->View Certificates, selecting the "Your Certificates" tab, clicking "Import", browsing to the "client1.p12" file and entering the password. By doing this, I can now see the appropriate certificate in the "Choose a certificate to present . . . " dropdown.
The question I have is how do I set-up Selenium WebDriver to select the certificate. The pop-up described above is a Windows component (not html), so I cannot simply click and select the certificate. I am also trying to use the headless option for geckodriver.
The best solution I was able to find involved something like the following:
DesiredCapabilities capabilities = new DesiredCapabilities();
capabilities.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
capabilities.setCapability("ssl-client-certificate-file", "");
capabilities.setCapability("ssl-client-key-passphrase", "");
WebDriver driver = new FirefoxDriver(capabilities);
driver.get();
Unfortunately, I get a "org.openqa.selenium.WebDriverException" at the last line, "driver.get();"
解决方案
I have figured out a partial solution. In other circumstances, it may be all I would need, but, for reasons I will describe at the end, it is insufficient here.
There were two sides to this problem. First, I needed to set up Selenium to accept the server's certificate. Second, I needed to get Selenium to deliver the .p12 certificate to the server.
To accept the server's certificate, I did something like the following:
DesiredCapabilities capabilities = DesiredCapabilities.firefox();
capabilities.setCapability(CapabilityType.ACCEPT_INSECURE_CERTS, true);
. . .
FirefoxOptions firefoxOptions = new FirefoxOptions();
. . .
firefoxOptions.addCapabilities(capabilities);
. . .
driver = new FirefoxDriver(firefoxOptions);
. . .
driver.get(nbisURL);
To send the .p12 certificate to the server, I used a firefox profile. Part of the procedure is described here: https://seleniumbycharan.wordpress.com/2015/07/12/how-to-create-custom-firefox-profile-in-selenium-webdriver/
Essentially, I created a profile ("eAgency-Client1"), as described in the article, which resulted in an open firefox browser. In that browser, I set-up the certificate in the manner I described in my original post. I then set up selenium to use that profile:
ProfilesIni profile = new ProfilesIni();
FirefoxProfile ffProfile = profile.getProfile("eAgency-Client1");
ffProfile.setPreference("security.default_personal_cert", "Select Automatically");
. . .
FirefoxOptions firefoxOptions = new FirefoxOptions();
. . .
firefoxOptions.setProfile(ffProfile);
. . .
driver = new FirefoxDriver(firefoxOptions);
So, interlacing the above two snippets results in my solution.
The problem I have now is that I cannot seem to use that profile on other machines, so this Selenium testing suite is not portable.
I run the testing suite in Jenkins. Jenkins runs on a CentOS server that does not have GUI. I copied the "eAgency-Client1" profile from my local windows machine to the proper location in the CentOS server and modified the profiles.ini file on CentOS appropriately.
(I loosely followed the advice given here http://forum.notebookreview.com/threads/migrate-firefox-profile-from-windows-to-linux.444601/. However, I needed to add the profile to the Jenkins firefox instance by copying it to /var/lib/jenkins/.mozilla/firefox. I also did not copy the entire Mozilla directory. Just the profile, after which I modified the profiles.ini file.)
I know the profile was successfully copied because . . .
FirefoxProfile ffProfile = profile.getProfile("eAgency-Client1");
. . . does not return a null. The trouble comes when I access the site. When I go to the site and get the page source, I can see the standard error which indicates I did not send the certificate:
400 No required SSL certificate was sent400 Bad Request
I do not get this source on my local machine. My local machine gets to the place it needs to go to without trouble. Locally, I do not get the "400 Bad Request".