Разработка аутентификации Facebook в приложении для iOS, которое также обращается к защищенному веб-сервису

402

Цель: разрешить пользователю проходить аутентификацию через Facebook в приложении iOS, для которого требуется доступ к защищенной веб-службе, которую я использую.

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

Подробности:

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

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

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

  1. Клиент выскакивает Facebook iOS Войти
  2. Пользователь UI входит в систему с учетными данными Facebook и получает токен доступа
  3. Приложение iOS передает токен доступа на наш сервер
  4. Наш сервер общается с API графа FB, используя токен доступа, чтобы (а) проверить токен и (б) получить идентификатор пользователя FB для этого токена доступа.

    например, наш сервер будет вызывать https://graph.facebook.com/me/?access_token=XYZ, который будет возвращать информацию профиля в объекте JSON

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

  6. Затем клиент передает билет проверки подлинности при последующих взаимодействиях, которые требуют проверки подлинности.

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

ТМС
источник
1
Как это было решено? Я также собираюсь передать токен доступа и раскрутить пользователя на сервере. Кажется академическим, но прошу.
Крис Ван Бускирк,
Это была моя реализация с использованием rails и devise: stackoverflow.com/questions/7232490/…
Мэтт
Почему бы не передать весь auth_hash вместо двух вызовов API FB (один с устройства iOS и один с сервера)?
bsiddiqui
1
Что делать, если вы хотите войти в систему с другого устройства (то есть у вас нет авторизационного билета)? И если вы только что получили новый билет авторизации, что мешает кому-либо похитить идентификатор / токен Facebook в пути и использовать его на своем устройстве?
Amitloaf
Из любопытства, на шаге 5, зачем выдавать свой собственный билет авторизации? Не могли бы вы использовать токен доступа Facebook для каждого последующего вызова сервера? Я понимаю, что это потребует вызова от сервера API Facebook для каждого приложения -> серверный вызов, а не только первый.
Андерс

Ответы:

80

Я только что имел дело с этим сам, и вот часть, которая укусила меня:

На вашем шаге 5 ... Пользователь может зарегистрировать учетную запись с вами совершенно отдельно от своего идентификатора Facebook, верно? Затем в другой раз они входят в систему с Facebook .... И вы просто создали им вторую учетную запись и потеряли их первую.

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

Кроме того, ваш план звучит убедительно.

Обновление : Facebook добавил документ с изложением такого сценария ЗДЕСЬ

Дэн Рэй
источник
7
Да, я обдумал это, и вы на месте. Мы планируем объединить учетные записи, если это тот же адрес электронной почты, а если нет, мы создадим другой способ их объединения.
TMC
Какую серверную библиотеку вы используете на стороне сервера для выполнения запроса?
TimLeung
7
@TimLeung - Насколько я понимаю, токен доступа встраивает идентификатор приложения, и что у вас не может быть токена доступа, БЕЗ врезанного идентификатора приложения.
Дэн Рэй
1
@TimLeunge: мы используем Graph API для запросов с токеном доступа пользователя.
TMC
29

Используйте https для передачи токена авторизации на ваш сервер, как заявлено в Facebook

Разделение токенов доступа

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

zoomcrypt
источник
16

Одна проблема, которую я вижу в этой стратегии, заключается в том, что кто-то может дать вам токен доступа, полученный для другого приложения Facebook. Насколько я знаю, нет способа проверить, что токен доступа предназначен для вашего приложения, поэтому вы просто продолжите и будете его использовать.

Это звучит не очень вредно, хотя. Обычно люди / приложения пытаются защитить токены доступа, а не делиться ими.

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

Это немного далеко, но я думаю, что это может сработать.

Изменить: похоже, что есть способ проверить токен доступа в конце концов. Смотрите ответ @Daaniel на вопрос. Получите идентификатор приложения из токена доступа пользователя (или проверьте исходное приложение для токена) .

ivant
источник
Отправка appsecret_proofдолжна предотвратить это (см. Здесь )
Тони
@ Тони, можешь объяснить, как appsecret_proofздесь помогает? Насколько я понимаю, это служит для того, чтобы доказать Facebook, что сервер знает секретный ключ. Однако ivant ссылался на вредоносное приложение, получающее токены и затем отправляющее их в ваш API. Сервер может проверить идентификатор приложения, но идентификатор приложения может быть легко подделан вредоносным приложением. Итак ... как бы это смягчить?
YSK
3
Вы можете проверить, что для вашего приложения был сгенерирован токен, https://graph.facebook.com/app/?access_token=[user_access_token]который возвращает идентификатор приложения, а затем сравнивает идентификаторы приложения
Nader
4

Ваше решение полностью работает.

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

hamsterdam
источник
3
Я мог бы легко узнать, как клиент общается с сервером. Тогда я мог просто бросить электронные письма на это, пока я не получу хит. Всегда должна быть какая-то форма проверки
Крис
5
Высокое доверие и клиент? Никогда в одном предложении, пожалуйста. За исключением предыдущего предложения, конечно.
EralpB