Аутентификация в веб-приложениях
#
Васильев Андрей Михайлович, 2022
Версии презентации
Вопросы доступа к данным
#
Защита
#
Доступ к данным должен осуществляться только уполномоченными лицами
Разделение на читателей и администрацию
#
- Большинство пользователей может только просматривать информацию
- Администрация может добавлять новые элементы на ресурс
Системы разделения полномочий
#
- Пользователю может быть доступна только часть функций
- Предоставление функций может определяться динамически приложением
Идентификация, аутентификация и авторизация
#
- Идентификация — процедура, в результате выполнения которой для субъекта идентификации выявляется его идентификатор, однозначно определяющий этого субъекта в информационной системе
- Аутентификация — это процедура проверки подлинности субъекта, например путём сравнения введённого им пароля с паролём, сохранённым в базе данных
- Авторизация — предоставление субъекту прав на выполнение определённых действий, разрешение на выполнение действия
Пример процедуры аутентификации
#
- Пользователь заходит на сайт и нажимает на кнопку «войти в систему»
- Система показывает экран для входа в систему
- Пользователь вводит имя пользователя, идентифицирует себя
- Пользователь вводит пароль,
- Пользователь нажимает на кнопку «Войти», начинает процедуру аутентификации
- Система получает введённые имя пользователя и пароль, завершая аутентификацию
- Аутентификационный токен передаётся пользователю в ответе
- Браузер выполняет запрос к серверу, сервер использует аутентификационный токен для авторизации последующих действий пользователя
Почему так сложно?
#
- Аутентификация без идентификации невозможна — нельзя определить субъекта, операцию выполнить невозможно
- Авторизация без аутентификации невозможна — нельзя понять какие действия можно разрешать данному пользователю
- Авторизация без идентификации возможна — публичная информация может быть доступна любым пользователем. Но даже в этом случае авторизация выполняется, если явно не обрабатывается приложением
Как оно может стать ещё сложнее:
- Вариантов решения задач очень много
- Зачастую требуется реализовать множество вариантов аутентификации в рамках одного приложения
- Простые процедуры выполнения аутентификации могут быть не безопасны, в приложениях следует реализовывать сценарии, проверенные специалистами по безопасности
Варианты аутентификации пользователей
#
- Аутентификация согласно встроенным возможностям протокола HTTP
- Аутентификация с сохранением сессии
- Аутентификация с использованием сертификатов
- Аутентификация по одноразовому паролю
- Аутентификация по ключам доступа
- Аутентификация по токенам
- Стандарты аутентификации OAuth и OpenID Connect
Аутентификация по протоколу HTTP
#
Задача аутентификации возникла давно и в рамках стандарта HTTP утверждено несколько способов аутентификации: IANA
sequenceDiagram
participant cli as Клиент
participant serv as Сервер
cli ->> serv : GET-запрос по пути PATH
serv ->> cli : Ответ 401, Unauthorized, заголовок WWW-Authenticate
cli ->> cli : Формирует ответ
cli ->> serv : GET-запрос по пути PATH с заголовком Authorization
alt Данные введены верно
serv ->> cli : Ответ 200 с указанным документом
else
serv ->> cli : Ответ 403, Forbidden
end
- Для указания поддерживаемого способа аутентификации сервер передаёт HTTP-заголовок
WWW-Authenticate
- Данные на сервер передаются в заголовке
Authorization
- После успешной авторизации пользователя браузер сохраняет данные в заголовке
Authorization
и передаёт их при каждом запросе серверу
Базовая HTTP-аутентификация, RFC7617
#
sequenceDiagram
actor user as Пользователь
participant brow as Браузер
participant serv as Сервер
user ->> brow : Открывает ссылку в интерфейса
brow ->> serv : Посылает GET-запрос на ссылку
serv ->> brow : Ответ с кодом 401, Unauthorized
brow ->> user : Окно для ввода имени имени и пароля
user ->> brow : Вводит имя пользователя и пароль
brow ->> serv : Передаёт данные в заголовке Authorization
serv ->> serv : Выполняет проверку введённых данных
serv ->> brow : Возвращает результат запроса
Особенности базовой аутентификации
#
- Браузер сохраняет введённые данные и добавляет заголовок ко всем последующим запросам серверу
- Для сброса введённых данных необходимо перезапустить браузер
- Данные базовой аутентификации передаются в открытом виде и может быть перехвачена. Необходимо использовать зашифрованное SSL-соединение
- Данные базовой аутентификации можно передать в рамках URL-запроса
https://username:password@example.com/
Имя пользователя и пароль передаются в формате имя:пароль
и отделяются от пути символом @
Аутентификация с сохранением сессии
#
HTTP cookie — это небольшой фрагмент данных, отправляемый сервером на браузер пользователя, который может сохранить и отсылать обратно с новым запросом к серверу
Используются в веб-приложениями для:
- Управления сеансами пользователя, аутентификации, корзины
- Персонализации контента
- Мониторинга поведения пользователя
sequenceDiagram
participant cli as Браузер
participant ser as Сервер
cli -> ser : Запрос данных
ser -> cli : Ответ с заголовком(ами) `Set-Cookie`
cli -> ser : Запрос с заголовком `Cookie`
Заголовки Set-Cookie
и Cookie
#
Заголовки Set-Cookie
устанавливаются сервером в рамках своего ответа
Простой заголовок может выглядит так:
Set-Cookie: <имя cookie>=<значение cookie>
Таких заголовков в ответе сервера может быть несколько:
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
Браузер будет передавать их клиенту в рамках заголовка Cookie
:
Cookie: yummy_cookie=choco; tasty_cookie=strawberry
От клиента на сервер может передаваться несколько куков
Время жизни куков
#
- Сессионные cookie удаляются при закрытии клиента, то есть существуют только на протяжении текущего сеанса. Однако сеанс автоматически не завершается, что делает их вечными
- Постоянные cookie удаляются не с закрытием клиента, а при наступлении определённого интервала времени
Set-Cookie: id=5aoeu; Expires=Wed, 20 Nov 2010 10:15:00 GMT;
Безопасность HTTP куков
#
- Данные передаются в открытом виде, для защиты нужно использовать SSL-шифрование
- Для защиты данных куки от доступа из JavaScript, необходимо использовать атрибут
HttpOnly
- Можно явно указать домены, с которых будет доступна информация с помощью атрибутов
Domain
и Path
- «Раздражающее» сообщение о куках необходимо по законодательству сообщать пользователю об их использовании веб-приложением и их назначением. Многие JavaScript-библиотеки добавляют свои куки
Аутентификация с сохранением сессии
#
Нет строгого стандарта, RFC, который определял бы процедуру авторизации с помощью формы, каждый разработчик может реализовать логику самостоятельно
Ключевая задача — сформировать токен аутентификации и сохранить его в куки
sequenceDiagram
participant cli as Браузер
participant ser as Сервер
cli ->> ser : GET-запрос на аутентификацию
ser ->> cli : 200, HTML-документ с формой
cli ->> cli : Пользователь заполняет форму и нажимает кнопку «отправить»
cli ->> ser : POST-запрос с данными формы, именем пользователя и паролём
ser ->> cli : 302, с заголовком `Set-Cookie`, содержащим токен аутентификации
cli ->> ser : GET-запрос с заголовком `Cookie` и токеном аутентификации
Аутентификация с использованием сертификатов
#
- Сертификат представляет собой набор атрибутов, идентифицирующих владельца и подписанный центром сертификации
- Центр сертификации выступает в роли посредника, который гарантирует подлинность
- Сертификат криптографически связан с закрытым ключом и позволяет подтвердить факт владения сертификатом
flowchart TB
app[Веб-приложение]
ca[Центр сертификации]
cli[Клиент]
app -- Доверяет центру --> ca
ca -- Выдаёт сертификат --> cli
cli -- Передаёт сертификат приложению при запросе --> app
Проверка сертификата сервером
#
- Сертификат должен быть подписан доверенным центом сертификации
- Сертификат должен быть действительным на данную дату (они выдаются на срок от нескольких месяцев до нескольких лет)
- Сертификат не должен быть отозван соответствующим центром сертификации
Приложение может использовать содержимое сертификата для выполнения авторизации
- Имя владельца
- Название эмитента сертификата
- Серийный номер сертификата
- Отпечаток открытого ключа
Ключевая проблема: сертификат надо создать, передать пользователю и, главное, не передать другим пользователям
Аутентификация по одноразовым паролям
#
Обычно применяется для реализации двухфакторной аутентификации:
- Пользователю необходимо пройти классическую схему аутентификации
- Затем необходимо передать одноразовый пароль
Источниками одноразовых паролей могут быть:
- Аппаратные или программные токены (Яндекс Ключ, Google Authenticator)
- Случайные коды, передаваемые по SMS или другой канал связи
- Распечатка со списком заранее сформированных паролей
В веб-приложениях обычно используется:
- После прохождения аутентификации с помощью формы
- Для подтверждения важных действий внутри приложения
Аутентификация по ключам доступа
#
Данный способ часто применяется для аутентификации устройств, сервисов или других приложений при обращении к веб-сервисам
- Секретные данные — длинные уникальные строки, замещающие имя и пароль
- При создании ключа можно ограничить время его действия
- Ключ нельзя передавать третьим лицам или по небезопасным каналам
Ключи можно передавать в параметрах запроса, в теле запроса, в заголовках запроса
Данную схему можно сравнить со схемой аутентификации по сертификатам, только выдачей сертификата занимается разработчик приложения
Аутентификация по токенам
#
В рамках данной схемы на сервере выделяется отдельное веб-приложение, выполняющее задачу аутентификации, а другие приложения делегируют решение задачи первому
- Веб-приложение, обеспечивающее аутентификацию, называется identity provider или authentication service (в случае, если происходит ещё и авторизация)
- Другие приложения в рамках данной схемы называются service provider
sequenceDiagram
participant cli as Клиент
participant iden as Провайдер идентификации
participant ser as Поставщик услуг
cli ->> iden : Запрос на получение токена для поставщика услуг
iden ->> cli : Формирует и возвращает токен
cli ->> ser : Запрос к услуге, включающий токен
ser ->> cli : Проверяет токен и возвращает ответ на запрос
Аутентификация браузера в провайдере
#
Предыдущий процесс можно реализовать в специализированных клиентах, однако при использовании браузера процедура становится более сложной
sequenceDiagram
participant brow as Веб-браузер
participant iden as Провайдер идентификации
participant ser as Поставщик услуг
brow ->> ser : Посылает GET-запрос по адресу
ser ->> brow : Ответ с перенаправлением на службу идентификации
brow ->> iden : GET-запрос по указанному адресу
iden ->> brow : Страница для ввода аутентификационных данных
brow ->> iden : Передача данных с формы
iden ->> brow : Отправка HTML-формы с введённым токеном
brow ->> ser : Автоматическая отправка формы после открытия
ser ->> brow : Показ запрошенной страницы
Варианты аутентификации по токену
#
Существует множество стандартов, среди наиболее популярных: OAuth, OAuth 2.0, OpenID Connect, SAML, WS-Federation
Внутри токена содержится дополнительная информация:
- кто сгенерировал токен
- кто может быть получателем токена
- срок действия
- набор сведений об аутентифицированной сущности
При получении токена его необходимо проверить на соответствие требованиям приложения
Форматы токенов
#
Simple Web Token
#
Набор пар имя-значение в формате кодирования HTML form, описывает стандартные ключи Issuer, Audience, ExpiresOn и HMACSHA256. Токен подписывается симметричным ключом
JSON Web Token, JWT
#
Содержит три блока, разделённых точками: заголовок, набор полей и подпись. Первые два блока закодированы в JSON-формате и закодированы в base64. Подпись может быть сформирована как симметричными, так и ассиметричными алгоритмами шифрования
Security Assertion Markup Language (SAML)
#
Определяет токены в XML-формате, включающем информацию об эмитенте, субъекте, необходимые условия для проверки токена. Подпись осуществляется при помощи ассиметричной криптографии. Содержат механизм для подтверждения владения токеном
Стандарты OAuth и OpenID Connect
#
Данные стандарты предназначены в первую очередь для решения задачи по предоставлению доступа одного приложения к другому от имени пользователя
Приложению для своей работы могут потребоваться данные из другой системы:
- Список контактов данного пользователя
- Список файлов данного пользователя
- Почтовый адрес данного пользователя
В рамках стандарта OpenID Connect на основе OAuth разработан слой учётных данных, в рамках которого сервер авторизации предоставляет идентификационный токен
Большие технологические компании и государства предоставляет возможности по аутентификации с помощью данных протоколов: Госуслуги, VK, Яндекс, Сбербанк
Реализация аутентификации по паролю
#
Для упрощения данной задачи в промышленных приложениях лучше всего делегировать задачи идентификации и аутентификации внешним приложениям с использованием протоколов OpenID Connect и OAuth 2.0
Для решения задачи аутентификации своими силами необходимо:
- Корректно сохранять данные для идентификации и аутентификации
- Сохранять средства быстрой проверки аутентификации, токены
Хранение аутентификационных данных
#
В рамках приложения необходимо организовать хранилище для зарегистрированных пользователей. Данное хранилище должно включать объекты с полями:
- Имя пользователя
- Зашифрованный пароль пользователя
Пароль пользователя нельзя хранить в открытом виде, т.к. при потере данных (которая точно случится) вся защищённая информация станет доступна
Для защиты пароля рекомендуется использовать схему с добавлением соли
flowchart LR
salt("Соль")
pass("Пароль")
com["Объединение"]
full("Соль + пароль")
hashing["Хеш-функция"]
hashed("Хеш пароля")
salt --> com
pass --> com
com --> full
full --> hashing
hashing --> hashed
Базы данных обычно предоставляют возможности по выполнению хеширования
Особенности использования соли
#
- Соль должна хранится отдельно от хеша пароля, иначе схема теряет смысл
- Соль должна быть достаточно длинная, т.к. небольшую соль достаточно легко подобрать по таблицам
- Соль должна обладать высоким уровнем энтропии
- Соль нельзя хранить в исходном коде приложения, которое устанавливается на многих компьютерах, т.к. она может быть потеряна
- Соль может создаваться динамически, например стандарт PBKDF2
Хранение и проверка сессионных токенов
#
Для верификации сессионных токенов необходимо:
- доверять данным, пришедшим от пользователя, т.е. отказаться от проверки данных
- хранить сессионный токен на стороне сервера для сверки
- применять схемы с шифрованием данных или подписью данных в токене
Хранение сессионных токенов на стороне сервера несёт ряд сложностей:
- сколько токенов может быть выдано конкретному пользователю?
- сколько пространства потребуется для хранения всех выданных токенов?
- сколько времени уйдёт на выявление их корректности?
Последняя схема имеет ряд проблем:
- надо корректно реализовать криптографические схемы
- сложно отозвать скомпрометированные токены