Aller au contenu principal
Leçon 8 sur 14 · Computer Use et Automatisation

Gérer l'authentification et les sessions

Leçon 8 sur 14 Mis à jour le 3 novembre 2026 Développeur
Sur cette page
  1. Le défi de l’authentification
  2. Connexion par formulaire
  3. Réutiliser l’état de session
  4. Gérer l’authentification à deux facteurs (2FA)
  5. Gérer les SSO (Single Sign-On)
  6. Détecter l’état de connexion
  7. Sécurité des identifiants
  8. Points clés à retenir

Leçon réécrite le 3 novembre 2026 d’après le guide Computer use d’OpenAI et la documentation d’authentification de Playwright. L’ancienne version plaçait le mot de passe et le code 2FA dans le prompt envoyé au modèle — y compris via des variables d’environnement, ce qui ne change rien à leur envoi — et confiait la connexion SSO à l’agent. Désormais, c’est votre code qui saisit les secrets, l’état de session est sauvegardé avec storage_state, et la connexion SSO se fait une fois à la main. Sources : Computer use · Playwright, authentification.

Le défi de l’authentification

La majorité des workflows d’automatisation nécessitent d’être connecté à un service. Tant que votre agent reste sur des pages publiques, tout va bien ; dès qu’il doit ouvrir un CRM, un back-office ou une boîte mail, il se heurte à un mur de connexion. Formulaires, 2FA, SSO et sessions persistantes se traitent chacun différemment, mais une règle les gouverne tous : le modèle ne voit jamais un secret.

Connexion par formulaire

La tentation est de dicter la séquence à l’agent, identifiants compris :

# À NE PAS FAIRE : le mot de passe part dans la requête envoyée à l'API
task = """
Connecte-toi au site :
1. Clique sur le champ email et tape : [email protected]
2. Clique sur le champ mot de passe et tape : MonMotDePasse123
3. Clique sur le bouton "Se connecter"
"""

Lire le mot de passe dans une variable d’environnement avant de l’insérer dans le prompt n’y change rien : il quitte toujours votre infrastructure dans la requête, il est conservé avec la réponse — les réponses sont stockées par défaut (leçon 12) — et il peut ressortir dans vos journaux. OpenAI recommande de garder les identifiants hors du texte des pages et des captures. La solution est de laisser votre code remplir le formulaire de connexion avec Playwright, puis de confier la suite à l’agent une fois la session ouverte.

import os

def se_connecter(page, login_url: str):
    """Connexion faite par votre code : le modèle ne voit jamais le mot de passe."""
    page.goto(login_url)
    page.get_by_label("Email").fill(os.environ["APP_EMAIL"])
    page.get_by_label("Mot de passe").fill(os.environ["APP_PASSWORD"])
    page.get_by_role("button", name="Se connecter").click()
    page.wait_for_load_state("networkidle")

Les libellés Email et Mot de passe sont à adapter à votre application. C’est l’un des rares endroits du workflow où un sélecteur se justifie pleinement : une page de connexion change rarement, et l’enjeu de sécurité l’emporte sur la souplesse.

Réutiliser l’état de session

Se reconnecter à chaque exécution coûte du temps et déclenche parfois des alertes de sécurité côté service. Playwright sait sauvegarder l’état d’un contexte — cookies, stockage local, IndexedDB — dans un fichier, puis créer un nouveau contexte à partir de ce fichier.

import os

def save_session(context, filepath="session.json"):
    """Sauvegarde l'état de la session courante."""
    context.storage_state(path=filepath)

def new_context_with_session(browser, filepath="session.json"):
    """Crée un contexte à partir de la session sauvegardée, s'il y en a une."""
    options = {"viewport": {"width": 1280, "height": 720}}
    if os.path.exists(filepath):
        options["storage_state"] = filepath
    return browser.new_context(**options)

Intégré au workflow, cela donne une logique en deux temps : on part de la session sauvegardée, on vérifie qu’elle est encore valide, et on ne repasse par la connexion qu’en cas d’échec. L’état est resauvegardé après la tâche, car beaucoup de services renouvellent leur jeton de session en cours de route.

from playwright.sync_api import sync_playwright

def authenticated_workflow(task: str, login_url: str):
    """Workflow avec réutilisation de la session."""
    pw = sync_playwright().start()
    browser = pw.chromium.launch(headless=True)
    try:
        context = new_context_with_session(browser)
        page = context.new_page()
        page.goto(login_url)

        if is_logged_in(page):
            print("Session restaurée avec succès")
        else:
            se_connecter(page, login_url)  # votre code, pas l'agent
            if not is_logged_in(page):
                raise RuntimeError("Connexion impossible : vérifiez les identifiants ou la 2FA")
        save_session(context)

        result = run_agent(task, page=page)
        save_session(context)  # mettre à jour l'état
        return result
    finally:
        browser.close()
        pw.stop()

Le fichier de session vaut un mot de passe : Playwright prévient qu’il peut contenir des cookies et des en-têtes permettant d’usurper le compte, et déconseille fortement de le versionner, même dans un dépôt privé. Rangez-le avec vos secrets.

Gérer l’authentification à deux facteurs (2FA)

