company_banner

Как ты реализуешь аутентификацию, приятель?

https://hackernoon.com/how-do-you-authenticate-mate-f2b70904cc3a
  • Перевод


Все знают о стандартной аутентификации пользователя в приложении. Это олдскульная процедура регистрации — пользователь вводит адрес почты, пароль и т. д., — а затем при входе мы сравниваем почту и/или пароль с сохранёнными данными. Если совпадает, даём доступ. Но времена изменились, и сегодня появилось много других методов аутентификации. Если хотите оставаться востребованным программистом/разработчиком в этом меняющемся, словно калейдоскоп, мире разработки ПО, то вы должны знать обо всех этих новых методах.


Нельзя отрицать, что в любых приложениях и ОС «аутентификация» — крайне важный элемент обеспечения сохранности пользовательских данных и регулирования доступа к информации. Чтобы понять, какой метод аутентификации для вас лучше, нужно разбираться в достоинствах и недостатках всех методов, а также неплохо представлять, как же они работают.


Здесь я постараюсь рассказать о большинстве распространённых сегодня методов аутентификации. Это не подробное техническое руководство, а лишь способ познакомить вас с ними. Хотя методы описаны с учётом применения в вебе, эти идеи можно реализовать и в других условиях.


Будем считать, вы уже знаете о том, что большая часть веба/интернета построена на протоколе HTTP. Также вам нужно знать, как работают веб-приложения, что означает аутентификация пользователя в приложении и что такое клиент-серверная архитектура.


Готовы? Поехали.


Аутентификация на основе сессий


Протокол HTTP не отслеживает состояния, и, если мы аутентифицируем пользователя с помощью имени и пароля, наше приложение не будет знать, тот ли это человек, что и в предыдущем запросе. Нам придётся аутентифицировать снова. При каждом запросе HTTP не знает ничего о том, что происходило до этого, он лишь передаёт запрос. Так что, если вам нужны личные данные, придётся снова логиниться, чтобы приложение знало, что это точно вы. Может сильно раздражать.


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


Процедура аутентификации на основе сессий:


  1. Пользователь вводит в браузере своё имя и пароль, после чего клиентское приложение отправляет на сервер запрос.
  2. Сервер проверяет пользователя, аутентифицирует его, шлёт приложению уникальный пользовательский токен (сохранив его в памяти или базе данных).
  3. Клиентское приложение сохраняет токены в куках и отправляет их при каждом последующем запросе.
  4. Сервер получает каждый запрос, требующий аутентификации, с помощью токена аутентифицирует пользователя и возвращает запрошенные данные клиентскому приложению.
  5. Когда пользователь выходит, клиентское приложение удаляет его токен, поэтому все последующие запросы от этого клиента становятся неаутентифицированными.


У этого метода несколько недостатков.


  • При каждой аутентификации пользователя сервер должен создавать у себя запись. Обычно она хранится в памяти, и при большом количестве пользователей есть вероятность слишком высокой нагрузки на сервер.
  • Поскольку сессии хранятся в памяти, масштабировать не так просто. Если вы многократно реплицируете сервер, то на все новые серверы придётся реплицировать и все пользовательские сессии. Это усложняет масштабирование. (Я считал, этого можно избежать, если иметь выделенный сервер для управления сессиями, но это сложно реализовать, да и не всегда возможно.)

Аутентификация на основе токенов


Аутентификация на основе токенов в последние годы стала очень популярна из-за распространения одностраничных приложений, веб-API и интернета вещей. Чаще всего в качестве токенов используются Json Web Tokens (JWT). Хотя реализации бывают разные, но токены JWT превратились в стандарт де-факто.


При аутентификации на основе токенов состояния не отслеживаются. Мы не будем хранить информацию о пользователе на сервере или в сессии и даже не будем хранить JWT, использованные для клиентов.


Процедура аутентификации на основе токенов:


  1. Пользователь вводит имя и пароль.
  2. Сервер проверяет их и возвращает токен (JWT), который может содержать метаданные вроде user_id, разрешений и т. д.
  3. Токен хранится на клиентской стороне, чаще всего в локальном хранилище, но может лежать и в хранилище сессий или кук.
  4. Последующие запросы к серверу обычно содержат этот токен в качестве дополнительного заголовка авторизации в виде Bearer {JWT}. Ещё токен может пересылаться в теле POST-запроса и даже как параметр запроса.
  5. Сервер расшифровывает JWT, если токен верный, сервер обрабатывает запрос.
  6. Когда пользователь выходит из системы, токен на клиентской стороне уничтожается, с сервером взаимодействовать не нужно.


Более подробное описание.


