REST API для веб-сайта, который использует Facebook для аутентификации

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

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

Этот вопрос касается того, как аутентифицироваться с нашего сайта из приложения /API и разбивается на 2 части:

  • Каков правильный способ обработки REST-аутентификации из API на веб-сайт, который использует только функцию OAuth Facebook в качестве метода проверки подлинности?

    Я прочитал и много исследовал стандартные методы аутентификации для REST API. Мы не можем использовать такие методы, как Basic Auth over HTTPS, поскольку учетные данные для пользователя как такового отсутствуют. Что-то вроде это, похоже, только для аутентификации приложений с использованием API.

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

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

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

Я чувствую, что мне не хватает чего-то очень очевидного или не совсем понимаю, как должны работать общедоступные API REST, поэтому вам будут очень благодарны любые советы и помощь.

Ответ 1

ОБНОВЛЕНИЕ: см. ниже

Я тоже много думал об этом вопросе. Это еще не совсем понятно мне, но вот маршрут, о котором я собираюсь идти. Я создаю REST API, и мои пользователи работают только с подключением Facebook.

В КЛИЕНТЕ:

  • Используйте API Facebook для входа и получения кода OAUTH2.
  • Замените этот код для токена доступа.
  • В каждом вызове моего пользовательского API я буду включать идентификатор пользователя Facebook и токен доступа.

В API (для каждого метода, который требует аутентификации пользователя):

  • Сделайте запрос на график /me Facebook, используя токен доступа сверху.
  • Убедитесь, что возвращаемый идентификатор пользователя Facebook соответствует идентификатору пользователя, переданному моему API сверху.
  • Если токен доступа истек, требуется дополнительная связь.

Мне еще предстоит проверить это. Как это звучит?

--- Обновление: 27 июля 2014 года, чтобы ответить на вопрос ---

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

В КЛИЕНТЕ:

  • Используйте API Facebook для входа и получения кода OAUTH2.
  • Замените этот код для токена доступа.
  • Запросить токен доступа из моего API, включая токен Facebook в качестве параметра

В API

  • Получить запрос доступа к токенам.
  • Сделайте запрос на графику /me Facebook, используя токен доступа к facebook
  • Убедитесь, что пользователь Facebook существует и соответствует пользователю в моей базе данных
  • Создайте мой собственный токен доступа, сохраните его и верните его клиенту, который будет использоваться с этого момента.

Ответ 2

Это моя реализация с использованием JWT (JSON Web Tokens), в основном аналогичная обновленному ответу Криса. Я использовал Facebook JS SDK и JWT.

Здесь моя реализация.

  • Клиент: Используйте JS SDK для входа в систему и получения токена доступа.

  • Клиент: Запросить JWT из моего API, вызывая /verify-access-token конечную точку.

  • MyAPI: Получает токен доступа, проверяет его, вызывая /me конечную точку Facebook API.

  • MyAPI: Если токен доступа действителен, он находит пользователя из базы данных, регистрирует пользователя, если существует. Создайте JWT с обязательными полями в качестве полезной нагрузки, установите срок действия, подпишите с помощью секретного ключа и отправьте обратно клиенту.

  • Клиент: Сохраняет JWT в локальном хранилище.

  • Клиент: Отправляет маркер вместе с запросом на следующий вызов API.

  • MyAPI: проверить маркер с помощью секретного ключа, если токен действителен, обменять токен на новый, отправить его клиенту вместе с ответом API. (Никакие внешние API-вызовы для проверки токена здесь после) [если токен недействителен/истек клиент запроса для повторной аутентификации и повторить с 1]

  • Клиент Заменяет сохраненный токен на новый и использует его для следующего вызова API. По истечении срока действия токена токен заканчивает отмену доступа к API.

Каждый токен используется один раз.

Подробнее о безопасности и JWT

Насколько безопасно JWT

Если вы можете декодировать JWT, как они защищены?

JSON Web Tokens (JWT) как идентификаторы пользователя и токены аутентификации

Ответ 3

Я пытаюсь ответить на один и тот же вопрос и много читаю недавно...

У меня не будет "ответа", но для меня все становится немного яснее. Вы читали комментарии в о статье, которую вы упомянули? Я нашел их действительно интересными и полезными.

В результате, и в свете того, как все сложилось с момента написания первой статьи, я думаю, что я буду делать:

  • HTTPS везде - это позволяет забыть о HMAC, подписании, nonce,...

  • Используйте OAuth2:

    • Когда запросы на аутентификацию поступают из моих собственных приложений/веб-сайта, используйте этот "трюк" (или его вариант), описанный в ответе на статья, упомянутая ранее.

    • В моем случае у меня есть два типа пользователей: те, у кого есть классические учетные данные для входа/пароля, и те, кто подписался на Facebook Connect.
      Поэтому я бы предоставил обычную регистрационную форму с кнопкой "Войти с Facebook". Если пользователь входит в систему со своими "классическими" учетными данными, я просто отправлю их в свою конечную точку OAuth2 с помощью grant_type=password.
      Если он решит войти в систему через Facebook, я думаю, что это будет двухэтапный процесс:

      • Сначала используйте Facebook iOS SDK, чтобы открыть FBSession
      • Когда это будет сделано, и приложение получит обратно контроль, должен быть способ получить идентификатор Facebook для этого пользователя. Я отправил бы этот идентификатор в мою конечную точку OAuth2 с помощью расширения расширения, понимаемого моим сервером как "с использованием идентификатора пользователя FB".

Обратите внимание, что я все еще сильно изучаю все это, так что это может быть не идеальный ответ... может быть, даже не правильный! Но я думаю, что это послужило бы хорошей отправной точкой. Идея использования "гранта расширения" для аутентификации Facebook может включать необходимость зарегистрировать его для правильной работы? Я не совсем уверен.

В любом случае, я надеюсь, что смогу немного помочь вам, и, по крайней мере, он может начать обсуждение, чтобы найти лучшее решение этой проблемы:)

Обновление
Вход в Facebook не является решением, как указано в комментариях: любой может отправить произвольный идентификатор пользователя и войти в систему как этот пользователь в API.

Как это сделать:

  • Показать форму входа с помощью кнопки входа в систему Facebook.
  • Если этот метод входа выбран, действуйте так же, как и SDK для Facebook: откройте веб-страницу с вашего сервера аутентификации, которая инициирует вход в систему Facebook.
  • Как только пользователь зарегистрировался, Facebook будет использовать ваш URL-адрес перенаправления для подтверждения; что этот URL указывает на другую конечную точку вашего сервера аутентификации (возможно, с дополнительным параметром, указывающим, что вызов пришел из приложения?)
  • Когда конечная точка аутентификации будет удалена, аутентификация может безопасно идентифицировать пользователя, сохранить его FB-идентификатор пользователя/FB-сеанс и вернуть токен доступа в ваше приложение с использованием специальной схемы URL-адресов, как это сделал бы SDK Facebook.

Выглядит лучше?