Handle WebDriver browser prompt for ADFS credentials Selenium C#

While working on Automating the UI using Selenium C#, you might encounter a scenario where a website requires to be authenticated with ADFS. The browser would prompt the user to provide the AD domain credentials to authorize for accessing the website. So automating this scenario with the Selenium C# API, would require you to provide the domain credentials programatically.

The WebDriver used is Firefox with Geckodriver. Another post explains the working of the automation and initialization of the WebDriver in detail here.

Code sample is as shown below:

public static IWebDriver driverWeb;
driverWeb.Navigate().GoToUrl(link);
try
{
	driverWeb.SwitchTo().Alert().SendKeys("Username" + Keys.Tab + "Password");
	driverWeb.SwitchTo().Alert().Accept();
}
catch { }

try
{
	driverWeb.FindElement(By.Id("acknowledgeCookieId")).Click();
}
catch { }

Take screen-shot of webpage with Firefox and Geckodriver using Selenium with C#

Gecko is a web browser engine used in many applications developed by Mozilla Foundation and the Mozilla Corporation. It is a proxy for using W3C WebDriver-compatible clients to interact with Gecko-based browsers, in this case, Firefox. Gecko Driver acts as the bridge between your script in Selenium and the Firefox browser.

Firefox browser implements the WebDriver protocol using an executable called GeckoDriver.exe. This executable starts a server on your system through which all interaction happens. It translates calls into the Marionette automation protocol by acting as a proxy between the local and remote ends.

To generate the screenshot, the web page will be loaded in the Firefox WebDriver and the height of the window adjusted appropriately. Every GeckoDriver process spawns 4 Firefox processes which you can check through Task Manager. The Preview generation logic can be written as a Web Service and hosted on IIS. The AppPool would require to be run with LocalSystem permission to enable communication between GeckoDriver and Firefox WebDriver.

The below code will run Firefox WebDriver in headless mode:

public static IWebDriver driverWeb;
public static FirefoxOptions optionsFirefox;
static int totalWidth = 1024;
static int additionalHeight = 220;
static int additionalHeightOffset = 2180;
static int normalHeight = 768;
static int explicitWaitTime = 5;

Setup browser profile:

static Firefox()
{
	try
	{
		optionsFirefox = new FirefoxOptions();
		FirefoxProfile profile = new FirefoxProfile();
		profile.SetPreference("permissions.default.desktop-notification", 1);
		profile.AcceptUntrustedCertificates = true; //Accept SSL certificates which have expired
		profile.AssumeUntrustedCertificateIssuer = false; //Firefox assumes untrusted SSL certificates are coming from untrusted issuer 
		profile.SetPreference("general.useragent.override", Convert.ToString(ConfigurationManager.AppSettings["driverUserAgent"]));
		profile.SetPreference("layout.css.devPixelsPerPx", "0.9");
		optionsFirefox.Profile = profile;
		optionsFirefox.AddArgument("-headless");
		KillExistingProcesses();
		initializeWebDriver();
	}
	catch (Exception e)
	{
		throw e;
	}
}

Initialize Web Driver:

public static void initializeWebDriver()
{
	try
	{
		FirefoxDriverService service = FirefoxDriverService.CreateDefaultService(Convert.ToString(ConfigurationManager.AppSettings["driverPath"]));
		service.HideCommandPromptWindow = true;
		driverWeb = null;
		driverWeb = new FirefoxDriver(service, optionsFirefox, new TimeSpan(0, 0, Convert.ToInt16(ConfigurationManager.AppSettings["setDriverTimeout"])));
		driverWeb.Manage().Timeouts().ImplicitWait = new TimeSpan(0, 0, Convert.ToInt16(ConfigurationManager.AppSettings["setPageLoadTimeout"]));
		driverWeb.Manage().Timeouts().PageLoad = new TimeSpan(0, 0, Convert.ToInt16(ConfigurationManager.AppSettings["setPageLoadTimeout"]));
	}
	catch
	{
		//log exception.
	}
}

Generate Preview:

//This method will be called from a Rest Service and returns a byte array for image.
public byte[] getImage()
{
	byte[] imageDataWeb;
	try
	{
		if (driverWeb == null)
		{
			lock (padlockWeb)
			{
				//double lock check for thread-safety.
				if (driverWeb == null)
				{
					initializeWebDriver();
				}
			}
		}

		if (getHttpResponseCode(link))
		{
			lock (driverWeb)
			{
				driverWeb.Navigate().GoToUrl(link);
				Thread.Sleep(100);
				/*Start Area: Get rendered page height/width and adjust browser accordingly*/
				try
				{
					var javaScriptExecutor = driverWeb as IJavaScriptExecutor;
					var waitPage = new WebDriverWait(driverWeb, TimeSpan.FromSeconds(explicitWaitTime));
					bool readyCondition(IWebDriver webDriver) => (bool)javaScriptExecutor.ExecuteScript("return document.readyState == 'complete'");
					waitPage.Until(readyCondition);

					string HeightScript = "return document.body.scrollHeight";
					long totalHeight1 = (long)javaScriptExecutor.ExecuteScript(HeightScript);
					int totalHeight = (int)totalHeight1;
					if (totalHeight == 0)
					{
						totalHeight = normalHeight + additionalHeight;
					}
					else
					{
						if (totalHeight <= additionalHeightOffset)
						{
							totalHeight += additionalHeight;
						}
					}
					driverWeb.Manage().Window.Size = new Size(totalWidth, totalHeight);
				}
				catch (Exception e)
				{
					_txtSource.TraceEvent(TraceEventType.Error, 0, e.Message);
					_txtSource.TraceEvent(TraceEventType.Error, 0, e.StackTrace);
					_txtSource.Flush();

					driverWeb.Manage().Window.Size = new Size(totalWidth, normalHeight + additionalHeight);
				}
				/*End Area: Get rendered page height/width and adjust browser accordingly*/

				screenshot = ((ITakesScreenshot)driverWeb).GetScreenshot().AsByteArray;

				if (screenshot.Length == 0)
				{
					throw new Exception("Website not responding.");
				}

				driverWeb.Navigate().GoToUrl("about:blank");
				driverWeb.Manage().Window.Size = new Size(totalWidth, normalHeight);
				return screenshot;
			}
		}
		else
		{
			imageDataWeb = returnErrorImage(); //return error image.
		}
		return imageDataWeb;

	}
	catch (Exception e)
	{
		//log exception
		imageDataWeb = doExtractEmptyPage();
		return imageDataWeb;
	}
	finally
	{
		imageDataWeb = null;
	}
}