Блокировка сторонних файлов cookie с помощью браузеров, пользовательских настроек и разделения хранилища представляет собой проблему для сайтов и служб, которые полагаются на файлы cookie и другие хранилища во встроенных контекстах для действий пользователя, таких как аутентификация. API доступа к хранилищу (SAA) позволяет этим вариантам использования продолжать работать, максимально ограничивая межсайтовое отслеживание.
Статус реализации
API доступа к хранилищу доступен во всех основных браузерах , но между браузерами существуют небольшие различия в реализации . Эти различия были подчеркнуты в соответствующих разделах этого поста.
Продолжается работа над решением всех оставшихся проблем с блокировкой перед стандартизацией API .
Что такое API доступа к хранилищу?
API доступа к хранилищу — это API JavaScript, который позволяет iframe запрашивать разрешения на доступ к хранилищу, если в противном случае доступ был бы запрещен настройками браузера. Встраивания со вариантами использования, которые зависят от загрузки межсайтовых ресурсов, могут использовать API для запроса разрешения на доступ у пользователя по мере необходимости.
Если запрос на хранение будет удовлетворен, iframe получит доступ к своим неразделенным файлам cookie и хранилищу, которые также доступны, когда пользователи посещают его как сайт верхнего уровня.
API доступа к хранилищу позволяет предоставлять определенные неразделенные файлы cookie и доступ к хранилищу с минимальной нагрузкой для конечного пользователя, в то же время предотвращая общий неразделенный доступ к файлам cookie и хранилищу, который часто используется для отслеживания пользователей.
Варианты использования
Некоторым сторонним встраиваниям требуется доступ к неразделенным файлам cookie или хранилищу, чтобы обеспечить удобство работы пользователя — то, что не будет доступно, если сторонние файлы cookie ограничены и включено разделение хранилища.
Варианты использования включают в себя:
- Встроенные виджеты комментариев, для которых требуются данные сеанса входа в систему.
- Кнопки «Мне нравится» в социальных сетях, для которых требуются данные сеанса входа в систему.
- Встроенные документы, для которых требуются данные сеанса входа в систему.
- Премиум-возможности, предоставляемые при встраивании видео (например, чтобы не показывать рекламу вошедшим в систему пользователям или знать предпочтения пользователя в отношении субтитров или ограничивать определенные типы видео).
- Встроенные платежные системы.
Многие из этих вариантов использования включают сохранение доступа для входа во встроенные iframe.
Когда использовать API доступа к хранилищу вместо других API
API доступа к хранилищу — это одна из альтернатив использованию неразделенных файлов cookie и хранилища, поэтому важно понимать, когда использовать этот API по сравнению с другими. Он предназначен для случаев использования, когда справедливы оба следующих условия:
- Пользователь будет взаимодействовать со встроенным контентом, то есть это не пассивный или скрытый iframe.
- Пользователь посетил встроенный источник в контексте верхнего уровня, то есть когда этот источник не встроен в другой сайт.
Существуют альтернативные API для различных случаев использования:
- Файлы cookie с независимым разделенным состоянием (CHIPS) позволяют разработчикам включать файлы cookie в «разделенное» хранилище с отдельной банкой файлов cookie для каждого сайта верхнего уровня. Например, сторонний виджет веб-чата может использовать установку файла cookie для сохранения информации о сеансе. Информация о сеансе сохраняется для каждого сайта, поэтому к файлу cookie, установленному виджетом, нет необходимости обращаться на других веб-сайтах, где он также встроен. API доступа к хранилищу полезен, когда встроенный сторонний виджет зависит от совместного использования одной и той же информации в разных источниках (например, для сведений о сеансе входа или предпочтений).
- Разделение хранилища — это способ межсайтовых iframe использовать существующие механизмы хранения JavaScript при разделении базового хранилища для каждого сайта. Это предотвращает доступ к встроенному хранилищу на одном веб-сайте с помощью той же вставки на других веб-сайтах.
- Наборы связанных веб-сайтов (RWS) — это способ для организации объявить взаимосвязи между сайтами, чтобы браузеры разрешали ограниченный доступ к неразделенным файлам cookie и хранилищу для определенных целей. Сайтам по-прежнему необходимо запрашивать доступ с помощью API доступа к хранилищу, но для сайтов в наборе доступ может быть предоставлен без запросов пользователя.
- Федеративное управление учетными данными (FedCM) — это подход к федеративным службам идентификации, обеспечивающий сохранение конфиденциальности. API доступа к хранилищу обеспечивает доступ к неразделенным файлам cookie и хранилищу после входа в систему. В некоторых случаях использования FedCM предоставляет альтернативное решение API доступа к хранилищу и может быть предпочтительнее, поскольку оно имеет более ориентированное на вход приглашение браузера. Однако внедрение FedCM обычно требует дополнительных изменений в вашем коде, например, для поддержки конечных точек HTTP.
- Также существуют API для защиты от мошенничества , рекламы и измерения , и API доступа к хранилищу не предназначен для решения этих проблем.
Используйте API доступа к хранилищу
API доступа к хранилищу имеет два метода на основе обещаний:
-
Document.hasStorageAccess()
(также доступен под новым именемDocument.hasUnpartitionedCookieAccess()
начиная с Chrome 125) -
Document.requestStorageAccess()
Он также интегрируется с API разрешений . Это позволяет вам проверить статус разрешения доступа к хранилищу в стороннем контексте, который указывает, будет ли автоматически разрешен вызов document.requestStorageAccess()
:
Используйте метод hasStorageAccess()
При первой загрузке сайта он может использовать метод hasStorageAccess()
, чтобы проверить, предоставлен ли уже доступ к сторонним файлам cookie.
// Set a hasAccess boolean variable which defaults to false.
let hasAccess = false;
async function handleCookieAccessInit() {
if (!document.hasStorageAccess) {
// Storage Access API is not supported so best we can do is
// hope it's an older browser that doesn't block 3P cookies.
hasAccess = true;
} else {
// Check whether access has been granted using the Storage Access API.
// Note on page load this will always be false initially so we could be
// skipped in this example, but including for completeness for when this
// is not so obvious.
hasAccess = await document.hasStorageAccess();
if (!hasAccess) {
// Handle the lack of access (covered later)
}
}
if (hasAccess) {
// Use the cookies.
}
}
handleCookieAccessInit();
Доступ к хранилищу предоставляется документу iframe только после того, как он вызывает requestStorageAccess(),
поэтому hasStorageAccess()
изначально всегда возвращает false — за исключением случаев, когда другому документу того же происхождения в том же iframe уже был предоставлен доступ. Предоставление сохраняется при навигации по тому же источнику внутри iframe специально для того, чтобы разрешить перезагрузку после предоставления доступа к страницам, для которых требуется присутствие файлов cookie в первоначальном запросе HTML-документа.
Используйте requestStorageAccess()
Если у iframe нет доступа, возможно, ему потребуется запросить доступ с помощью метода requestStorageAccess()
:
if (!hasAccess) {
try {
await document.requestStorageAccess();
} catch (err) {
// Access was not granted and it may be gated behind an interaction
return;
}
}
При первом запросе пользователю может потребоваться подтвердить этот доступ с помощью запроса браузера, после чего обещание будет разрешено или будет отклонено, что приведет к исключению, если используется await
.
Во избежание злоупотреблений это приглашение браузера будет отображаться только после взаимодействия с пользователем. Вот почему requestStorageAccess()
изначально необходимо вызывать из обработчика событий, активируемых пользователем, а не сразу при загрузке iframe:
async function doClick() {
// Only do this extra check if access hasn't already been given
// based on the hasAccess variable.
if (!hasAccess) {
try {
await document.requestStorageAccess();
hasAccess = true; // Can assume this was true if requestStorageAccess() did not reject.
} catch (err) {
// Access was not granted.
return;
}
}
if (hasAccess) {
// Use the cookies
}
}
document.querySelector('#my-button').addEventListener('click', doClick);
Если вам нужно использовать локальное хранилище вместо файлов cookie, вы можете сделать следующее:
let handle = null;
async function doClick() {
if (!handle) {
try {
handle = await document.requestStorageAccess({localStorage: true});
} catch (err) {
// Access was not granted.
return;
}
}
// Use handle to access unpartitioned local storage.
handle.localStorage.setItem('foo', 'bar');
}
document.querySelector('#my-button').addEventListener('click', doClick);
Запросы на разрешение
Когда пользователь нажимает кнопку в первый раз, в большинстве случаев автоматически появляется приглашение браузера, обычно в адресной строке. На следующем снимке экрана показан пример приглашения Chrome, но другие браузеры имеют аналогичный пользовательский интерфейс:
При определенных обстоятельствах запрос может быть пропущен браузером, и разрешение будет предоставлено автоматически:
- Если страница и iframe использовались в течение последних 30 дней после принятия запроса.
- Если встроенный iframe является частью набора связанных веб-сайтов .
- Если FedCM используется в качестве сигнала доверия для доступа к хранилищу.
- В Firefox приглашение также пропускается для известных веб-сайтов (тех, с которыми вы взаимодействовали на верхнем уровне) в течение первых пяти попыток.
Альтернативно, метод может быть автоматически отклонен без отображения подсказки при определенных обстоятельствах:
- Если пользователь ранее не посещал и не взаимодействовал с сайтом, которому принадлежит iframe как документ верхнего уровня, а не в iframe. Это означает, что API доступа к хранилищу полезен только для встроенных сайтов, которые пользователи ранее посещали в собственном контексте.
- Если метод
requestStorageAccess()
вызывается вне события взаимодействия с пользователем без предварительного утверждения запроса после взаимодействия.
Хотя пользователю будет предложено при первом использовании, последующие посещения могут разрешить requestStorageAccess()
без запроса и без вмешательства пользователя в Chrome и Firefox. Обратите внимание, что Safari всегда требует взаимодействия с пользователем.
Поскольку доступ к файлам cookie и хранилищу может быть предоставлен без запроса или взаимодействия с пользователем, часто можно получить неразделенный доступ к файлам cookie или хранилищу до взаимодействия с пользователем в браузерах, которые это поддерживают (Chrome и Firefox), вызвав requestStorageAccess()
при загрузке страницы. Это может позволить вам немедленно получить доступ к неразделенным файлам cookie и хранилищу и обеспечить более полный опыт, даже до того, как пользователь начнет взаимодействовать с iframe. В некоторых ситуациях это может оказаться более удобным для пользователя, чем ожидание взаимодействия с пользователем.
FedCM как сигнал доверия для SAA
FedCM (федеративное управление учетными данными) — это подход к федеративным службам идентификации, обеспечивающий сохранение конфиденциальности (например, «Войти с помощью...»), который не использует сторонние файлы cookie или навигационные перенаправления.
Когда пользователь входит в систему проверяющей стороны (RP), которая имеет встроенный контент от стороннего поставщика удостоверений (IdP) с помощью FedCM, встроенный контент IdP может автоматически получить доступ к хранилищу своих собственных неразделенных файлов cookie верхнего уровня. Чтобы включить автоматический доступ к хранилищу с помощью FedCM, должны быть выполнены следующие условия:
- Аутентификация FedCM (состояние входа пользователя) должна быть активной.
- RP согласился, установив разрешение
identity-credentials-get
, например:
<iframe src="https://idp.example" allow="identity-credentials-get"></iframe>
Например, iframe idp.example
встроен в rp.example
. Когда пользователь входит в систему с помощью FedCM, iframe idp.example
может запросить доступ к хранилищу для своих собственных файлов cookie верхнего уровня.
rp.example
выполняет вызов FedCM для входа пользователя в систему с помощью поставщика удостоверений idp.example
:
// The user will be asked to grant FedCM permission.
const cred = await navigator.credentials.get({
identity: {
providers: [{
configURL: 'https://idp.example/fedcm.json',
clientId: '123',
}],
},
});
После входа пользователя в систему IdP может вызвать requestStorageAccess()
из iframe idp.example
, если RP явно разрешил это с помощью Permissions Policy . Встроенному файлу будет автоматически предоставлен доступ к хранилищу его собственного файла cookie верхнего уровня без активации пользователя или необходимости получения другого запроса на разрешение :
// Make this call within the embedded IdP iframe:
// No user gesture is needed, and the storage access will be auto-granted.
await document.requestStorageAccess();
// This returns `true`.
const hasAccess = await document.hasStorageAccess();
Разрешение будет предоставлено автоматически только в том случае, если пользователь вошел в систему с помощью FedCM. Если аутентификация неактивна, для предоставления доступа к хранилищу применяются стандартные требования SAA .
Используйте запрос разрешения storage-access
Чтобы проверить, можно ли предоставить доступ без взаимодействия с пользователем, вы можете проверить статус разрешения storage-access
и выполнить вызов requestStoreAccess()
раньше, если никаких действий пользователя не требуется, вместо того, чтобы вызывать его и вызывать сбой при взаимодействии. требуется.
Это также позволяет вам потенциально удовлетворить потребность в предварительном запросе, отображая различное содержимое, например кнопку входа в систему.
Следующий код добавляет проверку разрешений storage-access
к предыдущему примеру:
// Set a hasAccess boolean variable which defaults to false except for
// browsers which don't support the API - where we assume
// such browsers also don't block third-party cookies.
let hasAccess = false;
async function hasCookieAccess() {
// Check if Storage Access API is supported
if (!document.requestStorageAccess) {
// Storage Access API is not supported so best we can do is
// hope it's an older browser that doesn't block 3P cookies.
return true;
}
// Check if access has already been granted
if (await document.hasStorageAccess()) {
return true;
}
// Check the storage-access permission
// Wrap this in a try/catch for browsers that support the
// Storage Access API but not this permission check
// (e.g. Safari and earlier versions of Firefox).
let permission;
try {
permission = await navigator.permissions.query(
{name: 'storage-access'}
);
} catch (error) {
// storage-access permission not supported. Assume no cookie access.
return false;
}
if (permission) {
if (permission.state === 'granted') {
// Permission has previously been granted so can just call
// requestStorageAccess() without a user interaction and
// it will resolve automatically.
try {
await document.requestStorageAccess();
return true;
} catch (error) {
// This shouldn't really fail if access is granted, but return false
// if it does.
return false;
}
} else if (permission.state === 'prompt') {
// Need to call requestStorageAccess() after a user interaction
// (potentially with a prompt). Can't do anything further here,
// so handle this in the click handler.
return false;
} else if (permission.state === 'denied') {
// Not used: see https://github.com/privacycg/storage-access/issues/149
return false;
}
}
// By default return false, though should really be caught by earlier tests.
return false;
}
async function handleCookieAccessInit() {
hasAccess = await hasCookieAccess();
if (hasAccess) {
// Use the cookies.
}
}
handleCookieAccessInit();
Изолированные iframe в песочнице
При использовании API доступа к хранилищу в изолированных iframes требуются следующие разрешения песочницы:
- Для разрешения доступа к API доступа к хранилищу требуется
allow-storage-access-by-user-activation
. -
allow-scripts
необходим, чтобы разрешить использование JavaScript для вызова API. -
allow-same-origin
требуется, чтобы разрешить доступ к файлам cookie того же происхождения и другим хранилищам.
Например:
<iframe sandbox="allow-storage-access-by-user-activation
allow-scripts
allow-same-origin"
src="..."></iframe>
Требования к файлам cookie
Чтобы к межсайтовым файлам cookie можно было получить доступ с помощью API доступа к хранилищу в Chrome, необходимо установить следующие два атрибута:
-
SameSite=None
— требуется, чтобы пометить файл cookie как межсайтовый. -
Secure
— обеспечивает доступ только к файлам cookie, установленным сайтами HTTPS.
В Firefox и Safari для файлов cookie по умолчанию установлено значение SameSite=None
, и они не ограничивают SAA для Secure
файлов cookie, поэтому эти атрибуты не являются обязательными. Рекомендуется явно указывать атрибут SameSite
и всегда использовать Secure
файлы cookie.
Доступ к странице верхнего уровня
API доступа к хранилищу предназначен для обеспечения доступа к сторонним файлам cookie во встроенных iframe.
Существуют также другие случаи использования, когда страница верхнего уровня требует доступа к сторонним файлам cookie. Например, изображения или скрипты, использование которых ограничено файлами cookie, и которые владельцы сайтов могут захотеть включить непосредственно в документ верхнего уровня, а не в iframe. Чтобы решить эту проблему, Chrome предложил расширение API доступа к хранилищу , которое добавляет метод requestStorageAccessFor()
.
Метод requestStorageAccessFor()
Метод requestStorageAccessFor()
работает аналогично requestStorageAccess()
но для ресурсов верхнего уровня. Его можно использовать только для сайтов в наборе связанных веб-сайтов , чтобы предотвратить предоставление общего доступа к сторонним файлам cookie.
Подробнее о том, как использовать requestStorageAccessFor()
читайте в разделе «Наборы связанных веб-сайтов: руководство для разработчиков» .
Запрос разрешения top-level-storage-access
Поддержка браузера
Подобно разрешению storage-access
, существует разрешение top-level-storage-access
позволяющее проверить, можно ли предоставить доступ для requestStorageAccessFor()
.
Чем отличается API доступа к хранилищу при использовании с RWS?
Когда наборы связанных веб-сайтов используются с API доступа к хранилищу, доступны определенные дополнительные возможности, подробно описанные в следующей таблице:
Без РВС | С РВС | |
---|---|---|
Требуется жест пользователя, чтобы инициировать запрос на доступ к хранилищу. | ||
Требуется, чтобы пользователь посетил запрошенное хранилище в контексте верхнего уровня, прежде чем предоставить доступ. | ||
Запрос пользователя при первом посещении можно пропустить. | ||
requestStorageAccess не требуется вызывать, если доступ был ранее предоставлен | ||
Автоматически предоставляет доступ к другим доменам на связанном веб-сайте. | ||
Поддерживает requestStorageAccessFor для доступа к страницам верхнего уровня. |
Демо: настройка и доступ к файлам cookie
В следующей демонстрации показано, как можно получить доступ к файлу cookie, установленному вами на первом экране демонстрации, во встроенном фрейме на втором сайте демонстрации:
хранилище-доступ-api-demo.glitch.me
Для демонстрации требуется браузер с отключенными сторонними файлами cookie:
- Chrome 118 или более поздней версии с установленным
chrome://flags/#test-third-party-cookie-phaseout
и перезапущенным браузером. - Firefox
- Сафари
Демо: настройка локального хранилища
В следующей демонстрации показано, как получить доступ к неразделенным широковещательным каналам из стороннего iframe с помощью API доступа к хранилищу:
https://saa-beyond-cookies.glitch.me/
Для демонстрации требуется Chrome 125 или более поздней версии с включенным флагом поэтапного отказа от сторонних файлов cookie .
Ресурсы
- Прочтите спецификацию , предоставляющую доступ к сторонним файлам cookie, или следуйте ей и поднимайте вопросы .
- Прочтите спецификацию , обеспечивающую доступ к неразделенному хранилищу, или следуйте ей и поднимайте вопросы .
- Документация и руководство по API.
- Документация Chrome по использованию API доступа к хранилищу в наборах связанных веб-сайтов