Friday 11 March 2016

Handling Authentication Popup Dialog in Selenium WebDriver

It has been observed that Selenium WebDriver is unable to handle the Authentication Security Popup Dialog because the Authentication popup is originated from OS. Selenium WebDriver has the limitation to work only inside DOM.

So the basic workflow to mitigate this issue is to let this job to be assigned to external process using thread. Which means before hitting the URL or before the security pop up appears this code needs to be executed. This external process will wait for the security pop up to appear and then mitigate the situation.

I tried many solutions while researching over internet. Some advised AutoIT script, Sikuli,  shell scripting. Every other had some issues and inconsistent performance. I learned that mitigating this at OS level would definitely be a good solution. I was able to implement a code involving exploitation of User32.dll methods.

I was surprised about the performance of this piece of code which provided robust solution to handle the Authentication Security Popup. Below is the raw C# console application code, please customise this accordingly.



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections;

namespace PopupHandler
{

    class Program
    {
        private const int WM_SETTEXT = 0x000C;
        public const int WM_SYSCOMMAND = 0x0112;
        public const int SC_CLOSE = 0xF060;
        public const int BM_CLICK = 0x00F5;
        public const int EM_SETPASSWORDCHAR = 0X00CC;

        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
        [DllImport("User32.dll")]
        private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindows);
        [DllImport("User32.dll")]
        private static extern Int32 SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, StringBuilder lParam);
        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        private void HandlePopUp(string browser, string executionmode, string uid, string pwd)
        {
           if (browser.Equals("ie"StringComparison.InvariantCultureIgnoreCase))
            {
                if (executionmode.Equals("cancel"StringComparison.InvariantCultureIgnoreCase))
                {
                    // retrieve Windows Security main window handle
                    IntPtr hWnd = FindWindow("#32770""Windows Security");
                    int iterateForSecurityPopup = 0;
                    for (iterateForSecurityPopup = 0; iterateForSecurityPopup < 20; iterateForSecurityPopup++)
                    {
                        hWnd = FindWindow("#32770""Windows Security");
                        if (!hWnd.Equals(IntPtr.Zero))
                        {

                            SendMessage(hWnd, WM_SYSCOMMAND, SC_CLOSE, 0);
                            Environment.Exit(0);
                        }
                        System.Threading.Thread.Sleep(1000);
                    }
                    if (hWnd.Equals(IntPtr.Zero)) {
                        Console.WriteLine("Dialog with title Security Popup not found");
                    }
                }
                else (executionmode.Equals("ok"StringComparison.InvariantCultureIgnoreCase))
                {
                    string[] data = { uid, pwd };
                    // retrieve Windows Security main window handle
                    IntPtr hWnd = FindWindow("#32770""Windows Security");
                    int iterateForSecurityPopup = 0;
                    IntPtr duihWnd;

                    for (iterateForSecurityPopup = 0; iterateForSecurityPopup < 25; iterateForSecurityPopup++)
                    {
                        hWnd = FindWindow("#32770""Windows Security");
                        if (!hWnd.Equals(IntPtr.Zero))
                        {
                            // Get DirectUIHandle
                            duihWnd = FindWindowEx(hWnd, IntPtr.Zero"DirectUIHWND""");
                            if (!duihWnd.Equals(IntPtr.Zero))
                            {
                                ArrayList childs = GetAllChildrenWindowHandles(duihWnd, 15);
                                int i = 0;
                                int j = 0;
                                while (i <= childs.Count)
                                {
                                    IntPtr edithWnd = FindWindowEx((IntPtr)childs[i], IntPtr.Zero"Edit""");
                                    if (!edithWnd.Equals(IntPtr.Zero))
                                    {
                                        // send WM_SETTEXT message to control
                                        SendMessage(edithWnd, WM_SETTEXT, IntPtr.Zeronew StringBuilder(data[j]));
                                        j++;
                                        if (j == 2) { break; }
                                    }
                                    i++;
                                }

                                i = 0;
                                while (i <= childs.Count)
                                {
                                    //Click on ok
                                    IntPtr btnOkhWnd = FindWindowEx((IntPtr)childs[i], IntPtr.Zero"Button""OK");

                                    if (!btnOkhWnd.Equals(IntPtr.Zero))
                                    {
                                        SendMessage(btnOkhWnd, BM_CLICK, 0, 0);
                                        break;
                                    }
                                    i++;
                                }
                            }
                        }

                       System.Threading.Thread.Sleep(750);
                    }

                    if (hWnd.Equals(IntPtr.Zero))
                    {
                        Console.WriteLine("Dialog Handle not present");
                    }

                }

           
            }


        }

        static ArrayList GetAllChildrenWindowHandles(IntPtr hParent, int maxCount)
        {
            ArrayList result = new ArrayList();
            int ct = 0;
            IntPtr prevChild = IntPtr.Zero;
            IntPtr currChild = IntPtr.Zero;
            while (true && ct < maxCount)
            {
                currChild = FindWindowEx(hParent, prevChild, nullnull);
                if (currChild == IntPtr.Zero)
                {
                    int errorCode = Marshal.GetLastWin32Error();
                    break;
                }
                result.Add(currChild);
                prevChild = currChild;
                ++ct;
            }
            return result;
        }

        static void Main(string[] args)
        {

            string browser = args[0];
            string mode = args[1];
            string uid = "";
            string pwd = "";

                uid = args[2];
                pwd = args[3];

            new Program().HandlePopUp(browser, mode, uid, pwd);


        }
    }

}



-Pankaj Dhapola
Let's Think on it