Passkeys

Аккаунт, который вы завели неделю назад,
должен пускать вас и сейчас.

У каждого профиля свой аутентификатор. Passkey, зарегистрированный внутри профиля, перехватывается, остаётся на вашем диске и подставляется, когда эта личность входит снова - в другом процессе, через неделю или на другой машине.

Почему это ломается

Passkey принадлежит устройству. А у вас много личностей.

Сайты переводят вход на passkeys по умолчанию, а passkey намеренно привязан к аутентификатору, который его создал. На обычной машине этот аутентификатор - сама машина: нормально для одного личного аккаунта и неверно для всего остального, чем вы здесь занимаетесь.

Одна связка ключей, много аккаунтов

Платформенный аутентификатор общий для всех профилей на компьютере. Заводите второй аккаунт на том же сайте - и просите одно устройство держать две личности, которым встречаться не полагалось.

Автоматизация до него не дотянется

Touch ID и Windows Hello ждут живого пальца. Агент упирается в запрос passkey и останавливается - так скрипт, который месяц назад входил нормально, тихо превращается в скрипт, который не входит вообще.

Личность не переезжает

Меняете машину - учётные данные остаются на прежней, ровно для этого аппаратная привязка и придумана. Куки переехали. Passkey нет, и аккаунт с новой машины недостижим.

регистрация и повтор выключить
// Включать нечего: захват и повтор работают по умолчанию.
const { browser, page } = await ab.launch({ profile: "seller-04" })

// Регистрируем passkey на сайте, руками или агентом.
// Он попадёт в <профиль>/passkeys.json, а не в связку ключей ОС.
await page.goto("https://webauthn.io")

// Через неделю, в другом процессе, на другой машине: тот же профиль, вход на месте.
const { page: later } = await ab.launch({ profile: "seller-04" })
await later.getByRole("button", { name: "Sign in with a passkey" }).click()
// Для профиля, если хотите подтверждать каждую регистрацию сами.
await ab.launch({ profile: "seller-04", webauthnCapture: false })

# Python, тот же формат профиля, то же хранилище
browser = await launch_async(profile="seller-04", webauthn_capture=False)

Один аутентификатор на профиль.

Устройство - это профиль. Его аутентификатор отвечает на WebAuthn-запрос сайта внутри браузера, а учётные данные пишутся в файл этого профиля, а не в связку ключей компьютера.

Регистрация перехватывается сама. Включено по умолчанию при создании профиля. Настраивать нечего, и не нужно прокликивать запрос при каждой регистрации.
Для повтора не нужен особый код. Агент или вы нажимаете кнопку входа на самом сайте. Подтверждение формируется ниже уровня автоматизации.
Едет вместе с личностью. Хранилище - часть профиля, поэтому экспорт профиля или включённая вами облачная синхронизация несут passkey вместе с куками и отпечатком.
Выключение - переключатель профиля. Отключите захват, и каждая регистрация будет спрашивать: то, что нужно личности, которую вы ведёте руками.

Проверяем это нарочно жёстко. Регистрируем passkey на webauthn.io в профиле, закрываем браузер, удаляем весь локальный каталог профиля, восстанавливаем тот же профиль в чистом каталоге и входим, имея только этот passkey. Тест входит в наборы обоих SDK, Node и Python, так что он обязан проходить перед выпуском. Повторите сами на бесплатном тарифе: разбор здесь.

Для чего это на самом деле.

Много аккаунтов, один сайт

Каждый профиль регистрирует свои учётные данные, поэтому аккаунты на одном сайте никогда не делят аутентификатор. Сайт видит разные устройства, потому что всеми доступными ему проверками это и есть разные устройства.

Агенты, которые держат аккаунты

Агенту, зарегистрировавшемуся сегодня и вернувшемуся через неделю, нужны те же учётные данные на месте. Рандомизация при каждом запуске - противоположность тому, что нужно долгоживущей личности. Подробнее про агентов.

Передача личности

Экспортируйте профиль, и тот, кто его импортирует, войдёт: без сброса пароля, без SMS-кода, без общего телефона. Учётные данные внутри полученного им файла.

Границы, прямым текстом

Чего это не делает.

Привязанные к устройству сессии - другое

Google умеет привязывать сессию к ключу в TPM или Secure Enclave, и этот ключ по замыслу не экспортируется. Копирование профиля его не копирует, поэтому мы отключаем механизм, а не оставляем его работать наполовину. Что уходит в сеть, а что нет.

Это не менеджер паролей

Здесь хранятся WebAuthn-данные того профиля, который их создал. Пароли не синхронизируются, и passkeys не импортируются из iCloud Keychain или телефона.

Passkey не заменяет чистую историю

Оставаться в аккаунте и вызывать доверие - не одно и то же. Сожжённый аккаунт, плохой прокси или роботизированное поведение по-прежнему приводят к флагу, и эта страница ничего в этом не меняет.

Вопросы и ответы.

В файле внутри каталога профиля, рядом с куками и хранилищем этого же профиля. Он не пишется ни в связку ключей macOS, ни в Windows Hello, ни в телефон - именно поэтому он принадлежит личности, а не машине. Экспортируете профиль - passkey уезжает вместе с ним.

Да, ради этого всё и сделано. У каждого профиля свой аутентификатор, поэтому десять профилей для сайта - десять разных устройств. На обычной машине платформенный аутентификатор один на все аккаунты, и ломается всё обычно на втором.

Он видит платформенный аутентификатор и получает корректное WebAuthn-подтверждение. Чего он не может - прочитать серийный номер, указывающий на наш софт: в учётных данных нет ничего вендорского. Обещать больше нельзя: аттестация WebAuthn - живая тема, и сайт, требующий аппаратной аттестации настоящего ключа, просит то, чего программный аутентификатор выдать не может.

С включённой облачной синхронизацией для этого профиля хранилище passkey едет вместе с ним, и на другой машине аккаунт входит. С выключенной - с диска не уходит ничего, и личность вы переносите сами, экспортом профиля. Оба пути несут один и тот же файл.

Passkeys - да. Google дополнительно использует привязанные к устройству сессии, приватный ключ которых лежит в TPM или Secure Enclave и по замыслу не экспортируется, так что эту часть не перенесём ни мы, ни кто-либо ещё. Мы отключаем этот механизм, а не делаем вид, что копия работает. Подробности на странице безопасности.

Нет. Агент нажимает ту же кнопку, что и человек. Отдельного API для passkey нет, потому что ответ формируется внутри браузера, ниже уровня автоматизации.

Войдите один раз. Сохраните аккаунт.

На бесплатном тарифе локальные профили без ограничений, у каждого свой аутентификатор. Без карты.

Windows, macOS и Linux · Node 18+ или Python 3.9+