Storage Access API pour le contenu intégré
Comment un document intégré demande l’accès aux cookies non partitionnés, ce qu’impliquent la médiation de l’utilisateur et la prise en charge, et comment prévoir un repli.
Vous voulez la documentation structurée pour Identité ?
Cet article fait partie de la bibliothèque éditoriale. Pour les étapes de configuration, la référence et les mises à jour continues, passez directement à la section docs.
La Storage Access API permet à un document intégré de demander au navigateur l’accès à ses cookies non partitionnés, et dans certains navigateurs à d’autres données de stockage, dans un contexte où cet accès est autrement bloqué ou partitionné. Le document intégré vérifie son état actuel avec document.hasStorageAccess() et fait sa demande avec document.requestStorageAccess(). C’est le navigateur, et non la page, qui décide du résultat, en général après un geste de l’utilisateur et parfois après une invite. Une autorisation est une exception limitée à un document intégré sous un site de premier niveau, et la page a besoin d’un parcours défini pour les résultats refusés et non pris en charge.
Ce que décide la Storage Access API
De nombreux navigateurs séparent ou bloquent l’état auquel un document intégré tiers peut accéder. Un widget de connexion, un formulaire de paiement, un service de commentaires ou un chat d’assistance peuvent constater que les cookies définis lorsque l’utilisateur a visité leur propre site ne sont pas envoyés depuis la page d’un autre site. La Storage Access API est le moyen normalisé pour un tel document de demander si cet état peut de nouveau être mis à sa disposition. L’aperçu de la Storage Access API sur MDN et le projet de spécification du PrivacyCG décrivent ce modèle.
Le mot à retenir est demande. Le document intégré demande ; il ne configure pas. Le navigateur applique ses propres règles pour savoir si la demande est autorisée, s’il faut interroger l’utilisateur et quelle interaction préalable l’utilisateur a eue avec le site intégré. Ces règles diffèrent selon le navigateur et la version, et elles peuvent changer d’une publication à l’autre. Une page peut décrire ce qu’elle demande, mais elle ne peut pas promettre ce que l’utilisateur verra.
La médiation de l’utilisateur explique la forme de cette API. Une personne qui navigue sur un site intégrant un service tiers n’a pas forcément choisi de partager avec ce site l’état enregistré de ce service. Le navigateur pose donc la question, soit par une invite qui nomme le site intégré et la page où il apparaît, soit par ses propres règles sur l’interaction préalable. Ce que l’autorisation enregistre, c’est le choix de l’utilisateur, non la préférence de la page.
La portée compte autant que la décision. Une demande acceptée s’applique à ce document intégré et au contexte de premier niveau dans lequel il est intégré. Elle ne change pas ce que d’autres cadres peuvent lire, elle ne se transmet pas à un autre site de premier niveau, et elle ne dit rien des autres API de stockage ni de l’identité de la personne. Les cookies sont le sujet central de l’API. L’inclusion d’autres types de stockage dépend du navigateur et de la version ; consultez donc la documentation du navigateur que vous testez.
Les clés de partition, c’est-à-dire le mécanisme par lequel les navigateurs séparent l’état par site de premier niveau, sont traitées dans Partitionnement du stockage du navigateur et confidentialité. La Storage Access API s’appuie sur cette frontière comme une exception et ne la remplace pas. Pour la question plus large du mécanisme de stockage adapté à chaque donnée, voir Cookies, localStorage et IndexedDB : où ranger chaque état.
L’API ne sert pas non plus à en apprendre davantage sur une personne ni à relier des sessions entre sites. Elle existe pour qu’un service intégré légitime, comme un widget de connexion ou de paiement avec lequel l’utilisateur a choisi d’interagir, continue de fonctionner lorsque le navigateur limite l’état tiers. Un document qui demande l’accès sans raison claire pour l’utilisateur ne lui donne aucune base pour décider et ne sert pas la personne qui utilise la page.
Vérifier l’état et demander l’accès
document.hasStorageAccess() renvoie une promesse qui se résout en booléen pour le document courant. Elle lit l’état actuel et ne demande rien ; elle peut donc s’exécuter au chargement sans geste de l’utilisateur. Un résultat true signifie que le document a actuellement accès à ses cookies non partitionnés. Cela peut venir d’une autorisation accordée plus tôt, du fait que le document n’est pas intégré, ou du fait que le navigateur ne restreint pas les cookies tiers dans cette configuration ; une valeur true seule ne prouve donc pas qu’une autorisation a été accordée.
document.requestStorageAccess() est la demande elle-même. Elle renvoie aussi une promesse, qui se résout lorsque l’accès est accordé et qui est rejetée dans le cas contraire. Elle exige une activation transitoire de l’utilisateur, comme un clic ou une pression de touche dans le document intégré ; l’appeler depuis un minuteur ou au chargement doit donc normalement être rejeté, sauf si l’autorisation a déjà été accordée auparavant, auquel cas certains navigateurs la résolvent sans geste. L’appel peut aussi être rejeté lorsque l’utilisateur refuse une invite, lorsque les règles du navigateur indiquent que la demande n’est pas autorisée, ou lorsqu’un refus précédent est mémorisé. Traitez le rejet comme un résultat normal, et non comme une exception à masquer. La référence de requestStorageAccess() énumère les conditions.
Une courte séquence convient à la plupart des widgets intégrés. Au chargement, détectez la présence des méthodes et appelez hasStorageAccess(). Si le résultat est true, poursuivez avec le parcours normal d’un utilisateur connecté. S’il est false, affichez un contrôle qui explique ce dont le widget a besoin, et n’appelez requestStorageAccess() que depuis le gestionnaire de clic de ce contrôle. Une fois la promesse résolue, rechargez ou redemandez l’état qui dépend des cookies, puis confirmez avec hasStorageAccess() avant d’afficher le contenu d’un utilisateur connecté.
async function showAccountState(button) {
if (!('hasStorageAccess' in document)) return renderSignedOut('unsupported');
if (await document.hasStorageAccess()) return renderSignedIn();
button.hidden = false;
button.addEventListener('click', async () => {
try {
await document.requestStorageAccess();
return (await document.hasStorageAccess()) ? renderSignedIn() : renderSignedOut('denied');
} catch {
return renderSignedOut('denied');
}
});
}
Appelez de nouveau hasStorageAccess() lors des visites suivantes plutôt que de supposer qu’une autorisation antérieure tient toujours. Les navigateurs mémorisent ou font expirer les décisions selon leur propre calendrier, l’utilisateur peut réinitialiser les autorisations du site, et un profil peut être effacé. Un document qui vérifie son état à chaque chargement part de la réponse actuelle du navigateur et ne traîne pas une hypothèse périmée d’une visite à l’autre. Le guide d’utilisation de la Storage Access API présente le même schéma plus en détail.
Plusieurs conditions au niveau de la page s’appliquent aussi. Le document intégré a besoin d’un contexte sécurisé. Si le cadre est placé en sandbox, la page qui l’intègre doit autoriser le jeton de sandbox d’accès au stockage (allow-storage-access-by-user-activation) en plus des jetons dont le script a besoin, comme allow-scripts et allow-same-origin. Une Permissions Policy peut aussi restreindre la fonctionnalité storage-access pour un cadre. Lorsqu’une demande est rejetée immédiatement, examinez les attributs du cadre et la politique de la page qui l’intègre avant de supposer qu’un utilisateur a pris une décision.
Lorsque le navigateur la prend en charge, la Permissions API signale une autorisation storage-access comme accordée ou à demander ; la spécification ne révèle pas d’état refusé, si bien qu’une demande déclinée apparaît comme à demander. Elle permet de lire l’état avant de demander, pas de le modifier. La prise en charge de cette requête varie selon le navigateur ; traitez-la donc comme un signal facultatif et gardez hasStorageAccess() comme l’état sur lequel vous agissez.
Une autorisation ne réécrit pas les règles des cookies. Un cookie destiné à circuler dans un contexte inter-sites a besoin de SameSite=None et de Secure dans les navigateurs qui appliquent les règles SameSite à la requête, et l’examen doit consigner les attributs qu’il observe. Si le widget semble toujours déconnecté alors que hasStorageAccess() renvoie true, vérifiez les attributs du cookie et l’origine de la requête avant de soupçonner l’API.
Différences entre navigateurs et prise en charge
Le comportement des navigateurs est la partie de ce sujet qui change le plus. Les navigateurs basés sur Chromium, Firefox et Safari proposent l’API, mais ils diffèrent sur le moment où une invite apparaît, sur l’importance d’une interaction préalable avec le site intégré en tant que page de premier niveau, sur la durée de mémorisation d’une décision et sur le stockage que couvre l’autorisation. Certains navigateurs appliquent aussi leurs propres heuristiques ou relations entre sites, qui peuvent accorder ou refuser l’accès sans invite visible. Ce sont des décisions du navigateur, et un script de page ne peut pas les forcer.
Considérez la prise en charge comme une donnée à mesurer par navigateur et par version. Une détection de fonctionnalité comme 'requestStorageAccess' in document vous apprend que la méthode existe. Elle ne vous dit pas si l’appel affichera une invite, se résoudra silencieusement ou sera rejeté. Consultez les tableaux de compatibilité de MDN et les conseils des éditeurs, comme le guide de Chrome sur la Storage Access API, et consignez la version testée, car la même page peut se comporter autrement après une mise à jour du navigateur.
Les navigateurs diffèrent aussi par leur posture par défaut envers les cookies tiers. Certains les bloquent ou les partitionnent par défaut, d’autres laissent le choix à l’utilisateur, et une politique d’entreprise peut encore modifier le résultat. Dans un navigateur qui ne restreint pas les cookies tiers, hasStorageAccess() peut renvoyer true sans aucune demande. Dans un navigateur qui les restreint, la même page a besoin de la demande. Le résultat d’un test dans une configuration ne décrit pas l’autre, et c’est pourquoi le compte rendu d’examen nomme le navigateur et ses réglages.
Le site intégré et le site de premier niveau font tous deux partie de la décision. L’utilisateur peut voir une invite qui nomme les deux, et une autorisation pour un couple de sites ne dit rien d’un autre couple. Si le même widget apparaît sur plusieurs sites que vous exploitez, prévoyez de tester et d’expliquer chaque couple, et attendez-vous à ce que les utilisateurs voient la demande plus d’une fois.
Ne voyez pas dans une autorisation réussie la preuve que le stockage tiers est non partitionné en général. L’autorisation est une exception pour un document intégré, créée parce qu’un utilisateur a accompli une action délibérée avec un service qu’il a choisi d’utiliser. Pour les autres cadres, les autres sites et les visites ultérieures, ce sont toujours les règles de partitionnement du navigateur qui s’appliquent. Si une fonctionnalité ne marche lors d’un test que parce qu’une autorisation a été accordée, la conception dépend d’une exception, et le produit doit énoncer cette dépendance dans sa propre documentation.
Concevoir les cas refusés et non pris en charge
Trois résultats exigent un parcours conçu : accordé, refusé et non pris en charge. Accordé poursuit avec l’état normal d’un utilisateur connecté. Refusé signifie que l’utilisateur a décliné, que le navigateur a rejeté l’appel, ou qu’un refus précédent a été mémorisé. Non pris en charge signifie que les méthodes sont absentes ou que le navigateur traite la fonctionnalité autrement. Chacun des deux derniers a besoin d’un état visible et fonctionnel, pas d’un cadre vide ni d’une bannière d’erreur.
La solution de repli la plus fiable est un parcours de première partie. Le widget intégré affiche une vue déconnectée avec une action claire qui ouvre le service dans sa propre fenêtre ou son propre onglet, où le navigateur applique les règles de première partie. Après la connexion, l’utilisateur revient à la page qui intègre le widget, et celui-ci utilise un état qui ne dépend pas d’un cookie tiers, par exemple une valeur de courte durée transmise par un message que le destinataire vérifie par rapport à l’origine attendue.
Gardez l’état déconnecté utile. Le contenu public doit s’afficher, les brouillons saisis par l’utilisateur doivent être conservés, et l’interface doit dire en termes simples ce qui manque : le service a besoin d’une autorisation pour utiliser sa connexion enregistrée dans cette page, et l’utilisateur peut continuer sans elle. Ne demandez pas de façon répétée. Après un refus, proposez l’action de première partie et laissez l’utilisateur choisir quand réessayer, car un appel répété peut de toute façon être rejeté sans invite.
Rédigez l’explication avant le clic, non après la réponse du navigateur. Le texte placé près du contrôle doit dire ce que le service intégré pourra utiliser, que le navigateur demandera confirmation avec ses propres mots, et ce que l’utilisateur peut encore faire s’il refuse. Restez bref, et évitez toute formulation qui présente l’invite du navigateur comme quelque chose que l’utilisateur doit accepter.
Ne construisez pas votre solution autour d’une invite. Une page ne peut ni répondre à une invite du navigateur, ni la masquer, ni la supprimer, et elle ne doit pas chercher à en déclencher une hors d’une action réelle de l’utilisateur. Ne présentez pas l’invite aux utilisateurs comme indispensable au fonctionnement du service lorsqu’un parcours de première partie existe. Le libellé et le moment de l’invite relèvent du navigateur. La part de la page est l’explication affichée avant le clic, qui doit dire ce que le service intégré pourra lire et pourquoi.
Utilisez la détection de fonctionnalités et la gestion des échecs plutôt que des tests sur le user agent. Bifurquez selon l’existence des méthodes et selon le résultat de la promesse, non selon un nom ou une chaîne de version de navigateur, afin qu’une mise à jour qui ajoute ou modifie la prise en charge n’exige pas de changement de code. Consignez pour votre propre diagnostic la catégorie du résultat, comme accordé, refusé, non pris en charge ou rejeté sans geste, et gardez ce journal exempt de valeurs de cookies et d’identifiants de compte.
Examiner un widget intégré dont vous êtes propriétaire
Testez l’API avec un widget qui vous appartient, intégré dans un site de premier niveau de test qui vous appartient aussi, afin de maîtriser les deux origines et les cookies. Utilisez deux domaines enregistrables distincts, ou deux noms d’hôte locaux que le navigateur traite comme des sites séparés, pour que le cadre soit réellement inter-sites. Une page de test sur un sous-domaine qui intègre un autre sous-domaine du même domaine enregistrable relève du même site et n’exerce pas la restriction.
Consignez les conditions de chaque exécution plutôt que de supposer une parité entre navigateurs : le nom et la version du navigateur, le site de premier niveau, l’origine intégrée, les attributs SameSite et Secure du cookie testé, si l’iframe est en sandbox ou porte un attribut allow, si un geste de l’utilisateur a précédé l’appel, le résultat observé de hasStorageAccess(), le résultat de l’appel et, lorsqu’il est disponible, l’état de l’autorisation. Deux exécutions aux comptes rendus différents sont des expériences différentes.
Partez à chaque exécution d’un état de cookies connu. La gestion des cookies décrit comment les cookies sont préchargés pour une session de navigateur, et l’isolation multi-comptes dans le navigateur décrit comment garder les contextes séparés. Un état de départ propre compte ici, car un cookie laissé par une exécution précédente peut faire passer un parcours refusé pour un parcours accordé.
BotBrowser prend en charge --bot-cookies, qui injecte des cookies au lancement ou par BrowserContext, de sorte que chaque contexte de test peut partir de son propre état de cookies documenté pendant l’examen d’un parcours intégré dont vous êtes propriétaire. BotBrowser n’accorde ni ne refuse les demandes de la Storage Access API, ne répond pas aux invites d’autorisation du navigateur ni ne les supprime, et il ne change pas les documents intégrés que le navigateur autorise à utiliser un stockage non partitionné ; ces résultats restent du ressort du navigateur et de l’utilisateur.
Exécutez le cas accordé avec un vrai geste de l’utilisateur et une vraie décision dans le navigateur testé. Si l’invite ne peut pas recevoir de réponse dans une exécution automatisée, réalisez ce cas à la main et consignez-le comme résultat manuel. Ne remplacez pas une autorisation par un cookie injecté, car cela testerait l’écran de l’utilisateur connecté et ne dirait rien de la demande.
Interprétez chaque résultat de façon étroite. Une exécution accordée montre que cette version du navigateur a autorisé cette origine intégrée sous ce site de premier niveau après ce geste. Elle ne montre ni le comportement d’un autre navigateur, ni que d’autres cadres peuvent lire le cookie, ni que le stockage tiers est ouvert en général.
Répétez la matrice après une version majeure du navigateur, un changement des attributs de vos cookies, un changement des attributs ou des politiques de cadre de la page qui intègre le widget, et un changement du parcours de connexion du widget. Le compte rendu de la dernière exécution acceptée sert de référence, et une différence de comportement du navigateur est un constat à lire, non un échec à masquer derrière une nouvelle tentative.
Exécuter les vérifications d’accès au stockage
Exécutez ces vérifications sur un widget intégré dont vous êtes propriétaire, dans chaque navigateur et chaque version que vous prenez en charge, et consignez une réussite ou un échec pour chacune.
- État et demande. Réussite si la page appelle
hasStorageAccess()au chargement sans invite, n’appellerequestStorageAccess()que depuis un gestionnaire de clic, et si le compte rendu montre les deux résultats séparément. Échec si la demande s’exécute au chargement ou si les deux résultats sont confondus. - Geste et rejet. En partant d’un état sans autorisation antérieure, appelez la demande une fois sans geste de l’utilisateur et une fois avec un geste. Réussite si le premier appel est traité comme un rejet avec un état déconnecté visible et si le second rapporte son résultat réel.
- Parcours accordé. Après un résultat accordé, confirmez que
hasStorageAccess()renvoietrueet que le widget affiche son état connecté à l’aide du cookie attendu. Échec si l’état connecté apparaît alors quehasStorageAccess()vautfalse. - Parcours refusé. Refusez l’invite, ou utilisez une configuration où l’appel est rejeté. Réussite si le widget affiche une solution de repli définie de première partie ou déconnectée, conserve le contenu public et les brouillons saisis, et ne redemande pas l’accès de lui-même.
- Parcours non pris en charge. Dans un navigateur ou une configuration où les méthodes sont absentes, réussite si le widget atteint la même solution de repli définie par détection de fonctionnalités et ne bifurque pas selon le nom du navigateur.
- Compte rendu de l’environnement. Réussite si le compte rendu indique le navigateur et la version, le site de premier niveau, l’origine intégrée, les attributs
SameSiteetSecure, les réglages de sandbox et d’allow, ainsi que l’état d’autorisation observé. Échec si un résultat est rapporté sans ces éléments ou supposé valable pour un autre navigateur. - Portée d’une autorisation. Intégrez le même widget sous un second site de premier niveau de test. Réussite si ce site obtient son propre résultat et si l’autorisation du premier n’est pas supposée s’appliquer.
Sources
Articles Connexes
Faites passer BotBrowser de la recherche à la production
Utilisez ces guides pour comprendre le modèle, puis passez à la validation multi-plateforme, aux contextes isolés et au déploiement navigateur prêt pour l'échelle.