СПА-рекомендации по аутентификации и управления сеансами

строя применения стиля СПА используя рамки как угловое, Уголек, реагирует, ЕТК. что люди считают лучшими практиками для аутентификации и управления сеансами? Я могу придумать несколько способов рассмотрения этой проблемы.

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

    Это, вероятно, будет включать наличие сеанса cookie, серверное хранилище сеансов и, возможно, конечная точка API сеанса, которую аутентифицированный веб-интерфейс может поразить, чтобы получить текущую информацию о пользователе, чтобы помочь с персонализацией или, возможно, даже определить роли/способности на стороне клиента. Сервер по-прежнему будет применять правила, защищающие доступ к данным конечно, пользовательский интерфейс будет просто использовать эту информацию для настройки опыта.

  2. относитесь к нему как к любому стороннему клиенту, использующему открытый API, и аутентифицируйтесь с помощью система токенов аналогична OAuth. Этот механизм маркеров будет использоваться клиентским пользовательским интерфейсом для аутентификации каждого запроса, сделанного к API сервера.

Я не эксперт здесь, но #1 кажется, что вполне достаточно для подавляющего большинства случаев, но я бы очень хотел услышать мнения более опытных.

3 ответов


этот вопрос был рассмотрен, в несколько иной форме, подробно, здесь:

RESTful Аутентификация

но это обращается к нему со стороны сервера. Давайте посмотрим на это со стороны клиента. Прежде чем мы это сделаем, есть важная прелюдия:

Javascript Crypto безнадежен

статья Матасано об этом известна, но содержащиеся в ней уроки довольно важно:

http://www.matasano.com/articles/javascript-cryptography/

подведем итоги:

  • атака "человек в середине" может тривиально заменить ваш крипто-код на <script> function hash_algorithm(password){ lol_nope_send_it_to_me_instead(password); }</script>
  • атака "человек в середине" тривиальна для страницы, которая обслуживает любой ресурс через соединение без SSL.
  • как только у вас есть SSL, вы все равно используете настоящий криптограф.

и добавить следствие моего собственный:

  • успешная атака XSS может привести к тому, что злоумышленник выполнит код в браузере вашего клиента, даже если вы используете SSL-поэтому, даже если у вас есть все люки, Ваш браузер crypto все равно может потерпеть неудачу, если ваш злоумышленник найдет способ выполнить любой код javascript в чужом браузере.

это делает многие схемы аутентификации RESTful невозможными или глупыми, если вы собираетесь использовать клиент JavaScript. Давайте посмотрим!

http Basic Auth

прежде всего, http Basic Auth. Самая простая из схем: просто передайте имя и пароль с каждым запросом.

Это, конечно, абсолютно требует SSL, потому что вы передаете Base64 (обратимо) закодированное имя и пароль с каждым запросом. Любой, кто слушал на линии, мог извлечь имя пользователя и пароль тривиально. Большинство аргументов" Basic Auth is insecure "происходят из места" Basic Auth over HTTP" , которое является ужасная идея.

браузер обеспечивает запеченную в HTTP Basic Auth поддержку, но это уродливо, как грех, и вы, вероятно, не должны использовать его для вашего приложения. Альтернативой, однако, является сохранение имени пользователя и пароля в JavaScript.

Это самое спокойное решение. Сервер не требует знания состояния вообще и аутентифицирует каждое индивидуальное взаимодействие с пользователем. Некоторые энтузиасты отдыха (в основном соломенники) настаивают на том, что поддержание любого государства является ересью и будет пена во рту, Если вы думаете о любом другом методе аутентификации. Есть теоретические преимущества такого рода стандартов-соответствие-он поддерживается Apache из коробки - вы можете хранить свои объекты в виде файлов в папках, защищенных .htaccess файлы, если ваше сердце желаемого!

на ? Вы кэширование на стороне клиента имя пользователя и пароль. Это дает evil.ru лучше взломать его - даже самые основные уязвимости XSS могут привести к клиент передает свое имя пользователя и пароль злому серверу. Вы могли бы попытаться смягчить этот риск путем хеширования и соления пароль, но помните: JavaScript Crypto безнадежен. Вы можете уменьшить этот риск, оставив его до базовой поддержки Auth браузера, но.. уродливый как грех, как упоминалось ранее.

http Digest Auth

