Checkpoint Lab — Authentication Flows, Proxies, Certificates, and Enterprise Browser Environments
The checkpoint operates the complete boundary: a synthetic identity enters an application through a constrained local proxy, browser session evidence is redacted, local certificate trust is verified separately, and one routing failure is injected and traced without weakening identity or TLS controls.
Learning objectives
- Predict browser, proxy, AUT, cookie, and evidence-state changes before each action.
- Run a controlled authenticated Selenium flow with isolated synthetic credentials and artifact namespace.
- Inject and classify a proxy failure while preserving first-attempt evidence.
- Verify the local test CA independently and explain the browser trust-store boundary.
- Produce an escalation rationale for identity/network/policy work that Selenium code must not perform.
1. Checkpoint architecture, assumptions, and safety gate
Reuse the Lesson 2 generated fixture. Required: Python 3.10+,
selenium==4.47.0, local Chromium, Selenium Manager, AUT
on 127.0.0.1:8783, proxy on
127.0.0.1:8899, and no public listener. Optional
certificate step requires OpenSSL and HTTPS server port
9443. Grid is not required; if you adapt the lab to
Grid, remember that 127.0.0.1 from a Node refers to the
Node itself and the Node must be able to resolve/reach the
AUT/proxy.
Continue only with the synthetic fixture. Do not substitute a production URL, employee account, real proxy credential, or enterprise MFA endpoint.
2. Prediction sheet before mutation
The following table organizes the key choices and evidence for Prediction sheet before mutation. Use it together with the surrounding prose so the rows serve as a comparison aid rather than standalone rules.
| Action | Predict before running | Independent verification |
|---|---|---|
| broken proxy 8999 | WebDriver session may start; navigation to synthetic AUT fails; no authenticated cookie | requested proxy JSON + exception type + absence of authenticated manifest |
| restored proxy 8899 | proxy marker becomes yes; AUT creates session; browser receives HttpOnly cookie | DOM route/state + redacted cookie metadata + AUT/proxy logs |
| default TLS client to lab HTTPS | private lab CA is rejected | certificate verification exception |
| client trusts ca.crt | same HTTPS endpoint succeeds without disabling verification | HTTP 200/tls-ok using explicit CA |
3. Execute the two-attempt Selenium run
The following example makes the Execute the two-attempt Selenium run behavior concrete. Read it with the stated assumptions, then compare its observable output or state changes with the explanation that follows.
import json, os, time
from pathlib import Path
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.proxy import Proxy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import WebDriverException
BASE = "http://auth.lab.test:8783"
USER = os.environ.get("SEL_LAB_USER", "learner@example.test")
PASSWORD = os.environ.get("SEL_LAB_PASSWORD", "LabOnly-2026!")
RUN = Path("evidence") / time.strftime("%Y%m%dT%H%M%S")
RUN.mkdir(parents=True, exist_ok=False)
def make_options(proxy_port: int):
p = Proxy({"proxyType":"manual", "httpProxy":f"127.0.0.1:{proxy_port}", "sslProxy":f"127.0.0.1:{proxy_port}"})
o = webdriver.ChromeOptions(); o.proxy = p
o.add_argument("--proxy-bypass-list=<-loopback>"); o.add_argument("--headless=new")
return o
def safe_caps(driver):
c = dict(driver.capabilities)
return {k:c.get(k) for k in ("browserName","browserVersion","platformName","acceptInsecureCerts","proxy")}
def run_login(proxy_port: int, label: str):
attempt = RUN / label; attempt.mkdir()
options = make_options(proxy_port)
(attempt / "requested.json").write_text(json.dumps(options.to_capabilities().get("proxy"), indent=2))
driver = webdriver.Chrome(options=options)
try:
manifest = {"session_id":driver.session_id, "capabilities":safe_caps(driver)}
try:
driver.get(BASE + "/login")
manifest["route"] = driver.find_element(By.ID, "route").text
driver.find_element(By.ID, "email").send_keys(USER)
driver.find_element(By.ID, "password").send_keys(PASSWORD)
driver.find_element(By.ID, "sign-in").click()
WebDriverWait(driver, 5).until(EC.text_to_be_present_in_element((By.ID,"state"),"authenticated"))
cookie = driver.get_cookie("lab_session")
manifest["cookie"] = {k:cookie.get(k) for k in ("name","domain","path","httpOnly","secure","sameSite")}
manifest["url"] = driver.current_url
driver.save_screenshot(str(attempt / "authenticated.png"))
manifest["outcome"] = "authenticated"
except WebDriverException as exc:
manifest["outcome"] = "browser-network-failure"
manifest["exception_type"] = type(exc).__name__
# Do not persist exception text if it could contain URLs/credentials in a real environment.
(attempt / "manifest.json").write_text(json.dumps(manifest, indent=2), encoding="utf-8")
return manifest["outcome"]
finally:
driver.quit()
print("broken prediction: browser session exists, navigation fails through port 8999")
print("broken actual:", run_login(8999, "01-broken-proxy"))
print("restored prediction: proxy=yes, authenticated cookie metadata, screenshot")
print("restored actual:", run_login(8899, "02-restored-proxy"))
The two attempts get separate evidence directories, so the successful restoration cannot overwrite the original failure. The manifest intentionally stores exception type, not arbitrary exception text, and cookie metadata without its value. In a controlled internal system you may retain more network evidence only after a privacy/security review.
4. Verify certificate trust as a separate boundary
Start the Lesson 2 HTTPS fixture. First run a default Python TLS client and expect certificate verification to fail because the private lab CA is not trusted. Then run the explicit-CA verifier:
from pathlib import Path
import ssl, urllib.request
lab = Path("selenium-auth-lab/tls")
trusted = ssl.create_default_context(cafile=str(lab / "ca.crt"))
with urllib.request.urlopen("https://127.0.0.1:9443/health", context=trusted, timeout=3) as response:
print(response.status, response.read().decode())
Expected trusted result: 200 tls-ok. The endpoint,
certificate, and server did not change; only the client trust input
changed. This is the causal distinction the evidence packet should
capture.
If your browser lab also imports ca.crt into a
disposable test profile using approved platform tooling, record the
profile/trust setup as infrastructure evidence. Remove that profile
in cleanup. Do not edit the user’s normal browser trust store as a
training shortcut.
5. Diagnostic conclusions for the injected failure
Broken proxy: browser session creation succeeds, but navigation fails before application DOM state exists. Requested capabilities point to port 8999. Root cause: browser/network routing configuration, not locator, wait, credentials, TLS, or AUT assertion.
Restored proxy: route DOM reports
proxy=yes, authenticated DOM is reached, and an
HttpOnly session-cookie record exists without persisting its value.
Root cause correction: restore the intended local proxy endpoint.
TLS trust experiment: default client rejects the private issuer and the explicit lab-CA client succeeds. Root cause classification is trust-store input, not Selenium availability.
6. What must be escalated instead of “fixed in Selenium”
The following table organizes the key choices and evidence for What must be escalated instead of “fixed in Selenium”. Use it together with the surrounding prose so the rows serve as a comparison aid rather than standalone rules.
| Situation | Owner / coordination | Why Selenium should not bypass it |
|---|---|---|
| Production MFA or conditional access | Identity/security team | factor and risk policy are security controls |
| Corporate proxy auth/PAC outage | Network/proxy team | routing/auth policy exists outside WebDriver semantics |
| Internal CA rotation or trust deployment | PKI/endpoint/platform team | browser trust roots are managed infrastructure |
| Managed browser policy blocks setting | Endpoint/browser administration | policy intentionally controls browser behavior |
| Real account lockout/privilege issue | Identity/application owner | authorization and account lifecycle require governance |
| Grid Node cannot reach internal AUT | Grid/network platform owner | browser executes from Node network, not test-runner localhost |
7. Evidence packet and verification checklist
- Two immutable attempt directories with requested proxy configuration.
- Session ID and redacted returned capabilities for each created session.
- Broken attempt classified as browser/network failure without a login screenshot containing a password.
-
Restored attempt records
proxy=yes, authenticated URL, browser/version, and cookie metadata only. - Authenticated screenshot contains no credential field.
- Default-versus-explicit-CA TLS result documented.
- No real credential, cookie value, Authorization header, proxy password, or production URL in artifacts.
- Short runbook names the team that owns each non-Selenium enterprise boundary.
8. Cleanup and rollback
The following example makes the Cleanup and rollback behavior concrete. Read it with the stated assumptions, then compare its observable output or state changes with the explanation that follows.
# Stop auth_server.py, proxy_server.py, and tls_server.py with Ctrl+C.
# Remove only this disposable lab and its generated evidence.
rm -rf selenium-auth-lab evidence
# Windows PowerShell equivalent:
# Remove-Item -Recurse -Force selenium-auth-lab, evidence
If you imported the lab CA into a disposable browser profile, delete that profile/trust database as part of cleanup. If anything was accidentally installed into a shared OS/browser trust store, remove it using the approved platform administration process and verify that the lab CA is gone.
Knowledge checks
Answer from the operating model, then reveal the explanation.
Why does the checkpoint create a browser session even for the broken proxy attempt?
It isolates the failure: session creation can succeed while subsequent browser navigation fails at the proxy/network layer.
Why must the successful attempt use a different evidence directory?
A successful rerun must not overwrite first-failure evidence; otherwise operators lose the causal record.
The TLS server works only when the client explicitly trusts ca.crt. Is acceptInsecureCerts required?
No. Explicit CA trust proves the intended issuer while preserving verification; accepting insecure certificates is a different, weaker session semantic.
A company policy blocks your temporary proxy option. Should the checkpoint add an “ignore policy” browser flag?
No. Managed policy is an enterprise boundary. Record the policy conflict and coordinate an approved test configuration with the browser/endpoint owner.
What is the production operating-model addition from Chapter 23?
Identity, proxy, TLS, browser policy, and authenticated session state become explicit, separately owned, privacy-aware inputs/evidence rather than hidden Selenium helper behavior.
Summary and next bridge
- Authorized authentication uses synthetic/test identities and preserves MFA/SSO controls.
- Proxy routing, TLS trust, browser policy, WebDriver session, and application session remain separate layers.
- Evidence is redacted and immutable across failure/restoration attempts.
- Enterprise identity/network changes require named owners rather than Selenium bypasses.
Chapter 24 builds directly on this boundary model to cover security, privacy, test accounts, and safe automation governance across the whole browser-testing platform.
Primary references and version notes
- Selenium downloads — stable client/Grid version baseline.
- Selenium Python Proxy API — MANUAL, PAC, AUTODETECT, SYSTEM, DIRECT and proxy fields.
- Selenium Python BaseOptions API — proxy and acceptInsecureCerts session configuration.
- Selenium cookie interactions — session-visible cookie operations.
The mandatory examples pin selenium==4.47.0 and
Python 3.10+. Selenium Manager remains the normal local
driver-resolution path. Browser/enterprise policy and trust-store
procedures are platform-managed state and are intentionally not
hidden inside Selenium helpers.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.