4

I need to automate a test that uses Windows Authentication.

I know that the the prompt that opens up is not part of the HTML page, yet why my code is not working:

login_page.click_iwa()
sleep(5)
self.page.keyboard.type('UserName')
sleep(5)
self.page.keyboard.press('Tab')
self.page.keyboard.type('Password')
Panagiotis Kanavos
  • 120,703
  • 13
  • 188
  • 236
Tal Angel
  • 1,301
  • 3
  • 29
  • 63
  • Hey, not able to understand iwa. can you check if iwa is a frame? usually, authorizations are iframe for which you might need frameLocator (https://playwright.dev/docs/api/class-framelocator) then only frame.keyboard functions will work – tushi43 Jun 28 '23 at 14:54
  • @tushi43 IWA is a windows prompt that asks for a username and password for a web site. It is not a dialog or normal alert. – Tal Angel Jun 28 '23 at 15:39
  • Have you tried this URL method? https://stackoverflow.com/a/11522757/8835695 – tushi43 Jun 29 '23 at 11:56
  • 1
    No, Windows authentication isn't a prompt. That's the entire point. There's absolutely no need for a prompt. The browser connects to the server using the user's account transparently. Credentials are only asked *by the browser*, when the current user isn't recognized. The prompt isn't displayed in a web page so isn't visible to Playwright – Panagiotis Kanavos Jul 04 '23 at 13:45
  • 1
    The easy solution is to run the tests using an account that's allowed to connect to the site – Panagiotis Kanavos Jul 04 '23 at 13:47

2 Answers2

2

I solved the issue by using a virtual keyboard:

from pyautogui import press, typewrite, hotkey


def press_key(key):
    press(key)


def type_text(text):
    typewrite(text)


def special_keys(special, normal):
    hotkey(special, normal)

Then, after I implemented the virtual keyboard, I did this:

def login_iwa(self, user_name='User321', password='123456', need_to_fail=False):
        pyautogui.FAILSAFE = False
        self.click_iwa()
        sleep(7)
        type_text(user_name)
        sleep(1)
        press_key('Tab')
        sleep(1)
        type_text(password)
        sleep(1)
        press_key('Enter')
        sleep(2)
        if need_to_fail:
            press_key('Tab')
            sleep(1)
            press_key('Tab')
            sleep(1)
            press_key('Tab')
            sleep(1)
            press_key('Enter')
            sleep(1)

I used pyautogui.FAILSAFE = False because sometime the popup was hiding behind the screen or was openning up on the 2nd screen.

Tal Angel
  • 1,301
  • 3
  • 29
  • 63
-2

I recommend using more protocol-based approaches. I have tested the following methods to authenticate using the the-internet.herokuapp.com/basic_auth endpoint with the username and password set to admin, and all of them worked successfully. Below, you'll find the complete code for each method to make it easy to test them by simply copy-pasting:

  1. Passing the credentials in the URL:

     from playwright.sync_api import sync_playwright
    
     with sync_playwright() as playwright:
         browser = playwright.chromium.launch(headless=False)
         context = browser.new_context()
         page = context.new_page()
         page.goto(url="http://admin:admin@the-internet.herokuapp.com/basic_auth")
         context.close()
         browser.close()
    
  2. Passing the credentials to the http_credentials context parameter:

     from playwright.sync_api import sync_playwright
    
     with sync_playwright() as playwright:
         browser = playwright.chromium.launch(headless=False)
         context = browser.new_context(
             http_credentials={
                 "username": "admin",
                 "password": "admin"
             }
         )
         page = context.new_page()
         page.goto(url="http://the-internet.herokuapp.com/basic_auth")
         context.close()
         browser.close()
    
  3. Using the Authorization HTTP header (however, there are other authentication types):

     import base64
     from playwright.sync_api import sync_playwright
    
     def generate_basic_authentication_header_value(username: str, password: str) -> str:
         token = base64.b64encode("{}:{}".format(username, password).encode("utf-8")).decode("ascii")
         return "Basic {}".format(token)
    
     with sync_playwright() as playwright:
         browser = playwright.chromium.launch(headless=False)
         context = browser.new_context(
             extra_http_headers={
                 "Authorization": generate_basic_authentication_header_value("admin", "admin"),
             }
         )
         page = context.new_page()
         page.goto(url="http://the-internet.herokuapp.com/basic_auth")
         context.close()
         browser.close()
    
Alireza Roshanzamir
  • 1,165
  • 6
  • 17