При создании приложений в стиле SPA с использованием таких фреймворков, как Angular, Ember, React и т. Д., Что люди считают лучшими практиками для аутентификации и управления сеансами? Я могу подумать о нескольких способах решения проблемы.
Относитесь к этому не иначе, как к аутентификации с помощью обычного веб-приложения, предполагая, что API и пользовательский интерфейс имеют одинаковый домен происхождения.
Скорее всего, это будет связано с наличием файла cookie сеанса, хранилища сеансов на стороне сервера и, возможно, некоторой конечной точки API сеанса, которую может использовать аутентифицированный веб-интерфейс пользователя, чтобы получить информацию о текущем пользователе, чтобы помочь с персонализацией или, возможно, даже определить роли / возможности на стороне клиента. Конечно, сервер будет по-прежнему применять правила, защищающие доступ к данным, пользовательский интерфейс будет просто использовать эту информацию для настройки взаимодействия.
Относитесь к нему как к любому стороннему клиенту, использующему общедоступный API, и выполняйте аутентификацию с помощью некоторой системы токенов, аналогичной OAuth. Этот механизм токенов использовался бы пользовательским интерфейсом клиента для аутентификации каждого запроса к API сервера.
Я не очень разбираюсь в этом, но № 1 кажется вполне достаточным для подавляющего большинства случаев, но мне бы очень хотелось услышать несколько более опытных мнений.
Ответы:
Этот вопрос был рассмотрен, в несколько иной форме, подробно, здесь:
RESTful аутентификация
Но это обращается к нему со стороны сервера. Давайте посмотрим на это со стороны клиента. Прежде чем мы сделаем это, есть важная прелюдия:
Javascript Crypto безнадежен
Статья Матасано об этом известна, но содержащиеся в ней уроки довольно важны:
https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/august/javascript-cryptography-considered-harmful/
Подвести итоги:
<script> function hash_algorithm(password){ lol_nope_send_it_to_me_instead(password); }</script>
И добавить собственное следствие:
Это делает многие схемы аутентификации RESTful невозможными или глупыми, если вы собираетесь использовать клиент JavaScript. Давайте смотреть!
HTTP Basic Auth
Прежде всего, HTTP Basic Auth. Самая простая схема: просто передайте имя и пароль при каждом запросе.
Конечно, для этого абсолютно необходим SSL, потому что вы передаете кодированное Base64 (обратимо) имя и пароль при каждом запросе. Любой, кто слушает линию, может легко извлечь имя пользователя и пароль. Большинство аргументов «Базовая аутентификация небезопасна» происходят из места «Базовая аутентификация через HTTP», что является ужасной идеей.
Браузер обеспечивает встроенную поддержку HTTP Basic Auth, но это ужасно, и вам, вероятно, не стоит использовать его для своего приложения. Однако альтернативой является сохранение имени пользователя и пароля в JavaScript.
Это самое ОТЛИЧНОЕ решение. Сервер не требует никакого знания состояния и проверяет подлинность каждого отдельного взаимодействия с пользователем. Некоторые энтузиасты REST (в основном, соломенные) настаивают на том, что поддержание любого рода состояния является ересью и пойдет на поводу, если вы подумаете о каком-либо другом методе аутентификации. У такого соответствия стандартам есть теоретические преимущества - он поддерживается Apache «из коробки» - вы можете хранить свои объекты в виде файлов в папках, защищенных файлами .htaccess, если хотите.
Проблема ? Вы кэшируете на стороне клиента имя пользователя и пароль. Это дает злому злу лучший выход из ситуации - даже самые элементарные уязвимости XSS могут привести к тому, что клиент отправит свое имя пользователя и пароль на злой сервер. Вы можете попытаться уменьшить этот риск, хэшируя и пересылая пароль, но помните: JavaScript Crypto безнадежен . Вы можете уменьшить этот риск, оставив его на усмотрение поддержки Basic Auth в браузере, но, как упоминалось ранее, это ужасно, как грех.
HTTP Digest Auth
Возможна ли дайджест-аутентификация с помощью jQuery?
Более «безопасная» аутентификация - это запрос хэша запроса / ответа. За исключением JavaScript, Crypto безнадежен , поэтому он работает только через SSL, и вам все равно придется кэшировать имя пользователя и пароль на стороне клиента, что делает его более сложным, чем HTTP Basic Auth, но не более безопасным .
Проверка подлинности запроса с дополнительными параметрами подписи.
Еще одна более «безопасная» аутентификация, где вы шифруете свои параметры одноразовыми и временными данными (для защиты от повторных и временных атак) и отправляете. Одним из лучших примеров этого является протокол 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, но не более безопасно .
знак
Пользователь отправляет имя пользователя и пароль, а взамен получает токен, который можно использовать для аутентификации запросов.
Это немного более безопасно, чем HTTP Basic Auth, потому что, как только транзакция с именем пользователя / паролем будет завершена, вы можете отбросить конфиденциальные данные. Он также менее RESTful, поскольку токены составляют «состояние» и усложняют реализацию сервера.
SSL Still
Проблема, однако, в том, что вам все еще нужно отправить это начальное имя пользователя и пароль, чтобы получить токен. Конфиденциальная информация по-прежнему касается вашего компромиссного JavaScript.
Чтобы защитить учетные данные вашего пользователя, вам все равно нужно держать злоумышленников вне вашего JavaScript, и вам все равно нужно отправить имя пользователя и пароль по сети. Требуется SSL.
Срок действия токена
Распространено применение политик токенов, например «эй, когда этот токен был слишком долгим, откажитесь от него и заставьте пользователя снова аутентифицироваться». или «Я уверен, что единственный IP-адрес, разрешенный для использования этого токена
XXX.XXX.XXX.XXX
». Многие из этих политик являются довольно хорошими идеями.Firesheeping
Однако использование токена без SSL по-прежнему уязвимо для атаки, называемой «подделка»: http://codebutler.github.io/firesheep/
Злоумышленник не получает учетные данные вашего пользователя, но он все равно может притвориться вашим пользователем, что может быть довольно плохо.
tl; dr: отправка незашифрованных токенов по проводам означает, что злоумышленники могут легко получить эти токены и выдать себя за пользователя. FireSheep - это программа, которая делает это очень просто.
Отдельная, более безопасная зона
Чем больше приложение, которое вы запускаете, тем труднее абсолютно гарантировать, что они не смогут внедрить некоторый код, который изменяет способ обработки конфиденциальных данных. Вы абсолютно доверяете своему CDN? Ваши рекламодатели? Ваша собственная кодовая база?
Общий для деталей кредитной карты и менее общий для имени пользователя и пароля - некоторые разработчики хранят «ввод конфиденциальных данных» на отдельной странице от остальной части своего приложения, страницу, которой можно жестко управлять и как можно лучше ее заблокировать, желательно такую, которая трудно фишинг пользователей.
Cookie (просто означает токен)
Можно (и часто) поместить маркер аутентификации в куки. Это не меняет никаких свойств auth с токеном, это скорее удобство. Все предыдущие аргументы все еще применяются.
Сессия (все еще означает просто токен)
Session Auth - это просто аутентификация токена, но с некоторыми отличиями, которые делают его немного другим:
Кроме того, на самом деле он ничем не отличается от Token Auth.
Это еще дальше от реализации RESTful - с объектами состояния вы идете все дальше и дальше по пути простого старого RPC на сервере с состоянием.
OAuth 2.0
OAuth 2.0 рассматривает проблему «Как Программное обеспечение A предоставляет Программному обеспечению B доступ к данным Пользователя X без программного обеспечения B, имеющего доступ к учетным данным пользователя X».
Реализация в значительной степени является просто стандартным способом для пользователя получить токен, а затем для стороннего сервиса перейти «да, этот пользователь и этот токен совпадают, и вы можете получить некоторые их данные от нас сейчас».
По сути, OAuth 2.0 - это просто протокол токенов. Он обладает теми же свойствами, что и другие протоколы токенов - вам все еще нужен SSL для защиты этих токенов - он просто меняет способ генерации этих токенов.
OAuth 2.0 может помочь вам двумя способами:
Но когда дело доходит до этого, вы просто ... используете токены.
Вернуться к вашему вопросу
Итак, вопрос, который вы задаете, заключается в следующем: «Должен ли я хранить свой токен в файле cookie, и чтобы автоматическое управление сеансами моей среды заботилось о деталях, или я должен хранить свой токен в Javascript и обрабатывать эти данные самостоятельно?»
И ответ таков: делай все, что делает тебя счастливым .
Суть автоматического управления сессиями в том, что за кулисами происходит много магии. Часто лучше самим контролировать эти детали.
Мне 21, так что SSL это да
Другой ответ: используйте https для всего, иначе разбойники украдут пароли и токены ваших пользователей.
источник
It's also less RESTful, as tokens constitute "state and make the server implementation more complicated."
(1) REST требует, чтобы сервер не имел состояния. Токен, хранимый на стороне клиента , не представляет состояния для сервера. (2) Более сложный серверный код не имеет ничего общего с RESTfulness.lol_nope_send_it_to_me_instead
Мне понравилось название этой функции: DВы можете повысить безопасность в процессе аутентификации, используя JWT (JSON Web Tokens) и SSL / HTTPS.
Базовый идентификатор аутентификации / сессии может быть украден через:
Используя JWT, вы шифруете данные аутентификации пользователя и сохраняете их в клиенте, а также отправляете их вместе с каждым запросом в API, где сервер / API проверяет токен.
Он не может быть расшифрован / прочитан без закрытого ключа (который сервер / API хранит тайно).Read update .Новый (более безопасный) поток будет:
Авторизоваться
Каждый запрос к API
Обновлено 30.07.15:
Полезная нагрузка / заявки JWT фактически могут быть прочитаны без закрытого ключа (секретного), и хранить его в localStorage небезопасно. Я сожалею об этих ложных утверждениях. Однако они, похоже, работают над стандартом JWE (JSON Web Encryption) .
Я реализовал это, сохранив утверждения (userID, exp) в JWT, подписав его закрытым ключом (секретным), о котором API / бэкэнд знает только, и сохранил его как безопасный HttpOnly cookie на клиенте. Таким образом, он не может быть прочитан через XSS и не может быть изменен, иначе JWT не пройдет проверку подписи. Кроме того, используя безопасный файл cookie HttpOnly , вы убедитесь, что файл cookie отправляется только через HTTP-запросы (недоступны для сценария) и только через безопасное соединение (HTTPS).
Обновлено 17.07.16:
JWT по своей природе не имеют гражданства. Это означает, что они лишают законной силы / истекают сами. Добавляя SessionID в утверждения токена, вы делаете его состоящим из состояния, поскольку его действительность теперь зависит не только от проверки подписи и даты истечения срока действия, но также от состояния сеанса на сервере. Однако положительным моментом является то, что вы можете легко аннулировать токены / сеансы, чего раньше не было с JWT без сохранения состояния.
источник
Я бы пошел на второй, система токенов.
Знаете ли вы о ember-auth или ember-simple-auth ? Они оба используют систему на основе токенов, например, ember-simple-auth:
У них есть управление сессиями, и их легко подключить к существующим проектам.
Существует также пример ember-simple-auth в качестве примера Ember App Kit: Рабочий пример использования ember-app-kit с использованием ember-simple-auth для аутентификации OAuth2.
источник