You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

91 lines
2.6 KiB

2 years ago
##
## lib/auth.py
## Provides functions for Calnet authentication over
## Selenium, including cookies export.
##
## Copyright (c) 2022 Kevin Mo
##
import pickle
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
COOKIES_NAME = "cookies.pkl"
def save_cookies(driver):
"""
Save cookies given a Selenium driver.
"""
pickle.dump(driver.get_cookies(), open(COOKIES_NAME, "wb"))
return True
def load_cookies(driver):
"""
Load cookies given a Selenium driver.
"""
try:
cookies = pickle.load(open(COOKIES_NAME, "rb"))
for cookie in cookies:
driver.add_cookie(cookie)
except IOError:
pass
return driver
def check_calnet_auth(driver):
"""
Returns whether CalNet authentication is ready.
"""
return "auth.berkeley.edu" in driver.current_url
def perform_calnet_auth(driver, cid, pwd):
"""
Perform authentication with CalNet, given
that driver is at auth.berkeley.edu.
"""
print("Performing Calnet authentication")
print("Current URL:", driver.current_url)
if not check_calnet_auth(driver):
raise Exception("Cannot perform authentication at current state.")
# Target user input and then submit
cid_box = driver.find_element_by_id("username")
pwd_box = driver.find_element_by_id("password")
submit_box = driver.find_element_by_id("submit")
cid_box.send_keys(cid)
pwd_box.send_keys(pwd)
submit_box.click()
# Handle incorrect login attempt
if "auth.berkeley.edu" in driver.current_url:
print("Incorrect login attempt detected.")
raise Exception("Incorrect CalNet credentials")
# Check the presence of Duo 2FA
try:
if "duosecurity.com" not in driver.current_url:
return True
print()
print("IMPORTANT: Complete the 2FA process on the automated browser.")
print("Complete the process through push notification, security key, etc.")
print()
# Stall for success or trust box
wait = WebDriverWait(driver, 30)
trust_box = wait.until(EC.element_to_be_clickable((By.ID, "trust-browser-button")))
print("Detected trust browser button, clicking...")
trust_box.click()
wait = WebDriverWait(driver, 10)
if not wait.until(EC.url_contains("duosecurity.com")):
raise Exception("2FA did not complete successfully")
else:
print("Detected redirect, authentication is a success!")
except:
print("Timed out or could not locate Duo 2FA prompt.")