Cycle de vie d'une session
- Leçon 9
- 55 min
- Module 3 : Sessions et intégration à l'application
Leçon 9 sur 19 · Authentification, autorisations et applications multilocatairesCycle de vie d'une session
1. Bases de l'identité et des autorisations
2. Comprendre la connexion et les jetons
3. Sessions et intégration à l'application
4. Contrôler l'accès aux ressources
5. Travail en arrière-plan et administration
6. Valider et documenter la conception
Ce que vous saurez faire
Décidez quand une session de navigateur se termine et testez chaque fin : inactivité, limite absolue, renouvellement refusé, déconnexion et deuxième personne dans le même navigateur. Une session qui se termine trop tard conserve un accès perdu. Une déconnexion incomplète donne les données de la personne précédente à la suivante.
Avant de commencerCe qu’il faut savoir et avoir sous la main
Ce que vous devez savoir
- La session côté serveur, le témoin (cookie)
ticket_sessionet le jeton CSRF, vus dans Choix de session dans le navigateur. - Les jetons de renouvellement : de nouveaux jetons sans nouvelle connexion, vus dans Flux d’application.
Ce qu’il vous faut sur votre ordinateur
- Le projet après Choix de session dans le navigateur :
python -m pytestaffiche193 passed(193 tests réussis). - Le fournisseur d’exercice (
python -m idp) et l’API (fastapi dev) en cours d’exécution, chacun dans son terminal. - Un troisième terminal dans le dossier du projet, avec l’environnement virtuel actif, pour curl et
psql.
Testé sur macOS (Apple silicon) avec Chromium 156; les commandes Windows sont écrites, mais non testées. Certaines étapes modifient les heures dans la table sessions à la main pour éviter d’attendre 30 minutes ou 8 heures. Ces étapes sont indiquées comme construites.
Un ordinateur partagé à la bibliothèque
Section intitulée « Un ordinateur partagé à la bibliothèque »Une bibliothèque publique met quelques ordinateurs à la disposition de tous. Vous vous asseyez, vous vous connectez à votre courriel et vous lisez un moment. Puis un ami appelle, et vous partez pendant vingt minutes. Certains ordinateurs de la bibliothèque vous déconnectent après une période d’inactivité. Tous déconnectent tout le monde à l’heure de fermeture. Ce sont deux horloges : une pour l’inactivité, une pour la journée entière.
Il y a un troisième piège. Avant de partir, vous fermez votre courriel et cliquez sur « Sign out » (se déconnecter). La personne suivante ouvre le même site de courriel et clique sur « Sign in » (se connecter). Le site ne demande pas de mot de passe : il la connecte à votre compte. Votre logiciel de courriel vous a déconnecté, mais le service de compte derrière lui se souvenait encore de vous. La personne suivante lit maintenant vos courriels.
Ainsi, « déconnecté » a plusieurs sens. Pour terminer complètement une session, vous devez connaître chaque endroit qui se souvient de vous.
Le problème : une session qui se termine trop tard, ou pas complètement
Section intitulée « Le problème : une session qui se termine trop tard, ou pas complètement »Les sessions de l’API de billets de soutien de la dernière leçon durent jusqu’à 8 heures. Trois questions montrent le problème.
- Sam laisse le centre de soutien ouvert et rentre chez lui à midi. Le témoin fonctionne jusqu’au soir. Toute personne au bureau de Sam peut l’utiliser.
- Larkfield désactive le compte d’Omar chez le fournisseur d’identité. L’API conserve sa propre session pour Omar. Combien de temps le navigateur ouvert d’Omar continue-t-il de fonctionner?
- Sam se déconnecte, et Ines s’assoit au même bureau. Elle clique sur « Sign in ». Pour qui l’API la prend-elle?
La troisième question a une réponse mesurée, et c’est la mauvaise. L’auteur a connecté Sam, terminé sa session uniquement dans l’API, puis s’est connecté « comme Ines » dans le même navigateur. Le fournisseur n’a affiché aucune page, et /v1/me a répondu "user_id": "usr-sam". La même chose s’est produite dans Chromium :

