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

Я пытаюсь аутентифицировать пользователя после регистрации. Каков правильный или стандартный способ сделать это?

Используя этот метод как способ его реализации, на шаге 3, как я могу сгенерировать случайный хэш для отправки пользователям Эл. адрес? Я вижу два разных варианта:

  1. крипто
  2. Токен JWT

В настоящее время я использую JWT для входа в систему, поэтому имеет ли смысл использовать тот же токен для проверки пользователя? Почему или почему бы и нет, а если нет, то как правильно?


person Jessica    schedule 17.05.2019    source источник


Ответы (1)


Ответ на ваш вопрос о том, следует ли вам использовать крипто-хэш или токен, не является ни тем, ни другим.

Хэш, который вы создаете для использования в качестве метода проверки, не обязательно должен быть криптографически безопасным, он должен быть только уникальным контрольным хэшем, который нелегко угадать.
В прошлом я использовал UUID версии 4 с < href="https://www.npmjs.com/package/uuid" rel="nofollow noreferrer">UUID, и он отлично работает. Вы также можете использовать base64 для некоторой известной части информации о пользователе, например, его идентификатор или адрес электронной почты, объединенный с чем-то случайным, например, временем в микросекундах и случайной шестнадцатеричной строкой значительной длины, но, честно говоря, время, необходимое для создания чего-то подобного, равно впустую, когда UUID v4 работает нормально.

Ваш хеш также не обязательно должен быть уникальным (разным для каждого пользователя, да, но избежать всех потенциальных коллизий? Нет) — попадание в конечную точку только с помощью хэша — не лучшая идея. Конечная точка также должна принимать идентификатор вашего пользователя в сочетании с хэшем подтверждения. Таким образом, вам не нужно беспокоиться об уникальности хэша в вашем хранилище данных. Найти пользователя по ID, проверить совпадение проверочных хэшей, проверить. Я бы только предложил вам запутать информацию о пользователе таким образом, чтобы вы могли декодировать его на своей стороне (например, base64 кодирует их идентификатор пользователя + адрес электронной почты + некоторую константную строку, которую вы используете).

[РЕДАКТИРОВАТЬ]

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

Когда вы сохраняете регистрационные данные своего пользователя, вы создаете общий секрет, который будете использовать для проверки учетной записи. Это может быть что угодно, что является (относительно) уникальным и содержит достаточную длину и энтропию, чтобы это было нелегко угадать. Мы не кодируем и не шифруем информацию, которая будет распакована позже, мы выполняем буквальное сравнение строк, чтобы убедиться, что секрет, который мы предоставили пользователю, был возвращен нам без изменений. Вот почему можно использовать простой односторонний хэш. Я предложил UUID v4, поскольку компоненты этого хэша генерируются из случайной информации (другие версии UUID используют MAC-адрес машины, время или другую известную часть информации). Вы можете использовать любой метод, который вам нравится, если его нельзя легко расшифровать или угадать.

После того, как вы сгенерируете хэш подтверждения, вы отправляете его пользователю (в красиво отформатированном URL-адресе, по которому ему нужно только щелкнуть), чтобы он завершил регистрацию своей учетной записи. Рекомендации по URL полностью зависят от вас, но вот несколько советов:

ПЛОХО

/verify/<verification hash>
or
/verify?hash=<verification hash>

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

ХОРОШО

/users/<id>/verify/<verification hash>
or
/users/<id>?action=verify&hash=<verification hash>

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

Приведенные выше схемы URL-адресов действительно работают, только если ваши идентификаторы пользователей безопасны для публичного показа. Как правило, никогда не следует использовать идентификаторы хранилища данных в URL-адресе, особенно если они являются последовательными INT. Существует множество вариантов идентификаторов, которые можно использовать в URL-адресах, таких как UUID v1 или HashID или любой другой. реализация короткого идентификатора.

ТАКЖЕ

Хороший способ увидеть, как это делается в дикой природе, — просмотреть электронные письма, которые вы получили от других систем с просьбой подтвердить свой собственный адрес электронной почты. Многие могут использовать формат:
/account/verify/<very long hash>

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

ПРИМЕЧАНИЕ. Хотя этот метод может быть самым «безопасным», я упоминаю его только потому, что он основан на типичных методах, используемых сторонними библиотеками, которые не делают предположений о вашей модели пользовательских данных. Вы можете реализовать этот стиль, если хотите, но это будет больше работы. Мой ответ сосредоточен на вашем намерении выполнить базовую проверку на основе данных в вашей пользовательской модели.

БОНУС

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

person Chase    schedule 17.05.2019
comment
TBH Мне пришлось искать, что такое UUID, но похоже, что он похож на JWT, за исключением того, что вы не можете его декодировать. Это правильно? Если это так, я мог бы также использовать jWT, так как я использую его для входа в систему. - person Jessica; 18.05.2019
comment
UUID похожи на хэш sha1, это односторонние хэши, и нет, вы их не декодируете. Вам не нужно расшифровывать хеш подтверждения, так как вы не кодируете и не шифруете информацию, которую нужно распаковывать здесь. Когда вы проверяете пользователя, вы не аутентифицируете его так же, как при входе в систему, вы просто с разумной уверенностью убеждаетесь, что это тот же пользователь, который предоставил адрес электронной почты при регистрации. Этот шаг является проверкой работоспособности, он не должен быть криптографически безопасным процессом. И повторное использование JWT для этого — не лучшая идея. - person Chase; 18.05.2019
comment
Интересно! Большое спасибо за ваше руководство и терпение!! Итак, я бы объединил электронное письмо вместе с хэшем и отправил его, верно? И небезопасно ли отправлять через JWT? - person Jessica; 18.05.2019
comment
Я исправлю свой ответ несколькими примерами, просто дайте мне пару минут. - person Chase; 18.05.2019