How to get Selenium to run the browser as a different user

Selenium is great for testing web-apps. One of the challenges that you’ll eventually run into is needing to control which user is connecting to the system under test. Achieving this is far from intuitive. A search for this topic gives many links that don’t solve this problem:

Most of these are attempting to make use of Impersonation. This doesn’t work as the web-browser process ends-up running under your credentials not the credentials that you impersonated into. This is because Selenium’s code on Windows uses the CreateProcess() function to starts its sub-processes. The MSDN page on that says

“If the calling process is impersonating another user, the new process uses the token for the calling process, not the impersonation token”

How do we achieve our objective then? The answer is to start using RemoteWebDriver together with Selenium Grid. Lets assume we want to run testcases under your account and the account of a user I will call user1.

Start a Selenium hub on your local machine under your account.

Start a Selenium node on your local machine under your account.This node will run web-browsers using your credentials. The following command will start a node that can run Firefox and Internet Explorer on Windows:

java 
-jar Selenium-server-standalone-x.xx.x.jar 
-role node 
-port 55565 
-hub "http://<yourmachine>:4444/grid/register" 
-browser "browserName=firefox" 
-browser "browserName=iexplore"

Start a Selenium node on another machine that is logged on as user1. This node will run web browsers as user1. Make sure that node is starting with different capabilities than your node. For example, here although we start the node on Windows, we manually overrule that and the node tells the hub that its running on Mac.

java 
-jar Selenium-server-standalone-x.xx.x.jar 
-role node 
-port 5556 
-hub "http://<yourmachine>:4444/grid/register" 
-browser "platform=MAC,browserName=firefox,maxinstances=12"

Instead of instantiating the actual implementations such as InternetExplorerDriver or FirefoxDriver, you need to instantiate a RemoteWebDriver. When instantiating the RemoteWebDriver, you can use the DesiredCapabilities object to determine which machine (and thus which user) Selenium will choose to run the browser on. For example:

public IWebDriver CreateNewBrowserFor(string Who)
{
    //Decide which of Selenium nodes we want to connect to 
    string CapabilitiesOfTargetUser;
    if(Who.Equals("user1"))
    {
        //We need to control a browser for user1 on his node
        CapabilitiesOfTargetUser = "platform=Mac;browserName=firefox";
    }
    else if(Who.Equals("me"))
    {
        //We need to control a browser for me on my node
        CapabilitiesOfTargetUser = "platform=WINDOWS";
    }
    else
    {
        throw new ArgumentException();
    }
    
    //Create a Selenium DesiredCapabilities object that contains our choosen capabilities
    Dictionary<string, object> RequestedCapabilities = new Dictionary<string, object> ();
    string[] CapabilitiesArray = CapabilitiesOfTargetUser.Split(';');
    foreach(string KeyValuePair in CapabilitiesArray)
    {
        string key = KeyValuePair.Split('=').First().Trim();
        string value = KeyValuePair.Split('=').Last().Trim();
        RequestedCapabilities[key] = value;
    }
    DesiredCapabilities Capabilities = new DesiredCapabilities(RequestedCapabilities);
    
    //Create the RemoteWebDriver. Selenium's hub will ensure that this RemoteWebDriver is
    //actually controlling a new browser on the correct machine
    return  new RemoteWebDriver
    (
         new Uri("http://localhost:4444/wd/hub")
       , Capabilities
       , new TimeSpan(0, 0, 50)
    );
}