Cette leçon donne à chaque question une réponse que le code applique et qu’un test prouve.
L’idée : trois horloges et quatre fins
Section intitulée « L’idée : trois horloges et quatre fins »Une session a besoin de trois horloges. Chacune répond à un risque différent.
- Délai d’inactivité : la session se termine après une période sans requête. C’est la règle d’inactivité de la bibliothèque. Elle protège l’onglet oublié. Le projet utilise 30 minutes (
SESSION_IDLE_MINUTES). - Délai absolu : la session se termine à un moment fixe après la connexion, quoi qu’il arrive. C’est l’heure de fermeture. Il impose une nouvelle connexion chaque jour de travail. Le projet utilise 8 heures (
SESSION_MAX_HOURS). - Durée d’accès : le jeton d’accès dans la session dure 10 minutes. Ensuite, l’API interroge de nouveau le fournisseur avec le jeton de renouvellement. Si le fournisseur refuse, la session se termine. Ainsi, une décision du fournisseur atteint l’API en quelques minutes.
Chaque fin inscrit sa raison dans la ligne de la session, dans end_reason : idle_timeout, absolute_timeout, provider_refused, ou logout pour une déconnexion. La prochaine requête avec ce témoin reçoit 401 session_ended (session terminée), avec la raison dans le message. L’API supprime le témoin. Voici toute la vie d’une session :
Description textuelle du diagramme
Commencez à gauche. Une connexion attend d’abord dans login_requests pendant au plus 10 minutes, et son state fonctionne une seule fois. Un retour valide rend la session active. Tant qu’elle est active, chaque requête déplace l’horloge d’inactivité, et un renouvellement prolonge la durée d’accès. Quatre flèches quittent l’état actif, une par raison de fin. Une session terminée ne redevient jamais active : il faut une nouvelle connexion, avec un nouveau témoin.
Un petit exemple : la matinée de Sam
Section intitulée « Un petit exemple : la matinée de Sam »Voici une matinée construite selon les règles du code. Sam se connecte à 9 h. Trois horloges démarrent : accès jusqu’à 9 h 10, fin d’inactivité à 9 h 30, fin absolue à 17 h.
| Heure | Requête de Sam | Ce que fait l’API | Accès jusqu’à | Fin d’inactivité |
|---|---|---|---|---|
| 9 h | se connecte | nouvelle session, témoin défini | 9 h 10 | 9 h 30 |
| 9 h 04 | GET /v1/me |
200; l’horloge d’inactivité se déplace | 9 h 10 | 9 h 34 |
| 9 h 25 | GET /v1/me |
durée d’accès écoulée : renouvellement auprès du fournisseur; 200 | 9 h 35 | 9 h 55 |
| 10 h 10 | GET /v1/me |
45 minutes sans requête : 401 session_ended (idle_timeout) |
— | — |
Description textuelle du diagramme
Lisez les lignes de haut en bas. Entre 9 h 10 et 9 h 25, la durée d’accès est écoulée, mais rien ne se passe. L’API renouvelle seulement quand une requête en a besoin. À 9 h 25, elle renouvelle avant de répondre. La ligne d’inactivité recommence à chaque requête. Sa fin passe donc de 9 h 30 à 9 h 34, puis à 9 h 55. À 10 h 10, la vérification d’inactivité passe en premier, avant tout renouvellement. La session se termine donc sans appel au fournisseur.
Remarquez l’ordre à 10 h 10. L’API vérifie d’abord la fin absolue, puis la fin d’inactivité, et seulement ensuite la durée d’accès. Une session terminée n’atteint jamais le fournisseur.
Larkfield : tester chaque fin
Section intitulée « Larkfield : tester chaque fin »Grace, propriétaire de Larkfield, demande des preuves, pas des promesses : « Montrez-moi chaque façon dont une session se termine. » Les tests le font déjà. Exécutez-les d’abord :
python -m pytest tests/test_sessions.py -vtests/test_sessions.py::test_sign_in_sets_an_httponly_cookie_and_the_api_knows_the_person PASSEDtests/test_sessions.py::test_the_server_keeps_only_a_hash_of_the_cookie_and_an_encrypted_refresh_token PASSEDtests/test_sessions.py::test_a_callback_with_an_unknown_or_used_state_fails PASSEDtests/test_sessions.py::test_return_to_cannot_send_you_to_another_site PASSEDtests/test_sessions.py::test_a_change_with_the_cookie_needs_the_csrf_token PASSEDtests/test_sessions.py::test_logout_ends_the_session_and_revokes_the_refresh_token PASSEDtests/test_sessions.py::test_a_session_ends_when_idle_or_too_old[last_seen_at = now() - interval '31 minutes'-idle_timeout] PASSEDtests/test_sessions.py::test_a_session_ends_when_idle_or_too_old[expires_at = now() - interval '1 second'-absolute_timeout] PASSEDtests/test_sessions.py::test_the_session_asks_the_provider_again_when_the_access_token_is_old PASSEDtests/test_sessions.py::test_a_disabled_account_loses_the_session_at_the_next_refresh PASSEDtests/test_sessions.py::test_account_switching_starts_a_new_session_for_the_other_person PASSEDtests/test_sessions.py::test_the_page_and_the_session_answer_are_not_cached PASSEDLes tests déplacent les heures dans la base de données au lieu d’attendre. Faites maintenant la même chose à la main, avec l’API en cours d’exécution, pour voir chaque réponse.
Exercice guidé
Section intitulée « Exercice guidé »-
Dans le troisième terminal, définissez deux petites fonctions utilitaires.
signinsuit la connexion comme le navigateur, avec le fichier de témoinsjar.txt. Elle ouvre d’abord la page du fournisseur; elle choisit la personne seulement si la page le demande.meappelle/v1/meavec ce fichier :Fenêtre de terminal signin() {TO=$(curl -s -o /dev/null -w '%{redirect_url}' -b jar.txt -c jar.txt "http://127.0.0.1:8000/auth/login?return_to=/app/$2")BACK=$(curl -s -o /dev/null -w '%{redirect_url}' -b jar.txt -c jar.txt "$TO") # open the provider's page# no redirect: the page asks for a person, so pick one[ -z "$BACK" ] && BACK=$(curl -s -o /dev/null -w '%{redirect_url}' -b jar.txt -c jar.txt -d user="$1" "$TO")curl -s -o /dev/null -b jar.txt -c jar.txt "$BACK"curl -s -b jar.txt http://127.0.0.1:8000/auth/session; echo}me() { curl -s -b jar.txt http://127.0.0.1:8000/v1/me; echo; }Fenêtre de terminal function signin($user, $extra = "") {$to = curl.exe -s -o NUL -w '%{redirect_url}' -b jar.txt -c jar.txt "http://127.0.0.1:8000/auth/login?return_to=/app/$extra"$back = curl.exe -s -o NUL -w '%{redirect_url}' -b jar.txt -c jar.txt "$to" # open the provider's page# no redirect: the page asks for a person, so pick oneif (-not $back) { $back = curl.exe -s -o NUL -w '%{redirect_url}' -b jar.txt -c jar.txt -d "user=$user" "$to" }curl.exe -s -o NUL -b jar.txt -c jar.txt "$back"curl.exe -s -b jar.txt http://127.0.0.1:8000/auth/session}function me { curl.exe -s -b jar.txt http://127.0.0.1:8000/v1/me }Commencez avec un navigateur neuf : supprimez
jar.txt(rm -f jar.txt, ouRemove-Item jar.txtdans PowerShell). Puis exécutezsignin usr-sam. La réponse commence par{"signed_in":true,"user_id":"usr-sam". -
Renouvellement (construit). Placez la fin de la durée d’accès de Sam une minute dans le passé, puis appelez l’API :
Fenêtre de terminal docker compose exec db psql -U tickets -c "UPDATE sessions SET access_expires_at = now() - interval '1 minute' WHERE user_id = 'usr-sam' AND ended_at IS NULL;"medocker compose exec db psql -U tickets -c "SELECT user_id, access_expires_at - now() AS access_left FROM sessions WHERE user_id = 'usr-sam' AND ended_at IS NULL;"Fenêtre de terminal docker compose exec db psql -U tickets -c "UPDATE sessions SET access_expires_at = now() - interval '1 minute' WHERE user_id = 'usr-sam' AND ended_at IS NULL;"medocker compose exec db psql -U tickets -c "SELECT user_id, access_expires_at - now() AS access_left FROM sessions WHERE user_id = 'usr-sam' AND ended_at IS NULL;"UPDATE 1{"user_id":"usr-sam","kind":"user","name":"Sam", … }user_id | access_left---------+-----------------usr-sam | 00:09:59.687126(1 row)/v1/mea répondu 200, et la durée d’accès est de nouveau de 10 minutes. L’API a utilisé le jeton de renouvellement auprès du fournisseur avant de répondre. Le fournisseur a aussi remplacé le jeton de renouvellement : la ligne conserve maintenant le nouveau, chiffré. -
Compte désactivé chez le fournisseur. Connectez-vous comme Omar, puis désactivez son compte chez le fournisseur :
Fenêtre de terminal rm -f jar.txtsignin usr-omarpython -m idp disable usr-omarmeFenêtre de terminal Remove-Item jar.txt -ErrorAction SilentlyContinuesignin usr-omarpython -m idp disable usr-omarmeusr-omar is disabled: they cannot sign in or refresh tokens. Tokens already issued stay valid until they expire.{"user_id":"usr-omar", … }Omar reçoit encore 200. La durée d’accès de sa session n’est pas écoulée, donc l’API n’interroge pas encore le fournisseur. Déplacez maintenant sa fin d’accès dans le passé (construit), comme à l’étape 2, et appelez de nouveau :
Fenêtre de terminal docker compose exec db psql -U tickets -c "UPDATE sessions SET access_expires_at = now() - interval '1 second' WHERE user_id = 'usr-omar' AND ended_at IS NULL;"mepython -m idp enable usr-omarFenêtre de terminal docker compose exec db psql -U tickets -c "UPDATE sessions SET access_expires_at = now() - interval '1 second' WHERE user_id = 'usr-omar' AND ended_at IS NULL;"mepython -m idp enable usr-omar{"error":{"code":"session_ended","message":"Your session has ended (provider_refused). Sign in again.", … }}usr-omar is enabled: they can sign in.Le fournisseur a refusé le renouvellement, donc la session s’est terminée. Sans l’étape construite, cela arrive au plus 10 minutes après la désactivation du compte. La durée d’accès limite le maintien d’un accès périmé.
-
Inactivité et limite absolue (construit). Connectez-vous comme Camille, placez sa dernière requête 31 minutes dans le passé, puis appelez :
Fenêtre de terminal rm -f jar.txtsignin usr-camilledocker compose exec db psql -U tickets -c "UPDATE sessions SET last_seen_at = now() - interval '31 minutes' WHERE user_id = 'usr-camille' AND ended_at IS NULL;"meFenêtre de terminal Remove-Item jar.txt -ErrorAction SilentlyContinuesignin usr-camilledocker compose exec db psql -U tickets -c "UPDATE sessions SET last_seen_at = now() - interval '31 minutes' WHERE user_id = 'usr-camille' AND ended_at IS NULL;"me{"error":{"code":"session_ended","message":"Your session has ended (idle_timeout). Sign in again.", … }}Recommencez à partir de
signin usr-camille, avecexpires_at = now() - interval '1 second'plutôt que la modification delast_seen_at. Le message indique(absolute_timeout)(délai absolu). -
Déconnexion et copie de l’ancien témoin. Connectez Sam, gardez une copie du fichier de témoins, puis déconnectez-vous avec le jeton CSRF. Utilisez ensuite la copie :
Fenêtre de terminal rm -f jar.txtsignin usr-samcp jar.txt sams-jar.txtCSRF=$(curl -s -b jar.txt http://127.0.0.1:8000/auth/session | python -c "import sys, json; print(json.load(sys.stdin)['csrf_token'])")curl -s -X POST -b jar.txt -c jar.txt -H "X-CSRF-Token: $CSRF" http://127.0.0.1:8000/auth/logout; echocurl -s -b sams-jar.txt http://127.0.0.1:8000/v1/me; echoFenêtre de terminal Remove-Item jar.txt -ErrorAction SilentlyContinuesignin usr-samCopy-Item jar.txt sams-jar.txt$csrf = (curl.exe -s -b jar.txt http://127.0.0.1:8000/auth/session | ConvertFrom-Json).csrf_tokencurl.exe -s -X POST -b jar.txt -c jar.txt -H "X-CSRF-Token: $csrf" http://127.0.0.1:8000/auth/logoutcurl.exe -s -b sams-jar.txt http://127.0.0.1:8000/v1/me{"signed_out":true,"provider_logout_url":"http://localhost:8400/logout?post_logout_redirect_uri=http%3A%2F%2F127.0.0.1%3A8000%2Fapp%2F"}{"error":{"code":"session_ended","message":"Your session has ended (logout). Sign in again.", … }}Supprimer le témoin dans le navigateur ne suffit pas, et l’API ne compte pas là-dessus. La ligne indique
logout(déconnexion), donc un témoin copié est lui aussi inutilisable. L’API a aussi révoqué le jeton de renouvellement chez le fournisseur.
Comptez les fins dans votre base de données :
docker compose exec db psql -U tickets -c "SELECT end_reason, count(*) FROM sessions GROUP BY 1 ORDER BY 1;"L’exécution des mêmes étapes par l’auteur a donné un absolute_timeout, un idle_timeout, trois logout, un provider_refused et une session encore active (end_reason vide). Vos nombres dépendent du nombre d’essais.
Changement de compte : la connexion que personne n’a vue
Section intitulée « Changement de compte : la connexion que personne n’a vue »L’étape 5 a maintenant une deuxième moitié. Sam s’est déconnecté de l’API. Ines s’assoit et exécute signin usr-ines avec le même fichier de témoins, comme la personne suivante dans le même navigateur :
signin usr-ines{"signed_in":true,"user_id":"usr-sam", … }La réponse indique usr-sam. Le fournisseur a redirigé immédiatement, donc la fonction utilitaire n’a jamais atteint l’étape qui choisit usr-ines. C’est le piège de la bibliothèque, et le diagramme montre pourquoi :
Description textuelle du diagramme
Suivez les deux témoins. ticket_session appartient à l’API, et la déconnexion l’a supprimé. idp_session appartient au fournisseur, sur un autre site, et l’API ne peut pas le supprimer. Quand la connexion suivante atteint le fournisseur, celui-ci voit sa propre session valide pour Sam. Il fait ce que permet l’authentification unique : il le connecte sans poser de question. Les vrais fournisseurs font la même chose.
Il y a deux corrections, et la page à /app/ utilise les deux.
- Se déconnecter termine la session de l’API, puis envoie le navigateur vers
provider_logout_url, fourni dans la réponse. C’est l’adresse de fin de session du fournisseur (déconnexion initiée par la partie utilisatrice, ou RP). Le fournisseur termine sa propre session et renvoie le navigateur à/app/. - Changer de compte termine la session de l’API et commence une nouvelle connexion avec
prompt=select_account. Ce paramètre demande au fournisseur d’afficher sa page même s’il se souvient de quelqu’un. La session de Sam chez le fournisseur peut continuer; c’est son choix sur son appareil.
Essayez la deuxième correction avec la fonction utilitaire. Son deuxième argument ajoute du texte à l’adresse de connexion :
CSRF=$(curl -s -b jar.txt http://127.0.0.1:8000/auth/session | python -c "import sys, json; print(json.load(sys.stdin)['csrf_token'])")curl -s -X POST -b jar.txt -c jar.txt -H "X-CSRF-Token: $CSRF" http://127.0.0.1:8000/auth/logout > /dev/nullsignin usr-ines "&prompt=select_account"{"signed_in":true,"user_id":"usr-ines", … }Le fournisseur a affiché sa page, et le choix lui est parvenu. Dans l’essai Chromium de l’auteur, Switch account (changer de compte) a fait la même chose. La page affichait Signed in as usr-ines (connecté comme usr-ines), sans aucune donnée de Sam. Après Sign out (se déconnecter), la déconnexion du fournisseur a renvoyé le navigateur à /app/, qui indiquait « Not signed in. » (non connecté). Le bouton Back (retour) affichait aussi « Not signed in. ».
Ce que le navigateur conserve de la personne précédente
Section intitulée « Ce que le navigateur conserve de la personne précédente »Le changement de compte ne doit pas laisser les données de Sam sur l’écran d’Ines. Le projet l’empêche à trois endroits :
- La page conserve les données uniquement en mémoire.
clearData()dansapp.htmlles efface à la déconnexion, avant toute autre action. - Chaque réponse authentifiée indique
Cache-Control: no-store:/v1/me,/auth/session,/app/et, à partir du module Contrôler l’accès aux ressources, chaque billet. Le navigateur et tout serveur mandataire ne conservent aucune copie. Le retour et l’historique ne peuvent donc pas montrer les réponses de Sam à Ines. - Chaque connexion reçoit une nouvelle session et un nouveau témoin. L’ancien témoin de Sam reste inutilisable (
401 session_ended), même si quelqu’un l’a conservé.
À vous : une limite d’inactivité d’une minute
Section intitulée « À vous : une limite d’inactivité d’une minute »Jusqu’ici, les fins après inactivité et à la limite absolue étaient construites. Rendez-en une réelle. Arrêtez fastapi dev avec Ctrl+C, puis redémarrez-le avec une limite d’inactivité d’une minute :
SESSION_IDLE_MINUTES=1 fastapi dev$env:SESSION_IDLE_MINUTES = "1"; fastapi devConnectez-vous avec signin usr-grace, appelez me, attendez 70 secondes, puis appelez me de nouveau. Prédisez les deux réponses avant d’exécuter les appels. Puis redémarrez l’API sans ce réglage (dans PowerShell, exécutez d’abord Remove-Item Env:SESSION_IDLE_MINUTES).
Afficher la réponse
Le premier me répond 200 avec les adhésions de Grace et repousse sa fin d’inactivité à une minute plus tard. Après 70 secondes sans requête, le deuxième me répond :
{"error":{"code":"session_ended","message":"Your session has ended (idle_timeout). Sign in again.", … }}La durée d’accès (10 minutes) n’était pas écoulée. La vérification d’inactivité passe en premier, donc l’API n’a pas appelé le fournisseur.
Quand choisir ces limites et quels sont leurs coûts
Section intitulée « Quand choisir ces limites et quels sont leurs coûts »Les trois nombres sont des choix, pas des lois de la nature. Choisissez-les avec les personnes qui utilisent la page.
- Inactivité de 30 minutes convient à un service de soutien, où les gens s’absentent souvent. Une limite plus courte protège mieux les postes partagés. Mais les gens se connectent plus souvent et peuvent trouver un moyen de la contourner.
- Durée absolue de 8 heures correspond à une journée de travail. Elle limite aussi l’utilisation d’un témoin volé : il fonctionne au plus une journée, pas pendant des semaines.
- Durée d’accès de 10 minutes limite l’accès périmé accordé par le fournisseur : un compte désactivé perd son accès en 10 minutes. Une durée plus courte exige plus d’appels au fournisseur; chaque session active renouvelle son accès environ six fois par heure.
Les coûts : une écriture en base de données à chaque requête pour mesurer l’inactivité. Il faut aussi un appel au fournisseur toutes les 10 minutes par session active, et les gens doivent se reconnecter. Les limites du fournisseur comptent aussi : ici, son jeton de renouvellement dure 8 heures. L’API ne peut donc pas renouveler l’accès au-delà de cette durée.
La suppression d’une adhésion n’est pas une décision du fournisseur : Larkfield retire Camille dans sa propre table. À partir du module 4, l’API lit l’adhésion à chaque requête. Camille perd donc son accès à sa prochaine requête. Changements de cycle de vie mesure ce parcours.
Erreur courante
Tout le monde est déconnecté quelques minutes après chaque redémarrage
Symptôme : après un redémarrage de l’API, les gens restent connectés quelques minutes. C’est aussi le cas après un rechargement de fastapi dev déclenché par l’enregistrement d’un fichier. Ensuite, tout le monde reçoit 401 session_ended (provider_refused) (session terminée, refus du fournisseur), même si aucun compte n’a été désactivé. Au démarrage, le journal de l’API affichait SESSION_KEY is not set: sessions end when the API stops (SESSION_KEY n’est pas définie : les sessions se terminent quand l’API s’arrête).
Cause : SESSION_KEY manque dans .env. L’API crée donc une nouvelle clé aléatoire à chaque démarrage. Les jetons de renouvellement dans la table sessions ont été chiffrés avec l’ancienne clé. Les sessions continuent jusqu’à la fin de leur durée d’accès. Ensuite, l’API ne peut pas déchiffrer le jeton de renouvellement. Elle ne peut donc pas renouveler l’accès et termine la session.
Diagnostic : python -m scripts.check_identity, présenté dans la prochaine leçon, affiche PROBLEM SESSION_KEY is set (problème : SESSION_KEY est définie). Le message d’aide indique : « Sans cette clé, chaque redémarrage de l’API déconnecte tout le monde. » Dans la base de données, les sessions terminées ont end_reason = 'provider_refused' dans les 10 minutes suivant le redémarrage.
Correction :
- Vérifiez que
.envcontient une ligneSESSION_KEY=….python -m idp initl’écrit; si vous avez recréé.envplus tard, elle manque. - Exécutez
python -m idp init --forcepour écrire de nouveaux secrets. Cette commande crée aussi une nouvelle clé de signature et de nouveaux secrets client. Redémarrez ensuite le fournisseur et l’API. - Connectez-vous de nouveau. Les sessions survivent maintenant à un redémarrage de l’API.
Sur un serveur, gardez SESSION_KEY dans le coffre de secrets, comme la clé d’API dans L’essentiel de Docker et du nuage pour les développeurs en IA. Si elle est divulguée, changez-la : chaque session se termine alors à son prochain renouvellement. C’est le résultat sûr.
Vérifiez votre compréhension
Pourquoi une session a-t-elle besoin d'un délai d'inactivité et d'une durée absolue? Donnez un cas que chacun détecte, mais pas l'autre.
Afficher la réponse
Le délai d’inactivité détecte une session oubliée. Sam quitte son poste à midi. La session se termine 30 minutes plus tard, même si les 8 heures ne sont pas écoulées. La durée absolue détecte une session qui reste toujours active. Une page qui envoie une requête chaque minute ne déclenche jamais le délai d’inactivité. C’est aussi le cas d’un témoin volé utilisé sans arrêt. La session se termine quand même 8 heures après la connexion. La fin absolue force aussi une nouvelle connexion. Le fournisseur vérifie donc de nouveau la personne et son deuxième facteur.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Prédisez : Larkfield désactive Omar chez le fournisseur 2 minutes après son dernier renouvellement. Il continue de travailler dans son navigateur ouvert. Quand sa session se termine-t-elle, pour quelle raison, et pourquoi pas immédiatement?
Afficher la réponse
Environ 8 minutes plus tard, à sa première requête après la fin de la durée d’accès de 10 minutes. L’API tente alors de renouveler l’accès, mais le fournisseur refuse. La session se termine avec provider_refused (refus du fournisseur) : 401 session_ended (session terminée). Elle ne se termine pas immédiatement, car l’API n’interroge pas le fournisseur à chaque requête. La durée d’accès est la limite convenue pour l’accès périmé. Si 10 minutes est trop long, réduisez cette durée. Ou laissez le fournisseur prévenir l’API immédiatement. Il s’agit d’une déconnexion par canal arrière, non implémentée dans ce cours.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Vérification finale : Sam est connecté à un poste partagé. Montrez, avec des commandes ou dans le navigateur, qu'Ines peut prendre sa place sans voir les données de Sam. Montrez aussi que l'ancienne session de Sam ne peut plus servir.
Afficher la réponse
Utilisez Switch account (changer de compte), ou déconnectez-vous, puis exécutez signin usr-ines "&prompt=select_account". Preuve : le fournisseur affiche sa page, et /auth/session répond "user_id":"usr-ines". La page affiche seulement le résultat de /v1/me pour Ines, car clearData() l’a vidée. Les réponses indiquent Cache-Control: no-store (ne pas stocker). Le bouton de retour n’affiche donc aucune donnée de Sam. Une copie du témoin de Sam reçoit 401 session_ended (logout) (session terminée, déconnexion). Montrez ensuite le problème que cela évite. Après une déconnexion de l’API seulement, sans prompt=select_account, la même commande signin usr-ines répond usr-sam.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Récapitulatif
- Une session a trois compteurs : inactivité (30 minutes), durée absolue (8 h) et durée d’accès (10 minutes, renouvelée avec le jeton de renouvellement).
- Elle peut se terminer de quatre façons, chacune enregistrée dans
sessions.end_reason:logout(déconnexion),idle_timeout(délai d’inactivité),absolute_timeout(durée absolue),provider_refused. La prochaine requête reçoit401 session_endedet perd le témoin. - Un compte désactivé chez le fournisseur perd sa session au prochain renouvellement, donc dans les 10 minutes. Un témoin copié ne fonctionne plus après la déconnexion.
- Se déconnecter de l’API ne déconnecte pas du fournisseur. Sans précaution, le prochain clic sur « Sign in » (se connecter) reconnecte la personne précédente sans avertissement. Corrigez cela avec l’URL de déconnexion du fournisseur et avec
prompt=select_accountpour Switch account. - Aucune donnée de la personne précédente ne reste. La déconnexion vide la mémoire, chaque réponse personnelle contient
Cache-Control: no-store, et chaque connexion reçoit un nouveau témoin.
La prochaine leçon examine l’autre côté de ces redirections. Elle présente ce que le fournisseur doit savoir sur l’API et ce qui change avec un vrai fournisseur.
Leçon suivante : Configuration du fournisseur