Является ли devise token_authenticatable безопасным?

65

Я создаю простой api с Rails API и хочу, чтобы я был на правильном пути здесь. Я использую приложение для обработки логинов и решил перейти с параметром Devise token_authenticatable, который генерирует ключ API, который вам нужно отправить с каждым запросом.

Я соединяю API с базовым интерфейсом/марионеткой и обычно задаюсь вопросом, как мне обрабатывать сеансы. Моя первая мысль состояла в том, чтобы просто сохранить ключ api в локальном хранилище или куки файл и получить его на загрузке страницы, но что-то о сохранении ключа api, которое меня беспокоило с точки зрения безопасности. Нелегко ли было бы захватить ключ api, заглянув в локальное хранилище/куки или обнюхивая любой запрос, который проходит, и используйте его для олицетворения этого пользователя на неопределенный срок? Я в настоящее время сбрасываю ключ api каждый логин, но даже это кажется частым - каждый раз, когда вы входите в систему на любом устройстве, это означает, что вы выходите на все остальные, что является видом боли. Если бы я мог отказаться от этого reset, я чувствую, что он улучшится с точки зрения удобства использования.

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

Теги:
authentication
devise
rails-api

3 ответа

160
Лучший ответ

token_authenticatable уязвим для временных атак, которые очень хорошо объясняются в этом сообщении в блоге. Эти атаки были причиной удаления token_authenticatable из Devise 3.1. См. сообщение в блоге plataformatec для получения дополнительной информации.

Чтобы иметь самый безопасный механизм аутентификации маркера, токен:

  • Должно быть отправлено через HTTPS.

  • Должен быть случайным, с криптографической силой.

  • Необходимо безопасно сравнивать.

  • Нельзя хранить непосредственно в базе данных. Здесь может храниться только хэш-токен. (Помните, токен = пароль. Мы не храним пароли в обычном тексте в db, правильно?)

  • Срок действия истекает в соответствии с некоторой логикой.

Если вы откажетесь от некоторых из этих пунктов в пользу удобства использования, у вас будет механизм, который не настолько безопасен, как мог бы быть. Это так просто. Вы должны быть достаточно безопасными, если удовлетворяете первым трем требованиям и ограничиваете доступ к своей базе данных.

Расширение и объяснение моего ответа:

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

    Если вы не используете HTTPS, то многое может пойти не так. Например:

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

    • В Rails 3 куки только окутаны кодировкой Base64, поэтому их можно довольно легко выявить. Для получения дополнительной информации см. Decoding Rails Session Cookies.

      Так как Rails 4, хранилище файлов cookie шифруется, поэтому данные как в цифровой форме, так и нечитабельно для злоумышленника. Файлы cookie должны быть защищены, если ваш secret_key_base не просочился.

  • Создайте свой токен, используя SecureRandom.hex. Или используйте драгоценный камень sysrandom.

    По-видимому, SecureRandom не является безопасным. Тем не менее, здесь есть компромисс: выберите что-нибудь из стандартной библиотеки или выберите немного известного драгоценного камня, которого кто-то поддерживает. Для обоснованного решения я предлагаю прочитать sysrandom README и сообщение в блоге Как создать безопасные случайные числа на разных языках программирования.

  • Найдите запись пользователя, используя идентификатор пользователя, адрес электронной почты или другой атрибут. Затем сравните этот токен пользователя с токеном запроса с Devise.secure_compare(user.auth_token, params[:auth_token]. Если вы используете Rails 4.2.1+, вы также можете использовать ActiveSupport::SecurityUtils.secure_compare.

    Do not найти запись пользователя с помощью Rails finder, например User.find_by(auth_token: params[:auth_token]). Это уязвимо для временных атак!

  • Если у вас одновременно будет несколько приложений/сеансов для каждого пользователя, у вас есть два варианта:

    • Храните незашифрованный токен в базе данных, чтобы он мог использоваться совместно. Это плохая практика, но я думаю, вы можете сделать это во имя UX (и если вы доверяете своим сотрудникам доступ к БД).

    • Храните столько зашифрованных токенов для каждого пользователя, сколько вы хотите разрешить текущие сеансы. Поэтому, если вы хотите разрешить 2 сеанса на двух разных устройствах, сохраните 2 разных хэша токена в базе данных. Этот вариант немного менее прост в реализации, но он определенно безопаснее. У этого также есть потенциал, позволяющий предоставить вашим пользователям возможность прекратить текущие активные сеансы на определенных устройствах, отменив их токены (так же как GitHub и Facebook).

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

    Google заканчивает токен, если он не использовался в течение шести месяцев.

    Facebook истекает токен, если он не использовался в течение двух месяцев:

    Родные мобильные приложения, использующие SDK для Facebook, получат долговременный доступ токены, хорошие около 60 дней. Эти токены будут обновляться один раз в день, когда пользователь, использующий ваше приложение, обращается с просьбой к Facebook сервера. Если запросы не будут выполнены, токен истечет после примерно 60 дней, и человеку придется снова пройти поток входа в систему получите новый токен.

  • Перейдите к Rails 4, чтобы использовать его зашифрованное хранилище cookie. Если вы не можете, тогда зашифруйте хранилище файлов cookie самостоятельно, как предлагается здесь. Не было бы проблем с хранением токена аутентификации в зашифрованном хранилище cookie.

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

Чтобы начать работу, вы можете проверить этот смысл (одним из авторов Devise) о том, как реализовать аутентификацию токена с помощью Devise, Наконец, Railscast для защиты API должен быть полезен.

  • 0
    Круто, это очень помогает - спасибо! Это почти наверняка даст правильный ответ. Щедрость принадлежит вам, если вы добавите к этому свое мнение / рекомендацию (в частности) о наилучшем способе обработки аутентификации API:)
  • 0
    То, что я описал, является наиболее безопасным способом обработки аутентификации API, не знаю, что вы подразумеваете под «лучшим». Но я постараюсь быть максимально конкретным.
Показать ещё 9 комментариев
8

Согласно проекту README, devise_token_auth был вдохновлен этой статьей StackOverflow: https://github.com/lynndylanhurley/devise_token_auth

3

Вы можете использовать rails4 с вашим API, обеспечивая более высокую безопасность и использование devise 3.1.0rc

  • В Rails 4.0 несколько функций были извлечены в драгоценные камни.

    • ActiveRecord:: SessionStore
    • Кэширование действий
    • Кэширование страницы
    • Russian Doll-кэширование через истечение срока действия ключа с автоматическим управлением зависимостями вложенных шаблонов.
      http://blog.envylabs.com/post/41711428227/rails-4-security-for-session-cookies
  • Devise 3.1.0.rc работает как с Rails 3.2, так и с Rails 4.0. http://blog.plataformatec.com.br/2013/08/devise-3-1-now-with-more-secure-defaults/

  • Devise - это отказ от TokenAuthenticatable в 3.1.0rc, но вы можете создать свой собственный TokenAuthenticatable метод для обеспечения безопасности. Он более надежный и безопасный.

Для токена, хранилища сеансов вы можете пройти через http://ruby.railstutorial.org/chapters/sign-in-sign-out и http://blog.bigbinary.com/2013/03/19/cookies-on-rails.html для более понятной.

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

  • 0
    У кого-нибудь есть пример кастомной альтернативы?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню