Chapter 23Lesson 05~300 minutes

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.

CheckpointProxy failureTLS evidenceRedactionEnterprise runbook

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.

Authorization gate

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?

Why must the successful attempt use a different evidence directory?

The TLS server works only when the client explicitly trusts ca.crt. Is acceptInsecureCerts required?

A company policy blocks your temporary proxy option. Should the checkpoint add an “ignore policy” browser flag?

What is the production operating-model addition from Chapter 23?

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.

Next chapter

Security, Privacy, Test Accounts, and Safe Automation Boundaries: Core Concepts and Mental Model

Continue with Security, Privacy, Test Accounts, and Safe Automation Boundaries: Core Concepts and Mental Model. It builds directly on the state, evidence, and operating assumptions established here, so carry those constraints forward rather than treating the next page as an isolated topic.

Primary references and version notes

Version baseline — August 2026

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this address.