I'm using webdriver.Firefox
and I'm trying to send the following custom header:
self.headers = { 'Authorization': 'Basic %s' % b64encode(bytes(self.args.user + ':' + self.args.password, "utf-8")).decode("ascii") }
in the following way:
self.driver.get(self.base_url + "/", headers=self.headers)
which is similar way as shown here, but I'm guessing it's using completely different driver.
However I've the error:
TypeError: get() got an unexpected keyword argument 'headers'
I've checked the old issue #2047: How to add a header to a request?, but it's closed as duplicate of another Won't Fix issue.
Is there any way of simply test the site using Selenium which is behind Basic Authentication?
One suggestion is to use proxy, however I don't believe such simple functionality doesn't exist.
Any suggestions?
5 Answers 5
I've tested using format http://user:pass@host
and it works.
So in Python (in setUp() of MyClass(unittest.TestCase)
class) this should look like:
self.base_url = "http://user:pass@host"
In Java based on #34 at code.google, the following code should work as well:
public void login(String username, String password){
WebDriver driver = getDriver();
String URL = "http:// + username + ":" + password + "@" + "link";
driver.get(URL);
driver.manage().window().maximize();
}
or:
FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("network.http.phishy-userpass-length", 255);
driver = new FirefoxDriver(profile);
driver.get(http://username:[email protected]/);
or:
FirefoxProfile profile = new FirefoxProfile();
profile.setPreference("network.http.phishy-userpass-length", 255);
profile.setPreference("network.automatic-ntlm-auth.trusted-uris", "<host>");
driver = new FirefoxDriver();
selenium = new WebDriverBackedSelenium(driver, "http://<user>:<password>@<host>");
or:
selenium.start("addCustomRequestHeader=true");
selenium.windowMaximize();
selenium.addCustomRequestHeader( "Authorization","Basic "+"YWRpZGFzOmFkaWRhczEyMyM=" );
or eventually by sending keys using SendKeys()
:
SendKeys("myUser");
SendKeys("{TAB}");
SendKeys("MyPassword");
SendKeys("~"); // Enter
or by using Alert API.
See also: Basic Authentication for FirefoxDriver, ChromeDriver and IEdriver?
For Chrome, please follow: How to override basic authentication in selenium2 chrome driver?
However each one of above has some downsides, so the feature needs to be more portable and there are some plans to do that (see: #453 at GitHub).
-
I tried
self.driver.addCustomRequestHeader
andself.driver.add_custom_request_header
and neither work on Selenium 2.0 (Webdriver). Is this method only available on Selenium RC which is no longer supported? github.com/SeleniumHQ/selenium-google-code-issue-archive/issues/…Cynic– Cynic2017年08月15日 17:25:22 +00:00Commented Aug 15, 2017 at 17:25 -
3The format user:pass in the URL is now a deprecated standard, and as such should not be used.Frank H.– Frank H.2018年04月13日 06:54:31 +00:00Commented Apr 13, 2018 at 6:54
I would like to add one more point:
If your application is making AJAX requests then this solution will not work directly. The HTTP authentication prompt will be shown. In order to bypass that what can be done is from the test case directly fire the URL for which the Ajax request will be sent by the application later. This will create the HTTP authorization header which will be carried in all subsequent requests including the Ajax requests and the authentication prompt will not be shown thus enabling smooth execution of the test case.
What I did for FirefoxDriver is this approach (this only uses for the base url, not for any further requests to other sites which may require basic authentification):
- configuring Firefox not to ask/warn about logging in with basic auth
- Passing user and password with the URL:
http://user:[email protected]
See here or my pull request.
-
2The format user:pass in the URL is now a deprecated standard, and as such should not be usedFrank H.– Frank H.2018年04月13日 06:55:08 +00:00Commented Apr 13, 2018 at 6:55
-
Yes, unfortunately it does not work any more, and there is for now, no other way to achieve it.Paul Wellner Bou– Paul Wellner Bou2018年04月14日 08:25:56 +00:00Commented Apr 14, 2018 at 8:25
Here is a solution that will work in recent versions of Google Chrome with recent versions of selenium. It generates a tiny chrome extension (~30 lines of code) that will add the headers for you. I've created a Java builder class to easily generate the extension. Here is how you can use it:
// Add basic auth header with a chrome extension on every request
File authExtension = new SeleniumChromeAuthExtensionBuilder()
.withBasicAuth("Ali Baba", "Open sesame")
.withBaseUrl("https://example.org/*")
.build();
try {
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions = chromeOptions.addExtensions(authExtension);
webDriver = new ChromeDriver(chromeOptions);
} finally {
authExtension.delete();
}
And that's all. Chrome will then use basic auth on every sub url of https://example.org.
You can get the builder class here: https://gist.github.com/gellweiler/ab0ecb67afb8063a1d276c116bfb26e2.
This problem is still relevant in 2021. However the solution from accepted answer is no longer valid.
The general solution now is to set up proxy that would serve the headers for your test. In python that could be Proxy Py tool that can be run directly from your test code.
You can implement a plugin that would be handing requests from your browser by adding corresponding headers:
from proxy.http.proxy import HttpProxyBasePlugin
from proxy.http.parser import HttpParser
from typing import Optional
import base64
class BasicAuthorizationPlugin(HttpProxyBasePlugin):
"""Modifies request headers."""
def before_upstream_connection(
self, request: HttpParser) -> Optional[HttpParser]:
return request
def handle_client_request(
self, request: HttpParser) -> Optional[HttpParser]:
basic_auth_header = 'Basic ' + base64.b64encode('webelement:click'.encode('utf-8')).decode('utf-8')
request.add_header('Authorization'.encode('utf-8'), basic_auth_header.encode('utf-8'))
return request
def on_upstream_connection_close(self) -> None:
pass
def handle_upstream_chunk(self, chunk: memoryview) -> memoryview:
return chunk
One more thing you need to consider is that you cannot easily modify HTTPs traffic. However Proxy Py allows to do that.
You can find complete solution in Four simple steps to add custom HTTP headers in Selenium Webdriver tests in Python
Explore related questions
See similar questions with these tags.
http://user:pass@host
as host.