Разработка процесса входа вручную

Если вам необходимо реализовать вход в веб-приложение или приложение для компьютера через браузер без использования наших SDK (например, создать веб-просмотр для нативного приложения для ПК в Windows 8 или процесс входа с использованием исключительно серверного кода), можно создать для себя процесс входа с использованием перенаправлений в браузере. В этом руководстве рассматриваются все этапы процесса входа и рассказывается, как реализовать каждый из них, не используя наши SDK.

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

Проверка статуса входа

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

Вход в приложение

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


Вызов диалога входа и настройка URL перенаправления

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

https://www.facebook.com/v21.0/dialog/oauth?
  client_id={app-id}
  &redirect_uri={redirect-uri}
  &state={state-param}

Обязательные параметры этой конечной точки:

  • client_id. ID приложения, который можно найти в его панели.
  • redirect_uri. URL, на который будет перенаправлен входящий пользователь. Этот URL получает ответ из диалога входа. Если вы используете веб-просмотр в приложении для ПК, для этого URL должно быть задано значение https://www.facebook.com/connect/login_success.html. Проверить, установлен ли этот URL для вашего приложения, можно в Панели приложений. В меню навигации в левой части Панели приложений выберите раздел Продукты, нажмите Вход через Facebook, а затем выберите Настройки. Проверьте Действительные URI для перенаправления OAuth в разделе Клиентские настройки OAuth.
  • state. Строковое значение, создаваемое приложением для сохранения статуса между запросом и обратным вызовом. Этот параметр предназначен для защиты от подделки межсайтовых запросов и передается обратно без изменений в URI перенаправления.

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

https://www.facebook.com/v21.0/dialog/oauth?
  client_id={app-id}
  &redirect_uri={"https://www.domain.com/login"}
  &state={"{st=state123abc,ds=123456789}"}

В этом случае URI перенаправления будет таким:

https://www.domain.com/login?state="{st=state123abc,ds=123456789}"
    

Он также содержит следующие необязательные параметры:

  • response_type. Указывает, куда будут добавлены данные ответа при перенаправлении обратно в приложение: в параметры или во фрагменты URL. Сведения о том, какой тип приложения выбрать, см. в этом разделе. Имеются следующие варианты:
    • code. Данные ответа добавляются в параметры URL и содержат параметр code (зашифрованную строку, уникальную для каждого запроса входа). Если этот параметр не указан, по умолчанию функция работает именно так. Этот вариант подходит лучше всего, если маркер обрабатывается сервером.
    • token. Данные ответа добавляются в виде фрагмента URL и содержат маркер доступа. Это значение response_type необходимо использовать в приложениях для ПК. Этот вариант подходит лучше всего, если маркер обрабатывается клиентом.
    • code%20token. Данные ответа добавляются в виде фрагмента URL и содержат как маркер доступа, так и параметр code.
    • granted_scopes. Возвращает разделенный запятыми список всех разрешений, предоставленных приложению пользователем на этапе входа. Может комбинироваться с другими значениями response_type. При использовании с параметром token данные ответа добавляются в виде фрагмента URL, в противном случае — в виде параметра URL.
  • scope. Разделенный запятыми или пробелами список разрешений, которые нужно запросить у пользователя приложения.
Для приложений Windows 8

Если вы реализуете вход в приложении для Windows, для параметра redirect_uri можно использовать идентификатор безопасности пакета. Чтобы открыть диалог входа, вызовите WebAuthenticationBroker.AuthenticateAsync и используйте конечную точку диалога входа в качестве значения requestUri. Вот пример такой реализации на JavaScript:

