16

I'm attempting to create some selenium tests for a website that requires windows authentication. I got my first test up and running fairly easily, but it pauses as soon as the system prompts for credentials.

Is there a way to provide these credentials that will still allow me to run the tests across all the major browsers?

11 Answers 11

4

I ended up creating a custom profile for Firefox and adding the AutoAuth addon. Not particularly elegant but it works. Credit goes to the following blog post:

http://www.codemiller.com/post/5923640143/overcoming-auth-pop-ups

4

I've found that WebDriver works with IE 9 and Windows / NTLM authentication via using Windows Impersonation and IE's automatic logon feature.
An example of the impersonateValidUser method you'll need to call can be found here: Impersonate a Specific User in Code.

Essentially you want to do the following (ensuring that IE 9 is configured to "Log me in automatically"):

impersonateValidUser("DifferentUser", "DOMAIN", "Password");
// WebDriver now logged in as "DifferentUser"
IWebDriver webDriver = new InternetExplorerDriver();

To revert back to the user running the tests / Selenium RC just call:

undoImpersonation();
  • did not work for me – ColacX Feb 12 '15 at 15:41
4

For Firefox this works:

C#

var profile = new FirefoxProfile();
profile.SetPreference("network.automatic-ntlm-auth.trusted-uris", ".companyname.com");

return new FirefoxDriver(profile);

Python

from selenium.webdriver import Firefox, FirefoxProfile

profile = FirefoxProfile()
profile.set_preference('network.automatic-ntlm-auth.trusted-uris', '.companyname.com')

return Firefox(firefox_profile=profile)
  • Thanks for the answer. I got my code worked. Python: profile = {'network.automatic-ntlm-auth.trusted-uris': ".companyname.com"} with Browser('firefox', profile_preferences=profile) as browser: browser.visit(url) – wei Nov 14 '17 at 6:19
1

Impersonation is tricky. I haven't done this with Selenium, but I have done it with WatiN and IE. I will post my WatiN solution which you could make work with Selemium (I think).

The trick is that you need to separate the launching of IE and the automation of IE as you can't just do them both in one hit.

First launch ie using System.Diagnostics.Process. Once you have launched IE you can then use the code from here to attach and talk to IE using impersionation

Here is the code

    [TestMethod]
    public void TestMethod()
    {
        SecureString password = new SecureString();
        password.AppendChar('p');
        password.AppendChar('a');
        password.AppendChar('s');
        password.AppendChar('s');
        password.AppendChar('w');
        password.AppendChar('o');
        password.AppendChar('r');
        password.AppendChar('d');

        ProcessStartInfo psi = new ProcessStartInfo();
        psi.UserName = "localtest";
        psi.Password = password;
        psi.UseShellExecute = false;
        psi.LoadUserProfile = true;
        psi.FileName = "c:\\Program Files\\Internet Explorer\\iexplore.exe";
        psi.Arguments = "about:blank";

        Process proc = new Process();
        proc.StartInfo = psi;
        proc.Start();

        t.Join();

        proc.Kill(); 
    }

    private static void DoWorkAs(object o)
    {
        User u = o as User;


        IntPtr hToken = IntPtr.Zero;
        IntPtr hTokenDuplicate = IntPtr.Zero;

        if (Win32.LogonUser(u.UserName, u.Domain, u.Password, 2 /*LOGON32_LOGON_INTERACTIVE*/, 0 /*LOGON32_PROVIDER_DEFAULT*/, out hToken))
        {
            if (Win32.DuplicateToken(hToken, 2, out hTokenDuplicate))
            {
                WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate);
                WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate();

                // domain\username
                Console.WriteLine(" Thread 2 : " + WindowsIdentity.GetCurrent().Name);


                // This is WatiN code, you will need to replace with Selenium
                IE ie = IE.AttachToIE(Find.ByUrl("about:blank"));

                ie.GoTo(@"http://www.google.com/");
                ie.TextField(Find.ByName("q")).TypeText("WatiN");
                ie.Button(Find.ByName("btnG")).Click();

                Assert.IsTrue(ie.ContainsText("WatiN"));
                ie.GoTo("about:blank");

                //revert
                impersonationContext.Undo();
                Console.WriteLine(WindowsIdentity.GetCurrent().Name);
            }
        }
        if (hToken != IntPtr.Zero) Win32.CloseHandle(hToken);
        if (hTokenDuplicate != IntPtr.Zero) Win32.CloseHandle(hTokenDuplicate);
    }

    public class User
    {
        public User(string u, string d, string p)
        {
            Domain = d;
            UserName = u;
            Password = p;
        }
        public string UserName;
        public string Domain;
        public string Password;
    }
    public class Win32
    {
        // P/Invoke snask
        [DllImport("advapi32.dll", SetLastError = true)]
        public static extern bool LogonUser(
            string lpszUsername,
            string lpszDomain,
            string lpszPassword,
            int dwLogonType,
            int dwLogonProvider,
            out IntPtr phToken);

        [DllImport("advapi32.dll", SetLastError = true)]
        public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int
           SECURITY_IMPERSONATION_LEVEL, out IntPtr DuplicateTokenHandle);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern bool CloseHandle(IntPtr hHandle);

    }