У метода есть ряд преимуществ:


  • Главное преимущество: поскольку метод никак не оперирует состояниями, серверу не нужно хранить записи с пользовательскими токенами или сессиями. Каждый токен самодостаточен, содержит все необходимые для проверки данные, а также передаёт затребованную пользовательскую информацию. Поэтому токены не усложняют масштабирование.
  • В куках вы просто храните ID пользовательских сессий, а JWT позволяет хранить метаданные любого типа, если это корректный JSON.
  • При использовании кук бэкенд должен выполнять поиск по традиционной SQL-базе или NoSQL-альтернативе, и обмен данными наверняка длится дольше, чем расшифровка токена. Кроме того, раз вы можете хранить внутри JWT дополнительные данные вроде пользовательских разрешений, то можете сэкономить и дополнительные обращения поисковые запросы на получение и обработку данных.
    Допустим, у вас есть API-ресурс /api/orders, который возвращает последние созданные приложением заказы, но просматривать их могут только пользователи категории админов. Если вы используете куки, то, сделав запрос, вы генерируете одно обращение к базе данных для проверки сессии, ещё одно обращение — для получения пользовательских данных и проверки, относится ли пользователь к админам, и третье обращение — для получения данных.
    А если вы применяете JWT, то можете хранить пользовательскую категорию уже в токене. Когда сервер запросит его и расшифрует, вы можете сделать одно обращение к базе данных, чтобы получить нужные заказы.
  • У использования кук на мобильных платформах есть много ограничений и особенностей. А токены сильно проще реализовать на iOS и Android. К тому же токены проще реализовать для приложений и сервисов интернета вещей, в которых не предусмотрено хранение кук.

Благодаря всему этому аутентификация на основе токенов сегодня набирает популярность.


Беспарольная аутентификация


Первой реакцией на термин «беспарольная аутентификация» может быть «Как аутентифицировать кого-то без пароля? Разве такое возможно?»


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


Беспарольная аутентификация — это способ конфигурирования процедуры входа и аутентификации пользователей без ввода паролей. Идея такая:


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


Есть похожий метод, при котором вместо одноразовой ссылки по SMS отправляется код или одноразовый пароль. Но тогда придётся объединить ваше приложение с SMS-сервисом вроде twilio (и сервис не бесплатен). Код или одноразовый пароль тоже можно отправлять по почте.


И ещё один, менее (пока) популярный (и доступный только на устройствах Apple) метод беспарольной аутентификации: использовать Touch ID для аутентификации по отпечаткам пальцев. Подробнее о технологии.


Если вы пользуетесь Slack, то уже могли столкнуться с беспарольной аутентификацией.



Medium предоставляет доступ к своему сайту только по почте. Я недавно обнаружил, что Auth0, или Facebook AccountKit, — это отличный вариант для реализации беспарольной системы для вашего приложения.


Что может пойти не так?


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


В чём преимущества?


Как часто вы пользуетесь ссылкой «забыли пароль» для сброса чёртового пароля, который так и не смогли вспомнить после нескольких неудачных попыток входа на сайт / в приложение? Все мы бываем в такой ситуации. Все пароли не упомнишь, особенно если вы заботитесь о безопасности и для каждого сайта делаете отдельный пароль (соблюдая все эти «должен состоять не менее чем из восьми символов, содержать хотя бы одну цифру, строчную букву и специальный символ»). От всего этого вас избавит беспарольная аутентификация. Знаю, вы думаете сейчас: «Я использую менеджер паролей, идиот». Уважаю. Но не забывайте, что подавляющее большинство пользователей не такие техногики, как вы. Это нужно учитывать.


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


Если вы думаете, что какие-то пользователи предпочтут старомодные логин/пароль, то предоставьте им оба варианта, чтобы они могли выбирать.



Сегодня беспарольная аутентификация быстро набирает популярность.


Единая точка входа (Single Sign On, SSO)


Обращали внимание, что, когда логинишься в браузере в каком-нибудь Google-сервисе, например Gmail, а потом идёшь на Youtube или иной Google-сервис, там не приходится логиниться? Ты автомагически получаешь доступ ко всем сервисам компании. Впечатляет, верно? Ведь хотя Gmail и Youtube — это сервисы Google, но всё же раздельные продукты. Как они аутентифицируют пользователя во всех продуктах после единственного входа?


Этот метод называется единой точкой входа (Single Sign On, SSO).


