Как мне спроектировать веб-сервис RESTful, чтобы использовать стороннюю систему (например, Google, Facebook, Twitter) для аутентификации?

25

Для моей работы у нас есть хороший веб-сервис RESTful, который мы используем для управления несколькими веб-сайтами, которые у нас есть. По сути, веб-сервис позволяет создавать заявки на поддержку и работать с ними, а веб-сайт отвечает за интерфейс. Любые запросы веб-сервиса используют заголовок авторизации, который мы используем для проверки пользователя и его пароля для каждого вызова.

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

В настоящее время мы думаем о том, чтобы веб-сайт обрабатывал аутентификацию самих пользователей, а затем использовал новый вызов setSessionId, который регистрирует их текущий сеанс с серверной частью веб-службы. Каждый дополнительный запрос к веб-сервису будет передавать этот идентификатор сессии и будет проверять его. Кажется, все в порядке, но у меня в голове возникает такое ощущение, что я не обдумываю это, и весь мой просмотр форумов и чтение спецификаций oauth и openid меня просто смущает. Любые советы о том, как справиться с этим?

Ральф Каллавей
источник
нет ничего плохого в том, что вы предлагаете. мне легче смотреть пример кода интеграции openid, чем действительные спецификации oauth и openid ...
spaceman
Какой язык / платформу вы используете? Вам не нужно изобретать велосипед, так как есть рамки, которые могут вам существенно помочь. :)
RobM
@Rob Веб-сервис размещен на Salesforce.com, но доступ к нему осуществляется через прокси-сервер, который на момент написания статьи был Node.js. Тем не менее, похоже, что общий вопрос будет применяться ко всем платформам. И да, я надеюсь использовать каркас, а не изобретать велосипед, просто не уверен, какое колесо использовать.
Ральф Каллавей
@Ralph Да, общий вопрос не зависит от платформы, но он имеет практические последствия, так как платформа, как правило, значительно сузит ваши возможности фреймворка. Итак, у вас есть пользовательское интерфейсное приложение, использующее node.js для веб-службы и хранилища данных, размещенных на salesforce? Вам нужно хранить информацию о пользователе / ​​личности в бэкэнде, или просто аутентификацию и авторизацию для действий во внешнем интерфейсе?
RobM
@RobM да, мы хотим сохранить информацию о пользователе на бэкэнде, т. Е. Электронную почту, имя, фамилию, а также все, что необходимо для проверки будущих вызовов от пользователей веб-службы после их аутентификации.
Ральф Каллавей

Ответы:

14

Похоже, есть две цели:

  1. Легко для конечных пользователей проходить аутентификацию с помощью существующих социальных аккаунтов
  2. Легко для разработчиков, использующих ваш веб-сервис

Разрешение людям использовать ресурсы на вашем сайте делает OAuth2 предпочтительным механизмом из-за популярности и доступности клиентских библиотек.

1. Легко для конечных пользователей проходить аутентификацию с помощью существующих социальных аккаунтов.

Конечный пользователь посещает сайт, который использует ваш API и выбирает для входа. Они отправляются на вашу страницу входа в OAuth. Ваша страница входа показывает обычное имя пользователя и пароль для учетных записей, управляемых на вашем сайте, и набор кнопок социальной авторизации, где они могут нажать, чтобы войти через сайт, такой как Facebook. Когда пользователь выбирает Facebook, вы перенаправляете его на Facebook, чтобы утвердить выбор (запуская поток авторизации Facebook). Когда конечный пользователь завершает вход в Facebook, он перенаправляется обратно на ваш сайт.

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

2. Легко для разработчиков, использующих ваш веб-сервис

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

Разработчику, использующему ваш приятный API отдыха, они не будут знать о взаимодействии Facebook, если вы не решите дать им подсказку в записи о захвате сеанса (например).

TL; DR

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

Изображение потому что картинка == слова * 1000:

введите описание изображения здесь

Можем ли мы назвать это oauth2-piggy-back?

Шаг за шагом

  1. Конечный пользователь посещает сайт, который использует ваш API
  2. Конечный пользователь отправляется на ваш сайт для авторизации или регистрации (oauth2)
  3. Конечный пользователь выбирает социальную аутентификацию, нажимает кнопку входа в Facebook
  4. Ваш сайт устанавливает cookie или устанавливает stateв оаве Facebook, чтобы знать, откуда пришел пользователь
  5. Конечный пользователь перенаправлен на Facebook и принимает соединение на сайте Facebook
  6. Конечный пользователь перенаправлен на ваш сайт для завершения процесса авторизации в Facebook
  7. Вы ищете или создаете пользователя в своей базе данных
  8. Вы создаете новый сеанс на вашем сервере
  9. Вы перенаправляете пользователя обратно на его исходный сайт с помощью токена сеанса.
Джеймс Салливан
источник
5

Как сделать его расширяемым

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

К сожалению, вам нужно два из них, потому что твиттер до сих пор не перешагнул подножку OAuth2.

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

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

Теперь вы разрабатываете интерфейс, который включает в себя другие необходимые вам функции. Я бы лично для этого настроил отдельный REST-сервис. Таким образом, вы можете легко расширить аутентификацию в других местах.
Некоторые сервисы используют JSON для связи, другие используют XML и т. Д. Для основного пользователя вам необходимо объединить их все. Это довольно болезненный процесс, но здесь можно найти некоторые общие основания.

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

Все это позволит вам легко добавлять новых сторонних поставщиков.

Проблемы с токенами

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

Иногда случается, что пользователь забирает токен. Будьте готовы к этому.

Хранилище данных

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

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

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

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

Эдгар Клеркс
источник
1

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

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

Rex
источник
1

Мои два цента: я никогда не делал ничего подобного раньше, и я не знаю, как работают механизмы входа в FB, Twitter или Google, но несколько вопросов всплыли у меня в голове, как только я прочитал ваш вопрос:

  • Несколько входов: что произойдет, если я войду в свой аккаунт Facebook один день, а мой аккаунт Google - в следующий? Или одновременно? Вы рассматриваете эти две учетные записи как уникальные, отдельные учетные записи или у вас должен быть какой-то способ связать эти две учетные записи и разрешить мне доступ к моим билетам в любом случае?
  • Использование внешних идентификаторов. Что происходит, когда Facebook или Twitter решают изменить внешний вид идентификаторов своих учетных записей? Чтобы проиллюстрировать это, если BazLogin представляет уникальную учетную запись, используя код {4382-af56}, но решает, что отныне учетные записи будут иметь 12 цифр, потому что 8 было недостаточно, как вы скажете {1234-4382-af56} из {0000-4382 -af56}?

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

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

idoby
источник