var requestUri = new Windows.Foundation.Uri(
  "https://www.facebook.com/v21.0/dialog/oauth?
    client_id={app-id}
    &display=popup
    &response_type=token
    &redirect_uri=ms-app://{package-security-identifier}");

Windows.Security.Authentication.Web.WebAuthenticationBroker.authenticateAsync(
  options,
  requestUri)
  .done(function (result) {
    // Handle the response from the Login Dialog
  }
);

Управление возвращается в приложение с маркером доступа в случае успеха или ошибкой в случае сбоя.

Обработка ответа диалога "Вход"

На этом этапе в процессе входа пользователь видит диалог входа и может выбрать отмену или разрешить приложению доступ к своим данным.

Если пользователь нажимает кнопку "ОК" в диалоге входа, он предоставляет приложению доступ к своему общедоступному профилю, списку друзей, а также дополнительные разрешения, которые оно запросило.

Во всех случаях браузер возвращает управление приложению, а ответ содержит сведения о том, вошел ли пользователь или отменил вход. Если приложение использует описанный выше метод перенаправления, к значению redirect_uri, которое возвращает приложение, добавляются параметры или фрагменты URL (в зависимости от выбранного значения response_type), которые необходимо принимать.

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

Клиентский код на JavaScript может извлекать из строки фрагменты URL (например, jQuery BBQ), а параметры URL можно отслеживать как в клиентском, так и в серверном коде (например, $_GET в PHP, jQuery.deparam в jQuery BBQ, querystring.parse в Node.js или urlparse в Python). Корпорация Microsoft предоставляет руководство и пример кода для приложений Windows 8, которые подключаются к онлайн-поставщику (в данном случае к Facebook).

При входе через приложение для компьютера Facebook перенаправляет пользователя на указанный выше адрес redirect_uri и добавляет во фрагмент URI маркер доступа, а также некоторые другие метаданные (например, время истечения срока действия маркера):

https://www.facebook.com/connect/login_success.html#
    access_token=ACCESS_TOKEN...

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


Отмена входа

Если пользователь приложения не принимает диалог входа и нажимает кнопку "Отмена", он перенаправляется на следующий адрес:

YOUR_REDIRECT_URI?
 error_reason=user_denied
 &error=access_denied
 &error_description=Permissions+error.

Дополнительные сведения о том, что должны делать приложения, когда пользователи отказываются от входа, см. в этом разделе.

Подтверждение личности

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

  • Если получен code, его необходимо обменять на маркер доступа, используя конечную точку. Соответствующий вызов должен производиться от сервера к серверу, поскольку содержит секрет вашего приложения. Секрет приложения ни в коем случае не должен попасть в клиентский код.
  • Если получен token, его необходимо проверить. В этом случае нужно выполнить вызов API к конечной точке проверки и уточнить, для кого и каким именно приложением был сгенерирован маркер. Поскольку для этого вызова API необходим маркер доступа приложения, его нельзя выполнять из клиента. Такой вызов должен выполняться с сервера, где можно безопасно сохранить секрет приложения.
  • Если получены как code, так и token, необходимо выполнить оба этих шага.

Обратите внимание: вы также можете сгенерировать собственный параметр state и использовать его со своим запросом входа, чтобы обеспечить защиту от межсайтовой подделки запросов.

Обмен кода на маркер доступа

Чтобы получить маркер доступа, отправьте HTTP-запрос GET на следующую конечную точку OAuth:

GET https://graph.facebook.com/v21.0/oauth/access_token?
   client_id={app-id}
   &redirect_uri={redirect-uri}
   &client_secret={app-secret}
   &code={code-parameter}

Обязательные параметры этой конечной точки:

  • client_id. ID вашего приложения.
  • redirect_uri. Этот аргумент является обязательным, и его значение должно совпадать с исходным значением request_uri, который использовался для запуска процесса входа OAuth.
  • client_secret. Ваш уникальный секрет приложения, отображаемый в Панели приложений. Никогда не используйте его в клиентском коде или двоичных файлах, которые можно декомпилировать. Крайне важно хранить это значение в полном секрете: оно лежит в основе безопасности вашего приложения и его пользователей.
  • code. Параметр, полученный от перенаправления диалога входа выше.

Обратите внимание: начиная с версии 2.3 эта конечная точка возвращает корректный ответ JSON. Если в вашем вызове не указана версия, по умолчанию будет использоваться самая старая из доступных.

Ответ

В случае успеха вы получите от конечной точки следующий ответ в формате JSON:

{
  "access_token": {access-token}, 
  "token_type": {type},
  "expires_in":  {seconds-til-expiration}
}

В противном случае вы получите сообщение об ошибке с объяснением причин.

Проверка маркеров доступа

Независимо от того, использует ли ваше приложение code или token в качестве response_type от диалога входа, оно получит маркер доступа. Для автоматической проверки таких маркеров можно использовать конечную точку API Graph:

GET graph.facebook.com/debug_token?
     input_token={token-to-inspect}
     &access_token={app-token-or-admin-token}

Эта конечная точка принимает следующие параметры:

Ответом на вызов API будет массив JSON с данными о проверенном маркере. Пример:

{
    "data": {
        "app_id": 138483919580948, 
        "type": "USER",
        "application": "Social Cafe", 
        "expires_at": 1352419328, 
        "is_valid": true, 
        "issued_at": 1347235328, 
        "metadata": {
            "sso": "iphone-safari"
        }, 
        "scopes": [
            "email", 
            "publish_actions"
        ], 
        "user_id": "1207059"
    }
}

С помощью полей app_id и user_id приложение проверяет, действителен ли маркер доступа для пользователя и для самого приложения. Полное описание других полей см. в руководстве по получению информации о маркерах доступа.

Проверка разрешений

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

Повторный запрос отклоненных разрешений

Вход через Facebook позволяет людям отказаться от предоставления определенных разрешений. Диалог "Вход" содержит экран, который выглядит примерно так:

Разрешение public_profile требуется всегда. Оно показано серым цветом, потому что его нельзя отключить.

Однако если бы пользователь в этом примере снял флажок user_likes (отметки "Нравится"), результат проверки /me/permissions на предмет того, какие разрешения были предоставлены, был бы следующим:

{
  "data":
    [
      {
        "permission":"public_profile",
        "status":"granted"
      },
      {
        "permission":"user_likes",
        "status":"declined"
      }
    ]
}

Обратите внимание, что разрешение user_likes не предоставлено, а отклонено.

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

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

Добавьте в URL диалога входа параметр auth_type=rerequest:

https://www.facebook.com/v21.0/dialog/oauth?
    client_id={app-id}
    &redirect_uri={redirect-uri}
    &auth_type=rerequest
    scope=email
   

В результате диалог входа будет заново запрашивать отклоненное разрешение.

Сохранение маркеров доступа и статуса входа

На этом этапе пользователь уже прошел проверку подлинности и вошел в приложение. Приложение готово отправлять вызовы API от его имени. Однако перед этим оно должно сохранить маркер доступа и статус входа пользователя.

Сохранение маркеров доступа

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

Подробнее о размере маркеров доступа см. в этом разделе.

Отслеживание статуса входа

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

Выход из приложения

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

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

Обнаружение удаления приложений

Люди могут удалять приложения через Facebook.com без непосредственного взаимодействия с ними. Чтобы приложения могли отслеживать такие операции, они могут предоставлять URL обратного вызова для отмены авторизации, который вызывается при наступлении такого события.

Включить обратный вызов для отмены авторизации можно в панели приложений.

Реагирование на запросы об удалении пользовательских данных

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