возможна ли дайджест-аутентификация с помощью jQuery?

более "безопасный" auth, это запрос / ответ хэш-вызов. Кроме JavaScript Crypto безнадежен, поэтому он работает только через SSL, и вам все равно нужно кэшировать имя пользователя и пароль на стороне клиента, что делает его более сложным, чем HTTP Basic Auth, но больше не безопасно.

проверка подлинности запроса с дополнительными параметрами подписи.

еще один более "безопасный" auth, где вы шифруете свои параметры с помощью данных nonce и синхронизации (для защиты от повторения и синхронизации атаки) и отправить. Одним из лучших примеров этого является протокол OAuth 1.0, который, насколько я знаю, является довольно сложным способом реализации аутентификации на сервере REST.

http://tools.ietf.org/html/rfc5849

О, но нет никаких клиентов OAuth 1.0 для JavaScript. Почему?

JavaScript Crypto безнадежен, помню. JavaScript не может участвовать в OAuth 1.0 без SSL, и вам все равно нужно сохранить имя пользователя и пароль клиента локально-что ставит это в ту же категорию, что и Digest Auth - это сложнее, чем HTTP Basic Auth, но это больше не безопасно.

маркер

пользователь отправляет имя пользователя и пароль, а в exchange получает токен, который можно использовать для аутентификации запросов.

это несколько более безопасно, чем HTTP Basic Auth, потому что как только транзакция имени пользователя / пароля завершена, вы можете отказаться от конфиденциальные данные. Это также менее спокойно, так как токены составляют "состояние" и усложняют реализацию сервера.

SSL все еще

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

чтобы защитить учетные данные пользователя, вам все равно нужно держать злоумышленников вне вашего JavaScript, и вам все равно нужно отправить имя пользователя и пароль по проводам. SSL требуется.

Срок Действия Токена

обычно применяются политики токенов, такие как " Эй, когда этот токен слишком долго, отбросьте его и сделайте аутентификацию пользователя снова."или" я уверен, что единственный IP-адрес, разрешенный для использования этого токена, -XXX.XXX.XXX.XXX". Многие из этих стратегий являются довольно хорошими идеями.

Firesheeping

однако использование токена без SSL по-прежнему уязвимо для атаки под названием "sidejacking": http://codebutler.github.io/firesheep/

злоумышленник не получает учетные данные вашего пользователя, но они все еще могут притворяться вашим пользователем, что может быть довольно плохо.

tl; dr: отправка незашифрованных токенов по проводу означает, что злоумышленники могут легко захватить эти токены и притвориться вашим пользователем. FireSheep-это программа, которая делает это очень легко.

Отдельная, Более Безопасная Зона

чем больше приложение, которое вы запуск, тем сложнее абсолютно гарантировать, что они не смогут ввести некоторый код, который изменяет способ обработки конфиденциальных данных. Вы абсолютно доверяете своему CDN? Ваши рекламодатели? Собственную базу кода?

общие для данных кредитных карт и менее распространенные для имени пользователя и пароля-некоторые разработчики хранят "конфиденциальный ввод данных" на отдельной странице от остальной части их приложения, страница, которая может быть жестко контролируется и заблокирован как можно лучше, предпочтительно тот, который трудно обмануть пользователей.

Cookie (просто означает токен)

можно (и часто) поместить маркер аутентификации в файл cookie. Это не меняет никаких свойств auth с помощью токена, это скорее удобство. Все предыдущие аргументы остаются в силе.

сессия (все еще просто означает токен)

аутентификация сеанса-это просто аутентификация токена, но с несколькими отличиями, которые делают его немного другим вещь:

  • пользователи начинают с неавторизованного маркера.
  • бэкэнд поддерживает объект "состояние", привязанный к токену пользователя.
  • токен в куки.
  • среда приложения абстрагирует детали от вас.

помимо этого, хотя, это ничем не отличается от токена Auth, на самом деле.

Это еще дальше от спокойной реализации-с объектами состояния вы идете все дальше и дальше по пути простого старого RPC на сервере с состоянием.

OAuth 2.0

OAuth 2.0 рассматривает проблему "как программное обеспечение A дает программное обеспечение B доступ к данным пользователя X без программного обеспечения B, имеющего доступ к учетным данным пользователя X."

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

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

есть два способа, которыми OAuth 2.0 может вам помочь:

  • предоставление аутентификации / информации другим
  • получение аутентификации / информации от других

