Способы аутентификации

Исследование методов аутентификации пользователя для сайтов и API. Аутентификация по протоколу oAuth2.

  • 00:02:39 - Allow
  • 00:03:19 - Unauthorized
  • 00:04:24 - Basic Auth
  • 00:11:37 - Bearer Auth
  • 00:15:53 - OAuth2
  • 00:16:53 - OAuth2 Password Grant
  • 00:20:26 - OAuth2 Refresh Token Grant
  • 00:21:57 - Аутентификация через социальную сеть
  • 00:26:34 - OAuth2 Authorization Code Grant
  • 00:27:55 - OAuth2 Token Mode
  • 00:28:25 - OAuth2 Code Mode
  • 00:29:43 - Session Auth
  • 00:31:53 - "Remember me" Cookie Auth
  • 00:32:29 - Cookie Auth
  • 00:35:09 - Подведение итогов
Скрытый контент (код, слайды, ...) для подписчиков. Открыть →
Дмитрий Елисеев
elisdn.ru
Комментарии (20)
voodooism

Почему-то именно в этом видео отсутствует регулятор звука.

Ответить
Дмитрий Елисеев

Весьма странный плеер. Фронтенд как всегда радует :)

Ответить
Антон Жданов

А можно рассказать про OIDC?

Ответить
Дмитрий Елисеев

Это тот же рассмотренный нами OAuth2, который дополнительно при указании scope=openid возвращает ещё один ID-токен формата JWT с данными пользователя.

Ответить
Антон Жданов

Спасибо.

Ответить
Владимир Перепеченко

Толково и кратко!, благодарю. А вопросы таковы :

  1. нужно ли думать как удалять накопившиеся файлы сессий на сервере или работает автоматический надёжный механизм для их очистки?

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

Ответить
Дмитрий Елисеев

Нужно ли думать как удалять накопившиеся файлы сессий

В PHP сессии автоматически чистятся по Cron через время session.gc_maxlifetime из php.ini

По умолчанию установлено 30 минут.

нужно костылить куки в дополнении к сессии

Куки устанавливаются автоматически на время session.cookie_lifetime

Ответить
Владимир Перепеченко

Куки устанавливаются автоматически на время session.cookie_lifetime

Спасибо. А как правильно быстро отменить сессию (запретить вход по старому паролю) не дожидаясь тайм-аута, например после смены пароля пользователя администратором?

Ответить
Дмитрий Елисеев

Можно хранить сессии в базе данных в таблице sessions(id,user_id,expires,value). И при смене пароля сразу по полю user_id всё удалять. Но тогда надо сделать ручную очистку через Cron по полю expires, чтобы база не переполнялась.

Ответить
Владимир Перепеченко

Дмитрий, а верно ли моё предположение, что аутентификация пользователя через сессии будет работать только с GET запросами из браузера, а с POST запросами (через POST ajax из того же броузера) - не будет?

Вроде как броузер не контролирует куки при POST запросах.

Если да, то как посоветуете контролировать безопасность POST запросов?

ПС: Я засомневался, потому что видел такой чужой костыль:

Перед отрисовкой формы (GET) , гетерится случайное число (типа токен) и записывается в сессию + сохраняется в скрытое поле формы. А при POST из этой формы этот "токен" из скрытого поля отправляется на backend в JSON с прочими данными и уже на backend сравнивается с тем же токеном из сессии.

Ответить
Дмитрий Елисеев

Куки по умолчанию не отправляются в Ajax-запросах. Чтобы они добавлялись нужно в JavaScript для fetch или axios включать параметр withCredentials.

Ответить
Владимир Перепеченко

Значит злоумышленник может отправить злонамеренный post запрос не будучи авторизован и запрос будет обработан на бэкенде? А как защититься от этого?

Ответить
Дмитрий Елисеев

Как раз для защиты CSRF в форму и куки добавляется случайный токен, чтобы не получилось отправить форму с другого сайта напрямую через <form action="ваш сайт"> или Ajax-запросом из JavaScript.

Чтобы Ajax-запрос учитывал куки нужно на клиенте в JavaScript включить withCredentials. Но при POST-запросе из-за наличия в запросе заголовка Cookie браузер сразу включает защиту CORS, рассмотренную в следующих скринкастах. Тогда он отправит сначала OPTINS запрос и проверит, что в ответе сервера есть Access-Control-Allow-Credentials. И уже после этого отправит настоящий POST-запрос с куками.

Так что для защиты от POST-запросов с чужих сайтов достаточно добавить скрытое поле и куку. Браузер нас защитит сам.

Но если злоумышленник отправляет запросы не через браузер, а напрямую из HTTP-клиента, то защититься можно только капчей.