La 2FA pose un défi car elle nécessite souvent une intervention humaine, qu’il s’agisse d’un code SMS ou d’une application authenticator. C’est précisément son but : elle est conçue pour qu’un automate ne puisse pas la franchir seul. Deux approches coexistent selon le facteur utilisé, et le choix du facteur au moment de créer le compte de service détermine si votre workflow pourra tourner sans surveillance.

TOTP automatisé

Si le compte utilise une application TOTP comme Google Authenticator ou Authy, le code affiché n’est qu’une fonction du secret partagé et de l’horloge. Votre code peut donc le générer et le saisir lui-même, sans le montrer au modèle.

import os

import pyotp

def saisir_code_totp(page):
    """Saisit le code TOTP courant : le secret et le code restent dans votre code."""
    totp = pyotp.TOTP(os.environ["TOTP_SECRET"])
    page.get_by_label("Code de vérification").fill(totp.now())
    page.get_by_role("button", name="Vérifier").click()

Mesurez ce que vous faites : stocker le secret TOTP à côté du mot de passe ramène la 2FA à un seul facteur, puisque les deux secrets vivent au même endroit. Réservez cette approche à un compte de service dédié, aux droits limités au strict nécessaire.

Attente manuelle

Les facteurs non automatisables, SMS ou notification push, imposent une pause explicite. L’agent s’arrête, un opérateur valide sur son téléphone, puis la boucle reprend là où elle s’était interrompue. C’est une solution acceptable pour un traitement lancé à la main, beaucoup moins pour un cron nocturne.

def wait_for_2fa(page):
    """Pause l'agent et attend la validation manuelle."""
    print("2FA requise. Validez manuellement, puis appuyez sur Entrée.")
    input("Appuyez sur Entrée pour continuer...")
    # L'agent reprend après la validation

Gérer les SSO (Single Sign-On)

Les connexions SSO (Google, Microsoft, SAML) redirigent vers un fournisseur d’identité externe : l’agent changerait de domaine en cours de route et devrait y saisir des identifiants. Ne lui confiez pas cette étape. Faites la connexion SSO une fois, à la main, dans un navigateur visible piloté par Playwright, puis sauvegardez l’état de session : les exécutions suivantes repartent de cet état.

def connexion_sso_manuelle(login_url: str, filepath="session.json"):
    """Un humain se connecte dans un navigateur visible ; la session est sauvegardée."""
    pw = sync_playwright().start()
    browser = pw.chromium.launch(headless=False)
    context = browser.new_context()
    page = context.new_page()
    page.goto(login_url)
    input("Connectez-vous dans la fenêtre ouverte, puis appuyez sur Entrée...")
    save_session(context, filepath)
    browser.close()
    pw.stop()

Quand la session finit par expirer, le workflow doit s’arrêter et redemander cette connexion humaine. Ajoutez la consigne dans les instructions de l’agent : s’il se retrouve devant la page d’un fournisseur d’identité, il s’arrête et le signale au lieu de tenter quoi que ce soit.

Détecter l’état de connexion

Toute cette mécanique repose sur une question à laquelle il faut savoir répondre de façon fiable : sommes-nous connectés ? Une fonction dédiée croise deux signaux, l’URL courante d’abord, puisqu’une redirection vers /login est sans ambiguïté, puis la présence d’un élément réservé aux utilisateurs authentifiés, typiquement le menu de compte. Le premier test est instantané, le second couvre les applications qui affichent la page de connexion sans changer d’URL.

from playwright.sync_api import TimeoutError as PlaywrightTimeoutError

def is_logged_in(page) -> bool:
    """Vérifie si la session est active."""
    # Vérification par URL
    if "/login" in page.url or "/signin" in page.url:
        return False

    # Vérification par élément DOM
    try:
        page.wait_for_selector("[data-testid=user-menu]", timeout=3000)
        return True
    except PlaywrightTimeoutError:
        return False

Le except vise précisément l’expiration du délai : un except: nu avalerait aussi une interruption clavier ou une vraie erreur de programmation, que vous voulez voir remonter.

Sécurité des identifiants

"Ne stockez jamais de mots de passe dans votre code source, vos prompts ou vos logs."

— Règle de sécurité fondamentale

En pratique, cette règle se décline en quelques habitudes qui ne coûtent presque rien une fois prises. Les identifiants vivent dans des variables d’environnement, alimentées en développement par un fichier .env que vous excluez immédiatement du contrôle de version via .gitignore — cet oubli est une cause classique de fuite de secrets sur les dépôts publics. En production, remplacez ce fichier par un gestionnaire de secrets, Vault ou AWS Secrets Manager, qui délivre les valeurs à la demande et trace les accès. Seul votre code les lit, jamais le modèle. Prévoyez une rotation régulière des mots de passe et des tokens API, de sorte qu’une fuite ancienne n’ouvre plus rien. Enfin, filtrez vos logs pour ne jamais y enregistrer de données sensibles : un agent qui journalise fidèlement chaque frappe recopie aussi ce qu’on lui a fait taper.

Points clés à retenir

  • Le modèle ne voit jamais un secret : votre code saisit mot de passe et code 2FA avec Playwright
  • Sauvegardez l’état de session avec storage_state et traitez ce fichier comme un secret
  • Le TOTP s’automatise côté code, à réserver à un compte de service aux droits limités
  • Faites la connexion SSO une fois à la main, puis réutilisez la session sauvegardée
  • Vérifiez toujours l’état de connexion avant de lancer un workflow