Session State Synchronization

Purpose

Session State Synchronization addresses the challenge of maintaining a consistent and authenticated session across two distinct interaction layers with Qualtrics: the automated browser controlled by Selenium and the backend HTTP requests handled by the `requests` library. Since the login flow requires complex UI interactions (including multi-factor authentication and browser trust prompts), it is performed in a Selenium-driven browser. However, subsequent API calls for collaboration management must be made via direct HTTP requests for efficiency and reliability.

This subtopic ensures that session cookies and authentication tokens obtained through Selenium are accurately extracted and transferred to the HTTP request session. Without this synchronization, API requests would lack the necessary credentials, causing failures or unauthorized responses.

Functionality

The core workflow in Session State Synchronization involves:

  1. Automated Login via Selenium:
    The client launches a headless Chrome browser to perform the login steps on Qualtrics’ UI, including typing credentials, handling two-factor authentication, and dealing with browser trust prompts.

  2. Extraction of Cookies from Selenium:
    Once logged in and navigated to the target Qualtrics page, the browser’s cookies (which include authentication tokens like XSRF-TOKEN) are retrieved using Selenium’s get_cookies() method.

  3. Injection of Cookies into the Requests Session:
    These cookies are then set into the requests.Session object’s cookie jar, enabling all future HTTP requests to carry the same authenticated session state established by the Selenium browser.

  4. Provision of Cookies as HTTP Headers:
    Certain API headers, such as x-xsrf-token, are dynamically populated from these cookies to satisfy Qualtrics’ security requirements.

The following snippet illustrates the cookie synchronization step after login completion within the `_selenium_login` method:

cookies = driver.get_cookies()
for cookie in cookies:
    self.session.cookies.set(cookie["name"], cookie["value"])

Additionally, the `cookies` property offers convenient access to the session cookies in dictionary form for other internal uses, such as header generation:

@property
def cookies(self) -> dict[str, str]:
    return requests.utils.dict_from_cookiejar(self.session.cookies)

Relationship

Session State Synchronization is a foundational subtopic underpinning the entire authenticated API interaction layer of the project. It complements:

Together, these subtopics form a tightly integrated module that abstracts away the complexity of session management, allowing higher-level functionalities like adding collaborators or accepting collaboration codes to operate reliably.

Without Session State Synchronization, the client would be unable to maintain authentication continuity, rendering API calls invalid despite successful UI login.


Diagram

sequenceDiagram
    participant User
    participant SeleniumBrowser
    participant CollaborationClient
    participant RequestsSession
    participant QualtricsAPI

    User->>SeleniumBrowser: Input credentials & perform login
    SeleniumBrowser->>SeleniumBrowser: Handle 2FA & Trust prompts
    SeleniumBrowser->>CollaborationClient: Retrieve authentication cookies
    CollaborationClient->>RequestsSession: Inject cookies into session
    CollaborationClient->>QualtricsAPI: Make authenticated API requests with synced cookies and headers
    QualtricsAPI-->>CollaborationClient: Return API responses

This sequence illustrates how user-driven login through Selenium results in cookie extraction and session synchronization, enabling authenticated API calls through the requests session.