• Как правильно написать авторизацию/аутентификацию?

    dasha_programmist
    @dasha_programmist
    ex Software Engineer at Reddit TS/React/GraphQL/Go
    Есть два варианта хранения данных об авторизованном пользователе:
    1) В куки (так по умолчанию используется в асп.нет): необходимые данные (claims) шифруются machineKey и отдаются пользователю в http-only куках, таким образом при каждом запросе на сервер они присылаются, расшифровываются и далее можно проверить в необходимых местах.
    плюсы: полностью stateless, нет надобности обращаться к БД
    минусы: при необходимости "выбить" сессию со стороны сервера нужно поднимать более сложную логику и хранить флаги в промежуточном хранилище (проверять что если для такого-то пользователя требуется завершить, то такие действия, иначе другие);
    2) Ключ сессии: после успешной аутентификации авторизуем пользователя и claims храним на сервере в быстрой памяти или БД (key-value), где ключ - ключ сессии, значение - любые данные.
    плюсы: есть полный контроль состоянием авторизации (как и возможность завершить сессию со стороны сервера, так и сменить пользователю роль(или другие параметры) "на лету")
    минусы: организация доп. прослойки - кэша или хранение в БД (медленно), при перезапуске/падении сервиса сессии клиентам потребуется перелогиниться.

    1
    1.1 В куки писать или ключ сессии или шифрованные данные о пользователе, сессия - абстрактное понятие (это пара: ключ и данные), ключ должен быть защищенным, т.е. трудным к копированию (хотя бы зрительно трудно запомнить), уникальным (чтобы не возникло коллизий: двум разным пользователям выдался один и тот же ключ, т.е. это не должна быть хэш-функция от логина-пароля или IP или чего-то неуникального).
    1.2 В асп.нет существуют атрибуты авторизации (в которых можно расставлять проверки на требование таковой, роль, конкретный пользователь), в общем смысле логика такова: поступил запрос на сервер, далее нужно посмотреть к какому ресурсу идёт обращение (защищенному или свободному), если ресурс защищен, то проверить куки (ключ сессии или шифрованные данные), расшифровать/получить данные о сессии из кэша и предпринять решение: пускаем или не пускаем (отдаём 401/403 или отдаем 200/404/...).
    1.3 Завести на сервере (в кэше или БД) словарь , при алгоритме проверки сессии добавить условие проверки на наличие записи в словаре.
    1.4 С нескольких - словаря не нужно.

    2
    2.1 Даже если пользователь входит через ВК всё равно нужно отдавать свои ключи сессий/шифрованные данные, а вот внутри данных уже хранить access_token от вк-шной сессии, так очень маленькая вероятность, что токен ВК утечет, а если утек ключ сессии, то действия будут ограничены только функционалом сайта.
    2.2 После расшифровки куки или данных по ключу сессии делать доп запрос на сервер ВК с токеном, который сохранился при аутентификации (access_token), запрос простой, например получить имя пользователя, если ВК выдал что токен просрочен или ошибку, то сессию закрывать или куки с данными обнулять.
    Ответ написан
    3 комментария