3

Hey Brilliant Stack overflow community,

I encountered an interesting scenarios regarding dealing with alert like pop up user authentication box.

1: website used (a practice website): https://the-internet.herokuapp.com/

2: When I clicked in to Basic Auth, there was a alert like pop up window show up (see below). enter image description here

3: What I tried so far.

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions

chrome_path = '.\chromedriver.exe'
chrome_service = Service(chrome_path)
chrome = webdriver.Chrome(service=chrome_service)
chrome.maximize_window()
chrome.get('https://the-internet.herokuapp.com/')
basic_auth = WebDriverWait(chrome,timeout=30).until(expected_conditions.element_to_be_clickable((By.PARTIAL_LINK_TEXT,'Basic Auth')))
basic_auth.click()

3-1: Treat it as alert (switch_to.alert) & use the send keys to insert user name and pwd. But Got the NoAlertPresentException.

chrome.switch_to.alert.send_keys('user\npass')
# get selenium.common.exceptions.NoAlertPresentException

3-2: Treat it as active element & use send keys. This time no error, but nothing being sent to input box too. And this pop up cannot be an element in my perspective.

chrome.switch_to.active_element.send_keys('user\npass')
# No error msg, but nothing show up in the pop up input field too. 

3-3: Treat it as a new window, but when checking how many windows active (driver.window_handles), there was only one window. So this pop up is not a window neither.

print(len(chrome.window_handles)) # return 1, so the pop up is not a window too

3-4: I stumbled upon this post, but I am not sure I understand what the solution is. Python Selenium Alert Authentication Trouble

I will be great if someone can help me out regarding how to navigate through non web element like this one.

Thank you so much!

=======

Question Update

Thank you so much for the help from @Tyzeron and @Nic Laforge!

I tried both methods mentioned in the post, buy wondering if I am doing it correctly or not?

FYI: The website itself is a practice website, so each time you input username and password then sign in, the website will generate a new basic authentication pop up. Which hard to tell if the methods I tried worked or not.

Method 1: Put Basic Authentication in the URL when using get method.

chrome_path = '.\chromedriver.exe'
chrome_service = Service(chrome_path)
chrome = webdriver.Chrome(service=chrome_service)
chrome.maximize_window()
chrome.get('https://username:pwd123@the-internet.herokuapp.com/basic_auth')

Method 2: Using Selenium Wire (I am not sure if my code is correct)

from seleniumwire import webdriver as wire_driver
import base64

def request_interceptor(req):
# add Authentication Here. 
# VXNlck5hbWU6UHNkMTIz is the base64 encoded str for "UserName:Psd123"
    req.headers['Authorization'] = 'Basic VXNlck5hbWU6UHNkMTIz=='
    print(req.headers)

chrome_path = '.\chromedriver.exe'
chrome_service = Service(chrome_path)
chrome = wire_driver.Chrome(service=chrome_service)
chrome.maximize_window()
chrome.request_interceptor = request_interceptor
chrome.get('https://the-internet.herokuapp.com/basic_auth')

The second method with selenium-wire did not generate an error too but no visible clue on the page indicates the success or not.

In addition, the printed result for req object in the function looks as follow: enter image description here

Now, Both methods did not generate the error nor visible clues to indicate the success of the code. So I am wondering how I can tell it worked or not?

Vae Jiang
  • 337
  • 3
  • 8

1 Answers1

3

The reason you cannot "find" the element

The alert box is not an HTML element. It's not part of the webpage, thus you could not see it in the HTML code. The alert box is part of the browser.

Some context

What you are seeing is an example of the Basic access authentication. As the wiki stated, what usually would happen is that your app/browser automatically provides the username and password via a header field (the Authorization header) in the request. In this case, your browser does not know the username and password yet so it asks for it via the browser's alert box.

My proposed solution

I believe the cleanest and easiest way to authenticate using selenium would be providing the credential during your get method like so:

chrome.get('http://username:password@domain')

In your specific case, it would be http://admin:admin@the-internet.herokuapp.com/basic_auth.

However, as @Nic-Laforge mentioned, this solution is dependent on the fact that the browser supports it. (as of writing the latest Chrome supports it)

The solutions from the other StackOverflow post

Unlike my proposed solution, both of the solutions proposed in the similar StackOverflow post require additional libraries.

The first solution Mr. @Evander proposes is to use a pynput library to simulate keyboard input. This solution requires the user to use a non-headless browser, to have the browser focused, and to not interact with the keyboard during the input.

The second solution is much nicer. As stated above, the Basic access authentication expects your credentials in the Authorization header in the request. What Mr. @Evander did is use the selenium-wire library to intercept selenium's request and add the header with the credentials.

Tyzeron
  • 186
  • 2
  • Your entire answer assume that the browser supports it. Chrome does not support it since 2011: https://bugs.chromium.org/p/chromium/issues/detail?id=82250#c7 – Nic Laforge Jan 02 '22 at 19:56
  • 1
    I tested with the **latest chrome v96** and it works. But you do have the point that the solution is dependent on the fact that the browser supports it and might not work on different browsers. – Tyzeron Jan 02 '22 at 19:59
  • Interesting to say the least! I have removed the downvote. Thanks for confirming you tested it. Might be enough for the OP. – Nic Laforge Jan 02 '22 at 20:04
  • There was a period of time when Chrome removed the support but then added later. But your point is valid and is added to the answer as a limitation of the proposed solution. – Tyzeron Jan 02 '22 at 20:13
  • Hey @Tyzeron, thank you so much for helping me out, and I really appreciate it. I tried the methods you suggested in the post, but still have one remaining question which is in the updated question. I am wondering if you can take a look at it when you available? – Vae Jiang Jan 03 '22 at 14:22
  • @VaeJiang, the herokuapp's `basic_auth` page correct credentials are: **username:** _admin_, **password:** _admin_. So if you used the correct credentials, and you see the `Congratulations` message on selenium browser, you can say your code is correct. – Tyzeron Jan 12 '22 at 08:57
  • @Tyzeron. You are right sir! I didn't noticed the correct username and password; therefore, the authentication didn't pass. Thank you so much! – Vae Jiang Jan 23 '22 at 16:01
  • @Tyzeron which 96v of chrome did you get this to work with? – Luke Hamilton Jul 05 '22 at 16:57
  • This doesn't work in chrome 105, neither with firefox ! – David Muñoz Tord Oct 12 '22 at 15:39