Ответить
Владимир Перепеченко

Но если злоумышленник отправляет запросы не через браузер, а напрямую из HTTP-клиента, то защититься можно только капчей.

Да, этот случай.

Но ведь капчей может пользоваться только человек, причем желательно не слепой/глухой. А если мы ждем нападения POST роботов? Или открываем наружу свой API с POST запросами по какому-то url?

В этих случаях защитит только токен? Надежно?

С прошедшим днем учителя Вас и Юлию !!!

Ответить
Дмитрий Елисеев

В этих случаях защитит только токен? Надежно?

Токен защищает только от HTML-форм или Ajax запросов с других сайтов в браузере. Другие HTTP-клиенты смогут спокойно получать и отправлять куку с этим токеном.

Или открываем наружу свой API с POST запросами по какому-то url?

Тогда никак. Можем ограничивать число запросов в минуту с одного IP.

А если мы ждем нападения POST роботов?

Для аутентиифицированных запросов можем банить аккаунты спамеров. А от гостевых запросов от роботов можно защититься только капчей.

Ответить
Владимир Перепеченко

Спасибо, Дмитрий!

Хочу Вас правильно понять.

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

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

Приведу пример, который вроде как должен надежно защищать от таких атак.

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

Наш код по url этой страницы отправляет POST запрос на совершение этого платежа. Без разницы как отправляет: или form submit средствами броузера, или fetch из JavaScript.

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

Пользователь жмет кнопку "оплатить" и наша форма отправляет post запрос на url этой же страницы. Причем запрос отправляется с упомянутым выше токеном.

В handler мы сверяем два значения токена: сохраненный в сессии и прилетевшый в POST запросе. Вот и вся проверка.

И как же ее обойдет внешний злодей с http клиентом?

Пусть он знает url страницы и данные для платежа. Пусть он может отправить post запрос через http клиент без POST авторизации. Но как он узнает свежий токен на странице, если он не авторизовался на ней по get запросу?

Я явно что-то не понимаю.

Ответить
Дмитрий Елисеев

И как же ее обойдет внешний злодей с http клиентом?

Сначала отправит GET запрос и спарсит куку сессии и скрытое поле.
Потом отправит POST с этими данными.

Ответить
Владимир Перепеченко

Отправляю запрос через postman:

get http;//site.ru

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

Что тут можно спарсить для взлома ?

прилетело в ответ:

1) кука

PHPSESSID=ch9lipkk97n9o5tg62rgnp76ro; Path=/;

2) страницу логина:

<form id="tel" method="post">
    <input type="text" name="tel" data-tel placeholder="Телефон">
    <button type="submit">Вход</button>
</form>
<form id="sms" method="post" action="/login">
    <input type="password" name="access-key" placeholder="Пароль">
    <button type="submit">Вход</button>
    <input type="hidden" name="tel">
</div>

<script>
  $(function () {
    $('[name=tel]').focus();
    $('#tel').submit(function () {
      $('#sms').find('[name="tel"]').val($(this).find('[name="tel"]').val());
      $(this).hide();
      $('#sms').show();
      $('#sms').find('[name="access-key"]').focus();
      return !1;
    });
  });
</script>
Ответить
Дмитрий Елисеев

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

Формы перевода в банках как раз доступны только свежезалогиненным клиентам, закрыты этими CSRF-токенами и работают с SMS-подтверждением. Так что взломщику Ajax-запросом с чужого сайта из браузера (или из Postman не зная пароля) что-то отправить с чужого счёта на свой не получится.

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

Что тут можно спарсить для взлома?

Эта форма как раз без CSRF-токена, так что её можно заспамить с других сайтов. Достаточно сделать на любом бесплатном хостинге страницу photo.html с кодом вроде:

<script>
setInterval(function () {
  var tel = rand(79001111111, 79999999999);
  $.post('https;//bank/login', {tel: tel});
}, 100);
</script>

Потом зайти на популярный форум и отправить сообщение с этим адресом:

[link=https;//site/photo.html]Моя фотка[/link]

Из браузеров тысяч читателей в форму банка прилетят миллионы запросов и он разорится на SMS-ках.

Ответить
Владимир Перепеченко

Спасибо!

Из Вашего пояснения я понял главное: что форма выплат с токеном, что находится за этой login страницей, всё-же находиться в безопасности, если злоумышленник не знает логина юзера.

Да, фронтальную логин форму можно заспамить, но это пустяк по сравнению с возможностью спереть деньги.

Теперь я спокоен :)

Благодарю, Дмитрий, за озвученные сценарии взлома! Применю для защиты.

Ответить
Зарегистрируйтесь или войдите чтобы оставить комментарий

Или войти через:

Google
GitHub
Yandex
MailRu