но когда он если уж на то пошло, ты просто ... .. использование токенов.

возвращаясь к вашему вопросу

Итак, вопрос, который вы задаете: "должен ли я хранить свой токен в файле cookie и иметь автоматическое управление сеансами моей среды, чтобы заботиться о деталях, или я должен хранить свой токен в Javascript и обрабатывать эти детали самостоятельно?"

ответ: делай то, что делает тебя счастливым.

дело в автоматическом управлении сеансами, хотя, что за кулисами для тебя происходит много волшебства. Часто лучше контролировать эти детали самому.

мне 21, поэтому SSL да

другой ответ: используйте https для всего или разбойники украдут пароли и токены ваших пользователей.


вы можете повысить безопасность процесса аутентификации с помощью JWT (веб-токены JSON) и SSL / HTTPS.

основной идентификатор Auth / Session может быть украден через:

  • MITM атака (человек-в-середине) -без SSL / HTTPS
  • злоумышленник получает доступ к компьютеру пользователя
  • межсайтовый скриптинг

используя JWT, вы шифруете данные аутентификации пользователя и сохраняете их в клиенте, а также отправка его вместе с каждым запросом в API, где сервер/API проверяет токен. он не может быть расшифрован / прочитан без закрытого ключа (который сервер / API хранит тайно) обновление читать.

новый (более безопасный) потока:

логин

  • пользователь входит в систему и отправляет учетные данные для входа в API (через SSL/HTTPS)
  • API получает логин верительные грамоты
  • если действует:
    • зарегистрировать новый сеанс в базе данных обновление читать
    • шифровать идентификатор пользователя, идентификатор сеанса, IP-адрес, метку времени и т. д. в JWT с закрытым ключом.
  • API отправляет токен JWT обратно клиенту (через SSL/HTTPS)
  • клиент получает токен JWT и сохраняет его в localStorage/cookie

каждый запрос В API

  • пользователь отправляет HTTP-запрос в API (через SSL/HTTPS) с сохраненным токеном JWT в заголовке HTTP
  • API читает HTTP-заголовок и расшифровывает токен JWT с его закрытым ключом
  • API проверяет токен JWT, сопоставляет IP-адрес из HTTP-запроса с адресом в токене JWT и проверяет, истек ли сеанс
  • если действует:
    • ответ просил содержание
  • если инвалид:
    • исключение броска (403 / 401)
    • флаг вторжения в систему
    • послать электронное письмо пользователю.

обновлен 30.07.15:

полезная нагрузка/утверждения JWT могут быть прочитаны без закрытого ключа (секрет), и небезопасно хранить его в localStorage. Я сожалею об этих ложных утверждениях. Однако они, похоже, работают над стандарт JWE (веб-шифрование JSON).

я реализовал это, сохранив утверждения (userID, exp) в JWT, подписал его закрытым ключом (секретным), о котором знает только API/backend, и сохранил его как безопасный файл cookie HttpOnly на клиенте. Таким образом, он не может быть прочитан через XSS и не может быть обработан, иначе JWT не проходит проверку подписи. Также с помощью безопасный HttpOnly cookie, вы убедитесь, что cookie отправляется только через HTTP запросы (недоступны для скрипта) и отправляются только через защищенное соединение (HTTPS).

Обновлено 17.07.16:

JWTs по своей природе без гражданства. Это означает, что они аннулируют / истекают сами. Добавляя SessionID в утверждения маркера, Вы делаете его stateful, потому что его действительность теперь зависит не только от проверки подписи и даты истечения срока действия, но и от состояния сеанса на сервере. Однако преимущество заключается в том, что вы можете аннулировать токены/сеансы легко, чего раньше не было с jwts без гражданства.


Я бы пошел на вторую, систему токенов.

вы знали о Эмбер-авт или Эмбер-простой-auth? Они оба используют систему на основе токенов, например ember-simple-auth:

легкая и ненавязчивая библиотека для реализации токенов на основе аутентификация в Ember.приложения на JS. http://ember-simple-auth.simplabs.com

Они имеют управление сеансом и легко подключаются в существующие проекты тоже.

существует также Ember App Kit пример версии ember-simple-auth:рабочий пример ember-app-kit с использованием ember-simple-auth для аутентификации OAuth2.