Реализовать его можно по-разному. Например, использовать центральный сервис для оркестрации единого входа между несколькими клиентами. В случае с Google этот сервис называется Google Accounts. Когда пользователь логинится, Google Accounts создаёт куку, которая сохраняется за пользователем, когда тот ходит по принадлежащим компании сервисам. Как это работает:


  1. Пользователь входит в один из сервисов Google.
  2. Пользователь получает сгенерированную в Google Accounts куку.
  3. Пользователь идёт в другой продукт Google.
  4. Пользователь снова перенаправляется в Google Accounts.
  5. Google Accounts видит, что пользователю уже присвоена кука, и перенаправляет пользователя в запрошенный продукт.

Очень простое описание единой точки входа: пользователь входит один раз и получает доступ ко всем системам без необходимости входить в каждую из них. В этой процедуре используется три сущности, доверяющие другу прямо и косвенно. Пользователь вводит пароль (или аутентифицируется иначе) у поставщика идентификационной информации (identity provider, IDP), чтобы получить доступ к поставщику услуги (service provider (SP). Пользователь доверяет IDP, и SP доверяет IDP, так что SP может доверять пользователю.


Выглядит очень просто, но конкретные реализации бывают очень сложными. Подробнее об этом методе аутентификации.


Аутентификация в соцсетях


Уверен, эта картинка знакома всем:



Это часто называют аутентификацией в соцсетях (Social sign-in) или социальным логином (Social Login). Вы можете аутентифицировать пользователей по их аккаунтам в соцсетях. Тогда пользователям не придётся регистрироваться отдельно в вашем приложении.


Формально социальный логин — это не отдельный метод аутентификации. Это разновидность единой точки входа с упрощением процесса регистрации/входа пользователя в ваше приложение.


Лучшее из двух миров


Пользователи могут войти в ваше приложение одним кликом, если у них есть аккаунт в одной из соцсетей. Им не нужно помнить логины и пароли. Это сильно улучшает опыт использования вашего приложения. Вам как разработчику не нужно волноваться о безопасности пользовательских данных и думать о проверке адресов почты — они уже проверены соцсетями. Кроме того, в соцсетях уже есть механизмы восстановления пароля.


Как использовать


Как разработчик вы должны разбираться в работе этого метода аутентификации. Большинство соцсетей в качестве механизма аутентификации используют авторизацию через OAuth2 (некоторые используют OAuth1, например Twitter). Разберёмся, что такое OAuth. Соцсеть — это сервер ресурсов, ваше приложение — клиент, а пытающийся войти в ваше приложение пользователь — владелец ресурса. Ресурсом называется пользовательский профиль / информация для аутентификации. Когда пользователь хочет войти в ваше приложение, оно перенаправляет пользователя в соцсеть для аутентификации (обычно это всплывающее окно с URL’ом соцсети). После успешной аутентификации пользователь должен дать вашему приложению разрешение на доступ к своему профилю из соцсети. Затем соцсеть возвращает пользователя обратно в ваше приложение, но уже с токеном доступа. В следующий раз приложение возьмёт этот токен и запросит у соцсети информацию из пользовательского профиля. Так работает OAuth (ради простоты я опустил технические подробности).


Для реализации такого механизма вам может понадобиться зарегистрировать своё приложение в разных соцсетях. Вам дадут app_id и другие ключи для конфигурирования подключения к соцсетям. Также есть несколько популярных библиотек/пакетов (вроде Passport, Laravel Socialite и т. д.), которые помогут упростить процедуру и избавят от излишней возни.


Двухфакторная аутентификация (2FA)


Двухфакторная аутентификация (2FA) улучшает безопасность доступа за счёт использования двух методов (также называемых факторами) проверки личности пользователя. Это разновидность многофакторной аутентификации. Наверное, вам не приходило в голову, но в банкоматах вы проходите двухфакторную аутентификацию: на вашей банковской карте должна быть записана правильная информация, и в дополнение к этому вы вводите PIN. Если кто-то украдёт вашу карту, то без кода он не сможет ею воспользоваться. (Не факт! — Примеч. пер.) То есть в системе двухфакторной аутентификации пользователь получает доступ только после того, как предоставит несколько отдельных частей информации.


Другой знакомый пример — двухфакторная аутентификация Mail.Ru, Google, Facebook и т. д. Если включён этот метод входа, то сначала вам нужно ввести логин и пароль, а затем одноразовый пароль (код проверки), отправляемый по SMS. Если ваш обычный пароль был скомпрометирован, аккаунт останется защищённым, потому что на втором шаге входа злоумышленник не сможет ввести нужный код проверки.



Вместо одноразового пароля в качестве второго фактора могут использоваться отпечатки пальцев или снимок сетчатки.


При двухфакторной аутентификации пользователь должен предоставить два из трёх:


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

Большинство хакеров охотятся за паролями и PIN-кодами. Гораздо труднее получить доступ к генератору токенов или биологическим свойствам, поэтому сегодня двухфакторка обеспечивает высокую безопасность аккаунтов.


То есть это универсальное решение? Возможно, нет.


И всё же двухфакторка поможет усилить безопасность аутентификации в вашем приложении. Как реализовать? Возможно, стоит не велосипедить, а воспользоваться существующими решениями вроде Auth0 или Duo.


Аутентификация или авторизация?


Некоторые путают термины «аутентификация» и «авторизация». Это разные вещи.


  • Аутентификация — это проверка вашей личности. Когда вы входите в приложение с именем и паролем, вы аутентифицируетесь.
  • Авторизация — это проверка наличия у вас доступа к чему-либо. Это может быть набор разрешений на какие-то действия. Например, если вы создали в приложении ресурс, то вы можете быть единственным, кому разрешено удалять этот ресурс (потому что вы владелец), а другие пользователи для того не «авторизованы».


Ещё тут?


Поздравляю, вы успешно дочитали длинную, нудную и скучную статью.

Mail.Ru Group 763,74
Строим Интернет
Поделиться публикацией
Похожие публикации
Комментарии 79
  • +2
    Спасибо за статью. Немного намешано разных аспектов аутентифкации, но в основном написаны правильные вещи.
    И ещё один, менее (пока) популярный (и доступный только на устройствах Apple) метод беспарольной аутентификации: использовать Touch ID для аутентификации по отпечаткам пальцев.

    Тут надо отметить, что Touch ID обычно только заменят PIN-код при доступе к криптографическим ключам, которые используются для аутентификации.
    Кстати есть решения и с новомодным FaceID.
    Что касается биометрии, то ее следует рассматривать как локальную аутентификацию на устройстве. Я бы избегал систем, где биометрические данные используются для централизованной аутентификации.

    Одним из трендов в аутентификации обещает стать FIDO U2F. Он, к сожалению, не упоминается в этой статье. Про него очень неплохо написано тут.
    • 0
      Что-то с токенами я не очень понял: если у каждого клиента на сервере хранится свой ключ для подписи токена, то один фиг придется лазить в базу при каждом запросе, если же один ключ для подписей всех токенов, то непонятно как инвалидировать скомпрометированные токены?
      • 0
        Очевидно, что сервер подписывает ответ своим ключом для всех токенов.
        Если аутентификация stateless, то инвалидировать нельзя никак. Единственное, чем вы можете управлять это время жизни токена. Нужно с умом выбирать тот или иной способ аутентификации в соответсвии с конкретной задачей. И конечно не стоит слепо гнаться за «набирающими популярность» вещами. Надо все самому взвешивать и оценивать.
        • 0
          Ну почему нельзя, можно.
          Если приходит юзер с токеном, то, как правило, там же приходит и user_id, по которому мы будем загружать из БД объект этого юзера. Ничего не мешает хранить в этом объекте и минимальную дату годного токена. Если нужна инвалидация — то просто обновляем эту дату в БД до текущей и все токены с ранними датами протухают.
          • 0
            Вы предлагаете по сути хранить в БД время жизни токена. Так мы пришли к противоречию, так как предложенная вами реализация совсем не stateless.
            Для задач, когда хочется и токены использовать и контролировать статус токена, удобнее использовать список отозванных токенов по аналогии CRL для сертификатов.
            • 0
              Токенов может быть много, дата — одна, список токенов хранить не надо.
              • 0
                Еще раз: если для аутентификации вам надо запрашивать статус токена любым способом, то вы теряете stateless. Совсем не важно, одна дата для всех токенов или для каждого индивидуальная. При масштабировании вам придется поддерживать актуальность этой даты на всех серверах.
                Пожалуйста, не надо меня убеждать, что это совсем чуть-чуть информации или что это легко и просто сделать. Я не это оспариваю сейчас.
                • 0

                  Я не спорю с утверждением, что это неподходящего решения для чистого stateless, я дополняю ваш ответ, говоря про случаи, где уже есть пользователь с состоянием (заблокирован/не заблокирован, платная/бесплатная подписка и т.д.). В этом случае это рабочий вариант.

          • 0
            всё-таки в таком варианте токен кажется легко уязвимым.
            куки, кажется привязывали к ip, но это хранится в бд сервера, а от нее мы хотим отказаться.
            ведь должно быть что-то подобное… ну, например, сервер видит запрос, на основании сведений об ip, браузере, на основании каких-то параметров fingerprint компьютера генерирует хэш, и возвращает нам токен с хешем внутри. И далее при каждом предоставлении токена сервером генерируется и проверяется совпадение хешей. Таким образом получится, что токеном нельзя воспользоваться на другом устройстве/из другой программы.
            Такое уже есть? Или проще и считается достаточным короткое время жизни?
          • 0
            by-design инвалидировать не получится, только костылить и хранить список отозванных токенов, что по сути возвращает нас к сессиям
            • 0
              По сути — да, но размер базы будет меньше, а поиск быстрее, ведь список отозванных токенов будет куда короче, чем список вообще всех токенов, плюс по истечении времени действия отозванных токенов их можно безопасно удалять.
              • 0
                А разве чтобы отозвать токен нам не придется его где-то хранить на сервере? Иначе как отозвать токен, который где-то там на клиенте? Или я чего-то не понимаю…
                • 0
                  Хранит придется только его идентификатор, что очень дешево
                  • 0
                    Да, нам придется хранить на сервере список отозванных токенов, но это будет куда дешевле, чем хранить вообще все токены. Это некоторый компромисс между удобством валидации токена и возможностью его отозвать
                    • –1
                      На самом деле не вижу особенной разницы между хранением всех токенов или только отозванных. И в том и другом случае об этом надо думать.
                      А вопрос объема дело десятое, т.к. на малом объеме это не существенно, а на большом есть проблемы и посерьезнее.
                      • +1

                        Отозванные за всё время хранить "дёшево"?

                        • 0
                          Зачем хранить за все время? или вы токены выдаете на года? Хранить надо до истечения времени жизни токена
                      • 0
                        Вы меня не поняли. Разве не надо в каком-то виде хранить инфу о выданном токене, чтобы потом его можно было отозвать? Как можно отозвать на сервере то чего на сервер нет?
                        • 0
                          Как сейчас государство отзывает (объявляет недействительными) паспорта, которые лежат у нас в карманах? Принцип примерно тот же — достаточно внести идентификатор в базу. Хранить идентификатор — дешево. Проверить — быстро.
              • 0
                Когда пользователь выходит из системы, токен на клиентской стороне уничтожается, с сервером взаимодействовать не нужно.

                И вот тут есть проблема — приложение должно особым образом обрабатывать выход (закрытие вкладки или окна). Так же стоит обратить внимание что токен не может быть отозван серверном до истечения expire. Ну то есть можно, но вообще нет.

                • 0

                  Пожалуй единственный недостаток jwt — отсутствие стандартных механизмов верификации. Но это прямо вытекает из его ориентированности на распределённость.

                  • +2
                    Не совсем понятно, что вы имеете в виду под «стандартными механизмами верификации». Можете ли Вы раскрыть более детально ваш тезис?
                    • 0
                      Наверно имелось ввиду то, что верифицировать токен можно имея только приватный ключ сервера.
                      Это не очень удобно если нужно дать возможность верификации другим сервисам (или даже сторонним). Было бы удобно если бы поддерживался еще и открытый ключ для верификации который можно было бы передавать другим.
                      • +1
                        Вы не поверите:

                        {"alg":"RS256","typ":"JWT"}
                      • 0
                        Я имел ввиду, что технология JWT не предусматривает механизма отзыва токена по инициативе сервера, или проверки его актуальности. Без централтного сервера выдачи токенов, или сессионно подобного хранилища этого не реализовать, кмк.
                        • 0

                          Возможно ограничение целей/приложений где и как долго токен действует.
                          Или приложение может требовать токен не старше N секунд и отправлять принудительно за новым

                          • 0
                            Возможно ограничение целей/приложений где и как долго токен действует.

                            Если в самом токене — это не возможность отзыва при бане, например.
                            Или приложение может требовать токен не старше N секунд и отправлять принудительно за новым
                            механизм получения по хорошему должен требовать действий от пользователя (аутентификация), в общем случае. Получается ограничение жизни «сессии».
                  • –1
                    Не очень понял насчет токенов. Если токен хранится только на клиенте и в нем содержится роль юзера, то что ему мешает подделать ее и прописать себя админом? Или он зашифрованный хранится?

                    И еще, не надо сыпать сложной терминологией в простой статье без пояснений, пожалуйста. :( Я ничего не знаю про репликацию. Я даже не знаю что это.

                    А так вообще очень крутая статья. Хорошо все объяснено.
                    • 0
                      В статье приведена ссылка на английский ресурс, где очень хорошо рассказывается про JWT.
                      • 0
                        Если токен хранится только на клиенте и в нем содержится роль юзера, то что ему мешает подделать ее и прописать себя админом?

                        Этому препятствует тот факт, что токен криптографически подписан.
                        • 0
                          На расшифровку подписи при каждом запросе будут тратиться ресурсы сервера.
                          Значит у сессий и у токенов один общий недостаток остается — нагрузка на сервер.
                          • +1
                            Нагрузка, которой вполне можно пренебречь
                      • +3
                        Вы вот шутите первой картинкой: «я использую только md5», а я сейчас как раз правлю сайт, в котором все пароли вместе с эмейлами лежат в таблице MySQL без любого шифра…
                        А вы говорите, «md5»…
                        • –3
                          пароли без соли в md5 — в принципе, правильное решение — при потери соли придется обнулять все пароли
                          • +1
                            Правильное решение в PHP — это хэшировать с помощью password_hash.
                            А без соли хранить md5 нельзя, так как в наши дни это равнозначно отсутствию хеширования — сейчас существует масса таблиц, в которых можно запросто найти все популярные хеши md5.
                            • +1

                              Хранить md5 нельзя ни с солью, ни без. Это очень быстрый алгоритм. А массу радужных таблиц можно найти далеко не только для md5.

                              • –1
                                Раз уж вы так уверены в том, что MD5 хранить нельзя, то, наверное, знаете когда для него нашли прообраз, да? Ну или хотя бы для MD2, который, как известно, ещё хуже, чем MD5?

                                Правильный ответ
                                Ни MD5, ни MD2 до сих пор не взломаны. Атака дней рождения успешно убивается случайной солью, а без этого — требуется память, измеряемая зеттабайтами даже для MD2
                                • 0
                                  Не совсем понимаю, причём тут атака дней рождения и случайная соль. Случайная соль нужна для того, чтобы нельзя было радужную таблицу построить. Атака дней рождения — из другой оперы.

                                  MD5 и какие-либо другие одиночные хэши не стоит использовать даже с солью — при известном хэше и соли 8-мизначный пароль из букв верхнего и нижнего регистра, цифр и спецсимволов можно перебрать за несколько часов. Вместо этого современные системы используют PBKDF2 с большим количеством итераций для сверки пароля.
                                  • 0
                                    Не совсем понимаю, причём тут атака дней рождения
                                    В том и дело, что ни причём. Но это единственная атака, которую практически можно провести на MD5. Кроме перебора, конечно.

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

                          • 0
                            Какого года сайт?
                            Лет 15-17 назад мало кто заморачивался хешированиями и соленьями.
                            Открытые пароли в базах лежали в каждой первой базе, которую я видел ^_^
                            • 0
                              Свежий сайт, работает на PHP 7.0 минимум (из-за синтаксического сахара не запустишь на более ранней версии). Просто вот такие разработчики с таким вот опытом…
                          • +2

                            Хотелось бы еще почитать про аутентификацию на основе утверждений (claims-based).

                            • 0
                              Аутентификация — это проверка вашей личности. Когда вы входите в приложение с именем и паролем, вы аутентифицируетесь.
                              Пароль в примере — способ разрешить дальнейшее использование аккаунта, идентификатором которого выступает имя. Аутентификация — проверка на подлинность, на соответствие заявленному. Проверку прав на доступ к аккаунту можно считать подвидом авторизации. Аутентификацию можно считать неотъемлемой частью, обязательным шагом процедуры авторизации. То есть «не путайте» не должно превратиться в «основательно разделяйте».
                              • 0
                                А еще можно новомодным блокчейном аутентификацию делать)
                                • 0
                                  запарная это штука. пока простое решение есть у emercoin, но там авторизация по сертификату. но для его получения нужен кошелёк и прочие проблемы
                                • +2
                                  Про минусы токенов то не написали: невозможно инвалидировать принудительно, и возросший оверхед при запросах.
                                  • +1
                                    Не очень понятно про возросший оверхед — сессию вы проверяли бесплатно? Поясните, пожалуйста. Инвалидация — да, болячка известная
                                  • +3
                                    Понимаю что статья для новичков и вообще является перводом, но тут явно не хватает описания минусов всех описанных методов помимо аутентификации по сессии (а они есть и еще огого какие). Кроме того можно было бы хотя бы перечислить некоторые менее очевидные методы (тот же kerberos, к примеру).
                                    • +2

                                      Мне кажется, или идея уже освещалась на хабре уважаемым SuperPaintman не так давно
                                      https://habrahabr.ru/post/341164/

                                    • +1
                                      Странно что не упомянули такую вещь как PAKE, которая позволяет аутентифицировать пользователя не передавая его пароль на сервер, тем самым исключая возможность «логирования» данного пароля сервером в открытом виде.
                                      • НЛО прилетело и опубликовало эту надпись здесь
                                        • 0

                                          Спасибо, актуально! Как раз ночью сдал контрольную на coursera.org, по аутентификации и авторизации в node.js через токены и пасспорт и думал что-нибудь почитать ещё по теме)

                                          • 0

                                            Автор, большое тебе спасибо! Я давно искал что-то вроде JWT, но почему-то Гугл для авторизации без состояния советовал только отдельные сервера для аутентификации, типо SAML и oAuth. Единственное о чем я думаю, секрет должен генерироваться раз в какой-то промежуток времени, иначе если его подобрали, то вся система скомпрометирована.

                                            • 0

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

                                              • 0

                                                В статье так и написано.
                                                "Токен хранится на клиентской стороне, чаще всего в локальном хранилище, но может лежать и в хранилище сессий или кук."

                                                • 0
                                                  Тренировался тут на кошках… токены для gmail и vk.com благополучно были доставлены на другую машину путем экспорта-импорта кук. На свежей машине для тех же свежеавторизованных gmail и vk.com в локальном хранилище ничего. Возникает подозрение, что токены ОБЫЧНО хранятся в куках, но МОГУТ лежать и в локальном хранилище. Т.е. все наоборот. Какой все-таки best practice в этом вопросе?
                                                  • 0

                                                    Или я вас не пойму, или вы запутались.
                                                    Сессионный токен это просто идентификатор без полезной нагрузки, просто случайно сгенерированная строка. Такой токен нет особого смысла держать в веб-хранилище. Он передается на сервер через куки, а потом сравнивается с имеющимися токенами в БД.


                                                    Токен JWT это зашифрованные данные. Они могут занимать большой размер и поэтому в куки могут не поместится, тут на помощь приходит веб-хранилище. Поскольку доступ к этому хранилищу осуществляется через js, то такой подход актуален, в основном, для SPA.

                                                    • 0
                                                      Однозначно я запутался -поэтому и спрашиваю. Тогда уточнение gmail и vk вообще используют JWT для авторизации? А кто из больших использует? Хочется в chrome dev tool на него «живьем» посмотреть.
                                                      И правильно ли я понимаю, что если мы используем jwt — мы должны его при каждом запросе передавать на сервер? или есть нюансы?
                                                      • +1
                                                        Токен jwt содержит ваш userid и все права котопые вам нужны. Типа «Пользователь 17, Администратор рубрики 1, администратор рубрики 7». Эту строку сервер генерирует и подписывает своим сертификатом и отдает вам. Пои последующих запросах вы только отдаете эту строку серверу, и если сервер убедился что строка подписана его сертификатом то он доверяет указанным правам сразу, не проверяя ваши права ни по каким своим базам.
                                                        Токен jwt можно использовать как вам вздумается. Например если у вас токен большой то чтобы его не гонять, можно его хранить в webstorage и токеном получать классическую сессионную куку на сервере и гонять уже ее. В таком случае плюс в экономии траффика и возможности сделать короткую сессию чтобы базу не забивать сессиями годовалой давности.

                                                        Недостаток у токена один: если кто то отберет у вас права, то в токене они останутся и сервер будет доверять токену, а не обновленным правам (потому что токен валиден). Чтобы этого избежать придется городить костыль и проверять права при каждом запросе, и jwt перестает отличаться от простых сессионных куки. Можно конечно сделать красивый костыль — например при смене прав куда-то писать что для такого пользователя все токены старше х считать недействительными, и еще хранить дату выдачи в токене, и еще проверять при каждом запросе эту базу, вместо перечитывания всех прав
                                                        • 0
                                                          Ну и все-таки у кого из известных сервис провайдеров можно живьем jwt увидеть? Хоть в хранилище, хоть в куках…
                                              • 0

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


                                                Ага, а если нам нужно изменить пользовательские разрешения?

                                                • 0
                                                  Всегда можно выдать пользователю новый токен
                                                  • 0

                                                    Ну на сервере мы токен не храним. Когда пользователь к нам прийдёт с токеном, откуда мы будем знать что для него нужно выдать новый токен? Из БД?

                                                    • 0
                                                      Могу предположить что надо сравнивать дату выдачи токена и дату изменения записи пользователя… И еще в этом момент сразу отзывать старый токен. А то будет потом ходить один пользователь с разными токенами, разными правами скажем с разных машин и жаловаться что «все глючит».
                                                • +6
                                                  Забавный момент в переводе
                                                  Оригинал
                                                  Another example you might be familiar with is the 2-step verification of Google, facebook etc.

                                                  Перевод
                                                  Другой знакомый пример — двухфакторная аутентификация Mail.Ru, Google, Facebook и т. д.


                                                  • +1
                                                    Забавно (а скорее печально) тут то, что это — знакомый пример двухшаговой аутентификации (2-step verification — 2SV), которую часто ошибочно считают двухфакторной (2FV). И такая ошибка в переводе более существенна, чем безобидное расширение списка компаний.

                                                    ГОСТ на эту тему сейчас только разрабатывается, но есть же NIST SP 800-63b, где про это очень хорошо написано. И Mail.ru стоило бы более грамотно подходить к этому вопросу, в переводах в том числе.
                                                    • +2
                                                      Согласен, это пожалуй более важная ошибка, чем самопиар мэйлру.
                                                      Для тех, кто не в теме:
                                                      Двухшаговая аутентификация отличается от двухфакторной тем, что при двухфакторной вы не знаете результат проверки первого фактора, пока не введете оба фактора. Результат для вас будет либо успех (оба фактора верны) либо неудача (как минимум один из факторов неверный). В двухшаговой вы сначала узнаете, что успешно ввели первый фактор и только после этого вам предлагается ввести второй фактор. То есть тут есть возможность провести атаку сначала на один фактор, а потом проводить атаку на второй. Это зачастую упрощает задачу злоумышленника и по праву считается менее защищенным способом аутентификации.
                                                  • 0
                                                    Авторизация — это проверка наличия у вас доступа к чему-либо. Это может быть набор разрешений на какие-то действия.

                                                    Авторизация — это НЕ проверка наличия у вас доступа к чему-либо.
                                                    Авторизация — это процедура предоставления субъекту определённых прав.
                                                    • 0
                                                      В литературе часто встречается, что авторизация состоит из двух частей — аутентификации (проверки наличия прав), а затем, по результатам, предоставление этих прав или отказ в них.
                                                      Так что это вопрос базисной терминологии.
                                                      • 0
                                                        Ну вот, вы всё запутали :) Aутентификация — проверка того, что идетифицированный субъект, есть тот за кого себя выдает. До прав еще не дошли. Контроль доступа (access approval, access control или enforcement) проверка при действии субъекта на наличие у него прав на это действие, то что часто и, не совсем правильно, называют авторизацией по-русски.
                                                        • 0
                                                          Поддерживаю, проблема размытости термина — авторизация это и процесс, и результат процесса.
                                                          Если процесс, то включает в себя аутентификацию.
                                                          Если результат, то отказ или отсутствие отказа, причем отсутствие отказа можно назвать предоставлением права.
                                                        • 0
                                                          Первый раз вижу такой определение авторизации.
                                                        • 0
                                                          На мой взгляд незаслуженно не рассмотрен вариант аутентификации на основе X.509.
                                                          В случае с Google этот сервис называется Google Accounts.
                                                          ЕМНИП сервис называется Google Maia, или что-то вроде того.
                                                          • +1
                                                            Since JWT are signed and encoded only, and since JWT are not encrypted, JWT do not guarantee any security for sensitive data.
                                                            • 0
                                                              Есть такое, но это не особая проблема т.к. и так JWT должен пересылаться поверх https. Если нужно большее, то есть JWE (JSON Web Encryption).
                                                              • +2

                                                                Ну, обычно JWT содержит данные о пользователе. Вряд ли они являются секретными для него самого.


                                                                Кроме того, ваша цитата противоречит RFC 7519:


                                                                JWTs represent a set of claims as a JSON object that is encoded in a JWS and/or JWE structure.
                                                                — пункт 3. JSON Web Token (JWT) Overview

                                                                То есть JWT может быть как подписанным, так и зашифрованным.

                                                              • 0
                                                                И ещё один, менее (пока) популярный (и доступный только на устройствах Apple) метод беспарольной аутентификации: использовать Touch ID для аутентификации по отпечаткам пальцев.

                                                                На адроиде СБОЛ использует биометрию вместо ввода пинкода, так что это не только Эпл.
                                                                image
                                                                • +1

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


                                                                  Ведь тот же беспарольный доступ с помощью одноразового токена или логин через соц. сети передает на сервер некий токен по клику по ссылке в письме или при редиректе с соц сети обратно на сайт проекта.


                                                                  Далее сервер проверяет этот токен (в базе, oAuth, да это может быть тот же JWT). И в случае успеха для последующих запросов клиент уже будет передавать нечто внутреннее для системы с помощью куки или заголовка.


                                                                  Так что я бы разбил методы на две группы — что мы используем для логина и что мы используем для подтверждения аутентификации для последующих запросов.

                                                                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                                                  Самое читаемое