Как спроектировать REST-вход без сохранения состояния с двухфакторной аутентификацией (2FA)?

Я борюсь с концепцией разработки API RESTful-аутентификации без сохранения состояния с многофакторной аутентификацией.

Почти по определению, потребность в 2FA требует нескольких состояний; войдите в систему с именем пользователя / паролем, затем отправьте "код" (TOTP, SMS-код, ответ на вопрос о проверке и т. д.). Это также подразумевает конечный автомат (FSM) некоторого вида.

Насколько я могу судить, единственные варианты, которые существуют для поддержания механизма без сохранения состояния:

  1. клиент должен передавать некоторую информацию о состоянии (например, текущее состояние FSM) при отправке данных для перехода в следующее состояние,
  2. состояние должно сохраняться на стороне сервера,
  3. клиент должен передавать ВСЕ данные при каждом запросе, что позволило ему достичь текущего состояния

Очевидно, что передача ВСЕХ данных бессмысленна. Таким образом, это подразумевает либо передачу информации о состоянии (непрозрачной или иной) в запросе, либо сохранение состояния на сервере.

Или есть какая-то другая техника, которую мне не хватает?

1 ответ

Решение

Я добавляю решение, которое придумал, на случай, если оно будет выгодным для кого-то еще в будущем. Обратите внимание, что в этом случае PVQ расшифровывается как "Персональный вопрос проверки" (т.е. аутентификация на основе знаний).

В конце я разработал конечную точку входа в систему так, чтобы она требовала:

  • Заголовок авторизации (который является токеном 2FA): Authorization: authType=”PVQ” token=”<tokenid>”
  • имя пользователя
  • пароль

Если Authorization заголовок отсутствует, конечная точка возвращает 401 и устанавливает WWW-Authenticate заголовок, указывающий, что для входа требуется токен 2FA (т. е. заголовок авторизации). параметр может быть PVQ, SMS, TOTP и т. д. (в зависимости от конфигурации пользователя)

WWW-Authenticate : authType="PVQ"

Если клиент получает ответ 401/WWW-Authenticate, он обязан вызвать конечные точки 2FA:

  • вызов / получить (получить жетон вызова)

    • Клиент: отправляет имя пользователя / пароль
    • Сервер: отвечает с идентификатором, и либо
      • вопрос (PVQ),
      • или просто отправляет отправляет СМС код через стороннего СМС провайдера
  • проверить / получить (получить токен 2FA, необходимый для Authorization заголовок)

    • Клиент: отправляет
      • ID, полученный в challenge/get
      • имя пользователя Пароль
      • ответ на вызов (т. е. текстовый ответ на PVQ, или код SMS, или код TOTP)
    • Сервер: возвращает
      • 2FA значение токена

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

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

На стороне сервера в БД хранится некоторая информация о состоянии в контексте кода SMS или вопроса PVQ, отправленного пользователю, а также эфемерный токен 2FA аутентификации (одноразовое использование и фиксированный TTL).

Другие вопросы по тегам