Аутентификация простыми словами
Зачем:«Кто вы» и «что вам можно» это два разных вопроса. После урока вы объясняете, как работают сессии и cookie, токены JWT, вход через сторонний сервис (OAuth, Яндекс ID) и пасскеи, выбираете безопасный способ входа для проекта и не станете хранить пароли открытым текстом.
30 минут
Озвучено синтезом речи (Qwen3-TTS), голос не принадлежит человеку.
Аутентификация — проверка, кто пользователь, а авторизация — решение, что ему можно. Узнают человека через сессию в cookie, токен JWT, OAuth или пасскей.
Два вопроса, которые путают
Когда на сайте появляется вход, возникают два разных вопроса, и их полезно держать врозь.
Аутентификация: кто вы? Это проверка личности: вы ввели пароль, подтвердили код из SMS, приложили палец. Как паспорт на проходной.
Авторизация: что вам можно? Это права: гость может смотреть, редактор править тексты, владелец удалять и видеть заявки. Как пропуск, который открывает одни двери и не открывает другие.
Сначала сервер выясняет, кто пришёл, а потом на каждом запросе решает, можно ли этому человеку то, о чём он просит. Начнём с первого.
Главный вопрос: а нужен ли вход?
Любой вход означает аккаунты, а аккаунты это обязанности. Вы храните чужие персональные данные (закон о них вы уже встречали), отвечаете за их утечку, должны уметь восстанавливать забытые пароли и защищаться от взлома. Для сайта-визитки, лендинга, блога чаще всего вход не нужен совсем: посетитель смотрит страницу и оставляет заявку без аккаунта. Вход нужен там, где есть личное: личный кабинет, заказы, закрытый раздел, редактирование владельцем.
Правило, которое сэкономит месяцы: нет входа, нет и проблем с входом. Начинайте без него.
Сессии и cookie
Допустим, вход нужен. Протокол HTTP, как вы помните, не помнит вас между запросами. Значит, после того как человек вошёл, его надо как-то узнавать при каждом следующем запросе. Классический способ: сессия. Сервер проверил пароль, создал у себя запись «сессия № …, пользователь Анна» и отправил браузеру номер в заголовке Set-Cookie. Браузер сохраняет этот cookie («печенье») и сам присылает его с каждым запросом к этому сайту. Сервер видит номер и узнаёт человека.
У cookie сессии есть три флага, которые ставят всегда:
HttpOnly: страничный скрипт не может прочитать cookie, поэтому даже если в страницу попал чужой скрипт (XSS из урока про DOM), сессию он не украдёт;Secure: cookie отправляется только по HTTPS;SameSite: cookie не отправляется с запросов, начатых чужими сайтами, и это защита от подделки запросов (CSRF).
Пароли: храним то, что нельзя прочитать
Если проверка идёт по паролю, возникает самый серьёзный вопрос: как хранить пароли? Ответ не оставляет вариантов: никогда в открытом виде. Базы данных утекают, и люди используют один и тот же пароль на многих сайтах, поэтому утёкший пароль ломает чужие аккаунты в других местах.
Хранят хеш пароля: результат необратимого вычисления (из хеша пароль не восстановить, можно только вычислить хеш от предполагаемого пароля и сравнить). Но не любой хеш, а медленный и с солью:
- соль: случайная добавка к каждому паролю, поэтому у двух людей с одинаковым паролем хеши разные, и атаковать всех сразу не выйдет;
- медленный алгоритм (argon2id, bcrypt, scrypt): подбор каждого пароля занимает заметное время, и перебирать миллиарды вариантов дорого. Быстрые хеши вроде MD5 или SHA-1 для паролей не годятся: их считают миллиарды в секунду.
Из этого следует и то, что сервис не может «напомнить» вам пароль: он его не знает, а может только дать задать новый. Если сайт присылает забытый пароль письмом, пароль у него хранится открытым текстом, и этому сайту доверять нельзя. Дальше: ограничивать число попыток, не заставлять придумывать сложные правила, но проверять пароль по базам утёкших и поощрять второй фактор (код из приложения). Подробный список правил есть в памятке OWASP по аутентификации (ссылка в источниках).
Токены и JWT
Для интерфейсов API и систем из многих серверов сессия неудобна: все серверы должны знать о ней. Поэтому придумали токены: после входа сервер выдаёт подписанную строку, где записано, кто вы и до какого срока она действует, и дальше не хранит ничего. Самый известный формат называется JWT (JSON Web Token) и состоит из трёх частей через точку: заголовок, содержимое и подпись.
Важно понять два свойства. Первое: JWT подписан, но не зашифрован. Две первые части это просто JSON в кодировке base64, прочитать его может любой. Подпись защищает от подмены, а не от прочтения, так что секретов в токен не кладут. Второе: токен действует до конца срока, и отозвать его раньше трудно. Поэтому срок делают коротким, а токен хранят в HttpOnly cookie. Проверьте на схеме: прочитайте содержимое токена, подмените роль и посмотрите, что скажет сервер:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c2VyLTQyIiwicm9sZSI6InZpc2l0b3IiLCJleHAiOjE4OTM0NTYwMDB9.
{
"sub": "user-42",
"role": "visitor",
"exp": 1893456000
}Подпись сошлась: токен принят. Сервер пересчитал подпись по первым двум частям и своему секрету, и она совпала с третьей.
Секрет здесь учебный и лежит в этой странице. В жизни он только на сервере. Токен ничего не шифрует: даже подписанный, он читается, поэтому не кладите в него то, что нельзя показать.
Проверьте себя: почему в JWT нельзя положить пароль или номер карты, раз он подписан?
Подпись не скрывает содержимое, она лишь не даёт его изменить. Первые две части токена декодирует любой, у кого токен есть.
Вход через стороннего провайдера: OAuth
Хранить пароли страшно, а помнить десять паролей тяжело, поэтому появился «вход через…»: Яндекс ID, VK ID, Госуслуги, а за границей Google или Apple. Работает это на стандарте OAuth 2.0, а точнее на OpenID Connect, который добавляет к нему вопрос «кто вы». (Сам OAuth про другое: он позволяет одному сервису получить ограниченный доступ к данным другого с вашего согласия, например приложению прочитать ваш календарь.)
Идея в том, что пароль вводится только на странице провайдера, а ваш сайт получает от него подтверждение, что человек вошёл, и (с его разрешения) имя или почту. Вы не храните пароль, не придумываете восстановление и получаете двухфакторную защиту провайдера бесплатно. Платой стали зависимость от провайдера и важная юридическая тонкость: данные посетителя проходят через стороннего оператора, а значит, это обработка персональных данных, о которой надо сказать в политике.
Пасскеи: вход без пароля
Самая современная защита называется пасскей (passkey) и построена на стандарте WebAuthn (FIDO2). При регистрации устройство создаёт пару ключей: открытый ключ уходит на сайт, закрытый остаётся на устройстве и никогда его не покидает. При входе сайт присылает случайную строку, а устройство подписывает её закрытым ключом, после того как вы подтвердили себя отпечатком, лицом или кодом устройства.
Результат: пароля нет, поэтому его нельзя подсмотреть, угадать, украсть из базы (на сервере лежат только открытые ключи) или выманить на поддельном сайте, потому что подпись привязана к настоящему адресу. Пасскеи синхронизируются между устройствами через менеджеры паролей Apple, Google и другие. Пока они непривычны многим, и нужен запасной способ входа, но будущее за ними.
Пройдите четыре способа по шагам и посмотрите, что в каждом можно украсть:
- Браузер → сервер. Посетитель вводит пароль, форма отправляет его по HTTPS.
- Сервер. Хеширует пароль и сравнивает с хешем в базе. Совпало: создаёт сессию и запоминает её номер.
- Сервер → браузер. Set-Cookie: sid=… (HttpOnly; Secure; SameSite). Браузер сохраняет cookie.
- Браузер → сервер. Каждый следующий запрос несёт cookie, и сервер узнаёт посетителя по номеру сессии.
Просто и привычно. Сервер помнит сессии, и их можно мгновенно закрыть. Нужен надёжный пароль и защита базы.
Авторизация: роли и права
Когда понятно, кто пришёл, решается, что ему можно. Самый простой и распространённый приём: роли. Каждому пользователю назначена роль (посетитель, редактор, владелец), а каждой роли набор прав (читать, править тексты, удалять, видеть заявки). Права на самое лишнее не раздают: минимум, необходимый для работы.
Главное правило авторизации одно: проверять надо на сервере, при каждом запросе. Скрыть кнопку «Удалить» от посетителей удобно, но это не защита: запрос можно отправить и без кнопки, из консоли или из программы. Если сервер не проверяет права, то кнопка ничего не защищает.
Практика
Вы на сайте эпохи 2022 года. Прежде чем думать о том, как сделать вход, решите, нужен ли он. Спросите себя: что посетитель делает на моём сайте (главное действие из брифа) и обязательно ли ему для этого быть узнанным? Для заявки через форму чаще нет.
Если вход нужен хотя бы владельцу, опишите три роли и что можно каждой, выберите способ входа и скажите, как хранятся пароли (или что их нет). И обязательно упомяните закон: адрес почты и имя персональные данные (152-ФЗ), а вход через Яндекс ID или по SMS обработка таких данных с участием сторонних операторов. Нужны согласие и политика.
Что было не так раньше
Пароли хранили открытым текстом, потом хешем MD5 без соли («достаточно, чтобы не читалось»), и при каждой утечке миллионы паролей оказывались подобраны за часы. «Секретные вопросы» («девичья фамилия матери») угадывались или находились в соцсетях. Номер сессии кладли прямо в адрес страницы (?sid=...), и пересланная ссылка отдавала чужой аккаунт. Basic-авторизация передавала логин с паролем в каждом запросе в открытом виде. Требования к паролям («восемь символов, цифра, заглавная и знак») заставляли придумывать слабые и повторяющиеся пароли.
Сегодняшние рекомендации противоположны: длинные пароли без вычурных правил, проверка по базам утёкших, медленный хеш с солью, второй фактор, а лучше пасскеи и вход через провайдера. Лучшее решение пароли не хранить совсем.
Практика
Готовлю вашу страницу…
Тест
Вопрос 1 из 7
Карточки
Эти карточки попадут в повторение, когда вы завершите урок.
Чем аутентификация отличается от авторизации?
Ответ
Аутентификация отвечает «кто вы» (вход). Авторизация отвечает «что вам можно» (права и роли). Первое проверяют один раз при входе, второе при каждом запросе и на сервере.
Как работает вход с сессией и cookie?
Ответ
После входа сервер создаёт сессию и отдаёт браузеру cookie с её номером (Set-Cookie). Браузер присылает его с каждым запросом. Флаги: HttpOnly, Secure, SameSite.
Как хранить пароли?
Ответ
Никогда открытым текстом: только медленный хеш с солью (argon2id, bcrypt, scrypt). Ограничивать число попыток, проверять по базам утёкших паролей, по возможности добавлять второй фактор или переходить на вход без пароля.
Что такое JWT и OAuth?
Ответ
JWT: подписанный (не зашифрованный!) токен из трёх частей, читаемый всеми. OAuth 2.0: протокол делегирования доступа; OpenID Connect поверх него даёт вход через стороннего провайдера (Яндекс ID, VK ID).
Что такое пасскеи?
Ответ
Вход без пароля по стандарту WebAuthn: пара ключей, закрытый ключ остаётся на устройстве, подтверждение отпечатком, лицом или PIN. Не подвержены фишингу, нечего украсть с сервера.
Источники
- MDN: HTTP authentication CC BY-SA, по-английски
- OWASP Cheat Sheet: Authentication CC BY-SA, по-английски
- OWASP Cheat Sheet: Session Management CC BY-SA, по-английски
- OAuth 2.0: описание и спецификации только ссылка, по-английски
- passkeys.dev: пасскеи для разработчиков только ссылка, по-английски
- Яндекс ID: документация для разработчиков только ссылка, по-русски
Видео
Аутентификация в веб-приложениях: JWT и сессии (Maksim Zhashkevych)
Видео загрузится с youtube-nocookie.com только после нажатия.
Дальше
Теперь вы знаете: сессии и cookie, аутентификация, авторизация и роли, OAuth и вход через сторонние сервисы, пасскеи.