This code needs a refactor, and wont work on Vista with IE7, because of an IE bug that was fixed in IE8.

1

There are two ways to achieve this:

  1. You can directly pass the credentials in url so it will skip authentication window.

  2. You can also use AutoIT which will help you to acheive the same in your test.

Here is the article will guide you:

http://learn-automation.com/handle-windows-authentication-using-selenium-webdriver/

1

What I'm using as solution that works across OS and Browsers is a MITM Proxy. See https://github.com/rac2030/CAPS which alows you to set the SSL Context yourself giving you the freedom wo use any method you want to gather that context (I use this for an Entrust based authentication using Smartcards and from a special Test certificate store) but usually stick with client certificates as this works across OS and especially from our CI Setup.

1

Javascript support for webdriver is pretty rough, so here's an example of this in Javascript, in case you're like me and need to go spend another half hour digging through documentation to find the right method names in JS:

let profile = new firefox.Profile();
profile.setPreference('network.automatic-ntlm-auth.trusted-uris', '.company.com')
let options = new firefox.Options().setProfile(profile);

let driver = new webdriver.Builder().
    usingServer('http://localhost:4444/wd/hub').
    withCapabilities(webdriver.Capabilities.firefox()).
    setFirefoxOptions(options).
    build();

(Obviously ES6; if you're on Node < 4, change all instances of let to var)

  • Is there a way to pass credentials other than the logged in user? – Polymorphic Jan 11 '17 at 12:52
  • @MohammadaminKhayat Not that I know of. Now you're talking about tricking Windows into confirming that you're a user you aren't, which would require more knowledge of the Windows side of things than I possess currently. You may want to re-think your strategy some – Yamikuronue Jan 16 '17 at 14:39
  • I am trying to test a scenario that is completed by multiple users with different roles. So I have to get change the user credentials for each browser instance. Because the web app is using windows authentication. – Polymorphic Jan 16 '17 at 14:45
  • @MohammadaminKhayat Any way to set up the role in the setup phase of the test? So before you run the test, you change the role for the user you're running under? – Yamikuronue Jan 16 '17 at 14:48
  • Changing the role of user is not realistic enough. In my case, different users actually have their own effect on the data and scenario. For example there would be some concerns about the creator of a record and the editor of a record (the user itself, not the role). So for the sake of a good end-to-end test, it is better to be close to reality. – Polymorphic Jan 16 '17 at 15:22
0

I used Java Thread and Robot with Selenium to automate windows active directory authentication. You may refer to my response here Windows Authentication using Selenium and Java Thread.

  • First, for a question this old, your answer doesn't add anything of value. Second, your proposed solution from SE doesn't actually answer the OP's question, which is for a solution that works across ALL major browsers. – Kate Paulk May 6 '15 at 11:39
0

i'm using this and it's working for me. It parses the url and i enter inside it the username and password, this way i can do the authentication via URL.

public void login(String username, String password){
        WebDriver driver = getDriver();
        String URL = "http://" + username + ":" + password + "@" + "link";
        driver.get(URL);
        driver.manage().window().maximize();
    }
  • 1
    This does not work on all browsers. For example Firefox shows a warning popup that you will have to handle. Apart from that it is not clever to transmit the password in the URL. This is a security risk – Elmue May 13 '17 at 14:51
0

This is not quite what the OP asked, but is an alternative for IE and Edge testing of a site with AD authentication; simply stop having the browsers prompt, and instead just use the AD credentials of the user running the browser.

If you are wanting to test your site against Edge or IE and the site uses AD authentication then both browsers will prompt to your users credentials as has been described for Firefox and Chrome.

You can make both browsers silently accept the AD credentials of the user running the browser by simply adding the site to the test machines list of intranet zone sites.

0

Based on Marc Lopez and Rohit's answer. I got my code worked.

Python:

from splinter import Browser

profile = {'network.automatic-ntlm-auth.trusted-uris': ".companyname.com"}

with Browser('firefox', profile_preferences=profile) as browser:
browser.visit(url)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.