Оптимизируем запросы к Facebook Graph API с помощью Real-Time Updates

    Приложения для Facebook могут иметь разнообразный функционал: например, часто приложению будет достаточно информации, полученной через API, во время работы пользователя с приложением. Но что делать, если ваше приложение должно работать с самыми “свежими” данными пользователе, даже если они не открывали его уже больше месяца?

    Есть два способа для того, чтобы получать данные не только во время работы пользователя с приложением:
    1. Получить от пользователя offline_access permission (сохранить “вечный” пользовательский access_token) и получать необходимые данные “по расписанию” (дергать скрипт cron-ом).
    2. Написать скрипт, который будет получать все изменения данных от Facebook, настроить и подписаться на обновления через Real-Time Updates.

    Под катом вы узнаете виртуальный пример, как использование real-time updates помогает сократить за день количество запросов к API более чем в 100 раз в некоторых ситуациях. Мы напишем скрипт подписки на обновления и проверим его работу, получив данные о изменении объектов от самого Facebook.

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

    Первый способ


    Функционал некоторых приложений может быть связан с необходимостью получать данные по расписанию. Например, вы собираете статистику количества лайков страниц из определенного каталога. Для этого вы получаете данные с периодичностью раз в час. Это правильный пример использования, по другому вы эти данные просто не получите. Но часто этот способ применяют и для объектов, по которым обновления можно получать не “по расписанию” а real-time от самого Facebook.

    Из серьезных недостатков первого способа можно выделить следующие:
    • Чем реже проверяются данные, тем меньше их достоверность.
    • Высокие затраты ресурсов при частом обновлении.
    • Пользователи с неохотой разрешают offline_access — доступ в любое время к их данным.

    Представьте что вы сделали приложение, функционал которого завязан на друзьях пользователя, и вам очень важно иметь самую свежую информацию. Допустим ваше приложение установили 1000 пользователей. И пусть приемлемым временем кеширования данных о друзьях будет 1 час. В итоге каждый день вы будете отправлять 24000 запросов для того, чтобы ваша база данных о друзьях пользователя была актуальна! А у вас всего 1000 пользователей, и можно предположить, что изменений в друзьях на всех за день будет не больше пары сотен (ну это догадка, основанная на личном опыте).

    Чтобы решить недостатки первого способа, Facebook сделал Real-Time Updates для своего Graph API.

    Второй способ


    Поддержка обновлений в реальном времени позволяет вашему приложению подписаться на изменения в данных в Facebook. Ваше приложение получает обновления от Facebook и сохраняет данные, вместо того, чтобы опрашивать серверы Facebook “по расписанию”. Кэширование данных и использование этого API могут улучшить надежность приложения и уменьшить его время загрузки. Всякий раз, когда происходит изменение на которое вы подписаны, Facebook делает HTTP POST запрос к скрипту обработки обновлений данных со списком изменений. Сервер пошлет вам уведомление об изменении в течение пары минут после его появления.

    Объекты

    На данный момент вы можете подписаться на следующие типы объектов:
    • user (пользователь) — получать уведомления о конкретных полях и связях пользователя с соответствующими узлами Graph API.*
    • permissions (разрешения) — получать уведомления когда пользователь изменяет разрешения для вашего приложения.
    • page (страница) — получать уведомления когда страницы, которые добавили (установили) ваше приложение, изменяют их общие свойства.

    * Не на все свойства и связи объекта User вы сможете подписаться. Например, вам доступны связи: feed, friends, activities, interests, music, books, movies, television, likes, checkins. Но при этом подписаться на изменения этих связей вы пока не сможете: home, tagged, posts, photos, albums, videos, groups, notes, events, inbox, outbox, updates, accounts

    Подписка

    Для того, чтобы настроить подписку на обновления, вам нужно:
    1. Настроить скрипт (URL) который будет получать как HTTP GET (для верификации подписки) так и POST (о изменении данных) запросы от Facebook.
    2. Сделать запрос POST к Graph API
      https://graph.facebook.com/<app-id>/subscriptions
      чтобы подписаться, и быть готовым к обработке запроса верификации.

    Отправив запрос на
    https://graph.facebook.com/<app-id>/subscriptions?access_token=...
    вы можете делать три вещи, смотря какой запрос HTTP POST, GET, or DELETE вы посылаете:
    1. Добавить и изменить подписку (POST).
    2. Получить список из всех объектов а также их поля, на которые вы подписались (GET)
    3. Удалить подписку (DELETE)

    В запрос должен быть включен access_token приложения, который можно получить, используя ID вашего приложения (app-id) и секретный ключ приложения (app-secret). Просто отправьте HTTP GET
    https://graph.facebook.com/oauth/access_token?client_id=<app-id>&client_secret=<app-secret>&grant_type=client_credentials
    и в ответе придет: access_token=…

    Добавление и изменение подписки

    Итак, вы прочитали выше куда нужно отправлять запрос для добавления подписки. Не спешите сразу выполнять эти запросы — структура изложения материала не такая, как последовательность нужных шагов. Сделано это специально, чтобы изучать материал последовательно. А вот в примере вы будете первыми выполнять запросы, которые описаны в последней части перед примером.


    Приложение может иметь только одну подписку на каждый из возможных типов объектов. Если вы добавляете объект, на который уже есть подписка, то существующая подписка будет заменена на новую. Чтобы добавить или изменить подписку, вы должны отправить POST запрос, содержащий поля:
    • object — тип объекта: user, permissions или page. Вы будете мониторить все объекты этого типа, например, всех пользователей вашего приложения.
    • fields — Список (элементы разделены запятыми) свойств и связей выбранного объекта. Например, чтобы следить за изменениями в полях name, picture, friends пользователя, а также связи News Feed, вы должны указать значение “name,picture,friends,feed”
    • callback_url — URL на который Facebook будет отправлять изменения, на которые подписано приложение.
    • verify_token — “секретный код”, который вы задаете для того, чтобы проверить подлинность запроса. Он будет передан в скрипт, обрабатывающий подписку.

    Получение списка из всех объектов а также их поля, на которые вы подписались
    Сделав GET запрос на URL подписки
    https://graph.facebook.com/<app-id>/subscriptions?access_token=...
    вы получите ответ с JSON-encoded контентом, который перечисляет ваши подписки. Я подписался на связь friends объекта user, а также на offline_access в permissions. Вот как выглядит ответ:
    {
      "data": [
         {
            "object": "user",
            "callback_url": "http://millione.tv/<путь до скрипта>",
            "fields": [
               "friends"
            ],
            "active": true
         },
         {
            "object": "permissions",
            "callback_url": "http://millione.tv/<путь до скрипта>",
            "fields": [
               "offline_access"
            ],
            "active": true
         }
      ]
    }
    

    Удаление подписки

    Чтобы удалить всю подписку на все объекты, отправьте DELETE запрос. Если вы хотите удалить подписку на конкретный объект, укажите параметр object (например, object=user).

    Ваш Callback сервер


    Сервера Facebook делают HTTP GET запрос на ваш callback_url когда вы пытаетесь добавить или модифицировать подписку. После успешной подписки, сервера Facebook будут отправлять уведомления о изменениях, используя HTTP POST, на тот же URL.

    Верификация подписки

    До того как подписка будет окончательно добавлена или модифицирована, сервера Facebook сделают HTTP GET на ваш callback_url со следующими параметрами:
    • hub.mode — Строка ‘subscribe’ передается в этом параметре.
    • hub.challenge — Случайная строка.
    • hub.verify_token — “секретный код”, который вы задаете для того, чтобы проверить подлинность запроса, который вы передали Facebook.

    Скрипт обработки обновлений данных должен первым делом проверить значение hub.verify_token — “секретный код”, который вы передали в Facebook, а потом вернуть обратно параметр hub.challenge. Это сделано специально, чтобы оградить скрипт как средство проведения DDoS атаки на сервер.
    Примечание для разработчиков: В PHP, точка конвертируется автоматически в подчеркивание в параметрах. Поэтому вы должны обращаться к $_GET["hub_mode"], $_GET["hub_challenge"] и $_GET["hub_verify_token"].

    Уведомления об изменениях

    Когда данные изменяются, и есть валидная подписка, сервера Facebook делают HTTP POST запрос на callback_url, который вы задавали. Тип контента запроса будет application/json; тело — JSON-encoded строка, содержащая информацию об одном или нескольких изменениях. Пример можно будет посмотреть ниже в коде приложения.

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

    Facebook агрегирует изменения и отправляет их пакетами каждые 5 секунд, или если количество произошедших изменений превысило 1000. В случае, когда уведомление о изменении не было доставлено к вам, Facebook повторит попытку заново, а затем немного позже, уменьшая частоту запросов в следующие 24 часа.

    Пример работы Real-Time Updates


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

    1. Приложение



    2. Скрипт обработки обновлений данных

    Сохраните скрипт для callback_url
    <?php
     
    /* Note the request must complete within 15 seconds.
    Otherwise Facebook server will consider it a timeout and
    resend the push notification again. */

     
    define('VERIFY_TOKEN', '<secret_code>');
    $method = $_SERVER['REQUEST_METHOD'];
     
    if ($method == 'GET' && $_GET['hub_mode'] == 'subscribe'  
                         && $_GET['hub_verify_token'] == VERIFY_TOKEN) {
       echo $_GET['hub_challenge'];
    } else
       if ($method == 'POST') {
           $data = file_get_contents("php://input");
           $fh = fopen('data.txt','a') or die('open file');
           if (-1 == fwrite($fh, $data)) { die('write data'); }
           fclose($fh) or die('close file');
       }
     
    ?>


    3. Добавляем подписку

    После этого воспользуемся новым инструментом для разработчиков Facebook — Graph API Explorer.


    Выберите POST запрос чтобы добавить подписку и заполните все поля. Чтобы получить access_token (приложения), откройте в браузере ссылку, заполнив app-id и app-secret данными вашего приложения.
    https://graph.facebook.com/oauth/access_token?client_id=<app-id>&client_secret=<app-secret>&grant_type=client_credentials

    Путь до скрипта может быть facebook/callback.php например. Важно, что app-secret вы берете из настроек приложения, а секретный код в verify_token вы придумываете сами!

    Итак, если после нажатия Submit в сером поле внизу ничего не произошло, значит вы все-таки добавили подписку на связи friends объекта user, и теперь как только любой пользователь вашего приложения добавит или удалил кого-то из друзей — Facebook отправит на callback_url вам уведомление. Я своем примере я добавил подписку еще и на offline_access объекта permissions.

    4. Создаем активность пользователя

    Если у вас ваше приложение было установлено — ничего страшного. Если нет — тоже. Последовательность действий одинаковая.

    Сначала нужно добавить разрешение offline_access. Если приложение не было установлено — это произойдет автоматически. У меня приложение не установлено. Попробую вызвать окно авторизации через строку браузера. Откройте ссылку, заменив в ней app-id на id вашего приложения, и заменив site-url на http://<ваш домен>:
    https://www.facebook.com/dialog/oauth?client_id=<app-id>&redirect_uri=<site-url>&scope=offline_access



    После удачной авторизации Facebook редиректит вас на http://<ваш домен>/?code=…

    По логике, которая содержится в скрипте — при обработке входящего уведомления мы просто добавляем переданную JSON-encoded строку в текстовый файл data.txt, который будет находиться в одной директории со скриптом. Проверьте, создался ли этот файл и какую информацию он содержит.

    У меня добавленная информация выглядит так:
    {"object":"permissions","entry":[{"uid":"100001828786121","id":"100001828786121","time":1310669052,"changed_fields":["connected"]},{"uid":"100001828786121","id":"100001828786121","time":1310669052,"changed_fields":["offline_access"]}]}

    Как видно — я и установил приложение, и разрешил offline_access permission. По uid вы можете определять пользователя у которого изменились данные, а по time — время добавления.

    5. Действия при удалении

    Вы можете зайти в настройки приложений на Facebook, открыть ваше приложение и удалить разрешение offline_access. В файле data.txt вы увидите, что вам опять прислали уведомление. Можете также добавить или удалить кого-то из друзей — вы увидите что и эти уведомления, на которые вы подписались, будут приходить на callback_url и обрабатываться вашим скриптом.

    Выводы

    Теперь вы знаете о замечательной возможности Facebook Real-Time Updates, которая может присылать вам информацию о изменениях данных пользователя и разрешений. К сожалению, почему-то при удалении пользователем приложения данные не изменились. Поэтому как бы новый способ не экономил время и ресурсы — все-таки при реализации определенных задач (например, отправка почтовой рассылки всем пользователям приложения) еще стоит предварительно обходить через обычное API всех пользователей в вашей базе данных, проверяя, установлено ли у них ваше приложение.

    Комментарии 55

      +5
      В следующей статье опишу как оптимизировать запросы к Facebook Graph API для первого способа: с помощью Batch API и работы ассинхронных сокетов на PHP. У меня время загрузки данных от 1000 запросов к API сократилось до 20 секунд. При обычном переборе это бы заняло более 15 минут.
        +1
        Статья разделяет типичное заблуждение: для получения пользовательских данных НЕ НУЖЕН offline_access

        Если вам просто нужны данные — то берёте их просто и получаете, как обычно. offline_access нужен, если вы хотите выполнять действия от имени пользователя
          0
          а можно ли без offline_access получить «вечный» access_token?
            0
            А зачем вам вечный access_token?

            Информация доступна и при обычных сессионных токенах, согласно пермишнов, которые вы попросили у пользователя при авторизации.
              0
              Об этом и написана статья, ведь если аппликации нужно постоянно работать с актуальными данными юзеров (даже в тот момент когда юзер не использует аппликацию), то нет никаких других способов, так как без offline_access нет актуального токена для доступа к пользовательским данным.
                0
                Эм, с чего вы это взяли?

                Пользовательские данные (которые он разрешил отдавать приложению) вполне доступны без offline_access и «вечных» токенов.
                  0
                  то есть при устаревании access_token'а его обновление не требует никаких подтверждений от пользователя?
                    +3
                    Эм.

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

                    В начале каждой сессии работы с FB API вы просто получаете новый токен и работаете с ним. По этому токену — апи понимает, что это ваше приложение. А у них в системе авторизации как раз и хранится, к каким пользователям какой доступ у вас есть.

                    После этого вы берёте и просто выполняете запрос нужной информации, подписывая запрос текущим сессионным токеном.
                      0
                      спасибо!
                        0
                        Так про это и речь, что допустим нет у меня никакой сессии, юзер воопще уже месяц не заходил в аппликацию, а мне позарез нужены его актуальные данные. Тут нет никакого выбора как использовать либо offline_access, либо realtime update.
                          +2
                          Вы ошибаетесь.

                          graph.facebook.com/oauth/access_token?
                          client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&
                          client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE


                          Вот так вы получаете актуальный access_token, суть сессионный. С его помощью у вас есть доступ ко всем данным, которые пользователи разрешили вам просматривать.

                          OAuth — это авторизационный протокол. Всё, что вам когда-либо было разрешено и до сих пор не запрещено вы можете получить, имея актуальный (живой) access_token.
                            0
                            >>code=THE_CODE_FROM_ABOVE
                            Откуда этот код взять?
                              0
                              developers.facebook.com/docs/authentication/ — вот тут всё в деталях описано
                                0
                                Ага, там в деталях описано, что этот код получается от юзера. Он его «приносит» с собой после аутентификации в фейсбуке. А если юзера не было месяц, то и кода нет.
                            0
                            Кстати, увидел запрос и понял, что вы же получили access_token от приложения. В запросе нет ни одного параметра, который бы был уникален для каждого конкретного пользователя. Поэтому если продолжать разговор о вечном acces_token пользователя, полученным с помощью offline_access permission — это разные вещи.
                              0
                              Приведите пример этой разницы? Какую именно информацию из статьи вы не смогли бы получить без offline_access?

                              (этот грант — очень серьёзный, и я бы никогда без реальной необходимости его не запрашивал)
                                0
                                Я скажу даже больше — в моём коде приложение вообще никаких токенов от FB API не получает. Единственный токен который используется — сгенерирован кодом и выглядит как «appid|secret».

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

                                0
                                Упс, отправилось случайно

                                через developers.facebook.com/tools/explorer

                                Не давайте оффлайна. Получите токен и читайте инфу.
                                  0
                                  Может я чего-то недопонимаю, тогда у меня пару вопросов…

                                  Ваш пример запроса сверху возвращает токен самой аппликации и вы хотите сказать, что с помощью него я смогу получать все данные юзера которые разрешено видеть этой аппликации? Если так, то тогда я воопще не понимаю зачем нужен offline_access. Не просто же так его придумали?
                                    0
                                    Дайте мне тогда минут 10 чтобы состряпать пример.

                                    По поводу «зачем» — написал ниже habrahabr.ru/blogs/facebook/124195/#comment_4082310

                                    Честно — не знаю. Но он мне не требовался никогда.
                                      0
                                      pastebin.com/yCcLrut7

                                      Как пользоваться им:

                                      1. Стягиваете php.sdk, кладёте его рядом с example.php
                                      2. Прописываете свои appid + secret
                                      3. Запускаете скрипт
                                      4. Переходите по login
                                      5. Авторизуете
                                      6. Сбрасываете кэш/открываете в другом браузере и убеждаетесь, что можете получить информацию

                                      ps: в 20 и 24 строках — просто подмените на свой nickname или uid
                                        0
                                        Бррр, сбрасываете кэш == сбрасываете куки
                                          0
                                          После того как вы авторизируете приложение, то по ссылке login вас сначала направят в фейсбук, а от туда будет сразу редирект обратно с токеном.
                                            +1
                                            Всё верно. Один раз пользователь должен авторизовать приложение. После этого пользователь может не ходить в ваше приложение никогда вообще, но права у вашего приложения так и останутся.

                                            И все данные ваше приложение получит и без пользовательской сессии.

                                            Собственно это мой код и делает.
                                              0
                                              Пользовательская сессия (access_token) по-умолчанию имеет короткое время жизни, и пользователь должен её обновлять, без него Вы сами не сможете её обновить.
                                              Чтобы сессия имела долгое время жизни, необходимо получить offline_access — именно это написано в доке.
                                              Это я хотел объяснить.
                                                0
                                                Опять двадцать пять.

                                                Зачем вам нужен долгоживущий токен? Пользовательская информация доступна и без него.

                                                Я могу вам сейчас даже в скайпе зашарить экран и показать простой пример, если вы мне до сих пор не верите :-) мой uid есть в профиле
                                        0
                                        Выполняю последовательность:
                                        1. Захожу на developers.facebook.com/tools/explorer/
                                        2. Получить access_token
                                        3. Разрешаю (права стандартные).
                                        4. Запрос "/me" — получаю инфу о себе (убеждаюсь, что токен привязан к пользователю, id пользователя кстати есть в токене).
                                        5. Выхожу из фейсбука (логаут).
                                        6. Опять "/me" — ошибка.
                                        7. Захожу в фейсбук.
                                        8. Запрос "/me" — ошибка.
                                        9. Получаю access_token с правами offline_access
                                        10. Логаут
                                        11. Запрос "/me" — успешно.
                                          0
                                          Роман, я вам в третий раз даю ссылку на код habrahabr.ru/blogs/facebook/124195/#comment_4082353

                                          Пожалуйста, изучите его.

                                          Правда, повторять одно и то же более трёх раз становится уже совсем несмешно :-(
                                            0
                                            По поводу вашего эксперимента — естественно /me будет давать ошибку.

                                            А вы получайте информацию из "/username" или "/user_id". В этом случае апи вам отдаст всю информацию, в случае если пользователь авторизовал ваше приложение.
                                              0
                                              Все запросы "/me" можно заменить на "/__мой_ид__" результат будет аналогичный.
                                                0
                                                Отнюдь. Если бы вы запустили мой код выше — то вы бы увидели, что для запросов "/user_id" для авторизованного (когда угодно) пользователя без живой сессии данные получить можно.

                                                Пожалуйста, запустите код, а то разговор напоминает слепого с глухим.
                                                  0
                                                  Дайте мне ид вашего приложения, я в нем авторизуюсь, а потом вы попробуете получить мои данные :)
                                                    0
                                                    146040145421160
                                                      0
                                                      www.facebook.com/dialog/oauth?client_id=146040145421160&redirect_uri=http%3A%2F%2Ffa-cebook.zerkms.ru%2Fexamples%2Fexample.php

                                                      Вот вам даже готовый урл, без редиректа оно не даст по идее ведь авторизоваться
                                                        0
                                                        Редирект был на 404, но приложение добавилось.
                                                        Мой ид 100002546363795.
                                                        Попробуйте получить инфу.
                                                          +1
                                                          Френды:

                                                          array(1) { ["data"]=> array(12) { [0]=> array(2) { ["name"]=> string(13) "Roman Voronin" ["id"]=> string(9) "768709678" } [1]=> array(2) { ["name"]=> string(12) "Vadim Petrov" ["id"]=> string(10) "1132705230" } [2]=> array(2) { ["name"]=> string(27) "Семен Васильев" ["id"]=> string(10) "1228603568" } [3]=> array(2) { ["name"]=> string(15) "Ivan Pesochenko" ["id"]=> string(10) "1306991321" } [4]=> array(2) { ["name"]=> string(16) "Dmitry Pleshakov" ["id"]=> string(15) "100001252861042" } [5]=> array(2) { ["name"]=> string(13) "Alexey Ishkov" ["id"]=> string(15) "100001429562921" } [6]=> array(2) { ["name"]=> string(15) "Sergey Akhmetov" ["id"]=> string(15) "100001490046287" } [7]=> array(2) { ["name"]=> string(13) "Irina Grandel" ["id"]=> string(15) "100001546721562" } [8]=> array(2) { ["name"]=> string(20) "Konstantin Gorlitsyn" ["id"]=> string(15) "100001846579290" } [9]=> array(2) { ["name"]=> string(31) "Сергей Мокроусов" ["id"]=> string(15) "100001876811246" } [10]=> array(2) { ["name"]=> string(12) "Ivan Bazetov" ["id"]=> string(15) "100002016464041" } [11]=> array(2) { ["name"]=> string(16) "Maxim Volosenkov" ["id"]=> string(15) "100002520373782" } } }

                                                          Публичная часть профиля:

                                                          array(7) { ["id"]=> string(15) "100002546363795" ["name"]=> string(14) "Roman Gogolev" ["first_name"]=> string(5) "Roman" ["last_name"]=> string(7) "Gogolev" ["link"]=> string(60) "http://www.facebook.com/people/Roman-Gogolev/100002546363795" ["gender"]=> string(4) "male" ["locale"]=> string(5) "ru_RU" }
                                                            0
                                                            ok, твоя взяла
                                                            пойду положу мозги на полочку
                                                +1
                                                И напоследок — если вы внимательно прочитаете все мои комментарии, то вы увидите, что я НЕ ГОВОРИЛ что вариант с offline_access работать не будет.

                                                Я говорил, что offline_access — это избыточные права для рассматриваемой задачи и осторожные пользователи так много прав вам не дадут.
                                                  0
                                                  Я вам лишь хочу сказать, что чтобы получить данные о юзере нужен юзер, или offline_access :)
                                                    +1
                                                    Не нужен. Код выше это демонстрирует, но вам лень его запустить. Вместо этого вы пытаетесь отрицать очевидное. Дело ваше. Я умолять не буду. Считайте как хотите.
                                  0
                                0
                                Расскажите, пожалуйста, для чего тогда этот offline_token.
                                  +1
                                  Согласно описанию в developers.facebook.com/docs/reference/api/permissions/ — он необходим для выполнения действий от имени пользователя. Ни разу его не использовал, если честно, потому что и без него всё всегда доступно.
                                    0
                                    offline_access — Enables your app to perform authorized requests on behalf of the user at any time. By default, most access tokens expire after a short time period to ensure applications only make requests on behalf of the user when the are actively using the application. This permission makes the access token returned by our OAuth endpoint long-lived.

                                    Переводится примерно так:
                                    Разрешает Вашему приложению выполнять авторизованные запросы от имени пользователя в любое время. По-умолчанию, большинство access-токенов экспарятся после непродолжительного периода, чтобы быть уверынным, что приложения делают запросы от имени пользователя только когда он пользуется этим приложением. Этот пермишен делает access-токен долгоживучим.
                                      0
                                      Я могу перевести это :-)

                                      Вам вопрос — и что? :-) Я выше дал пример кода, как получить данные пользователя, не имея пользовательской сессии.
                                0
                                для фонового чтения ресурсов, на которых нет реалтайм апдейдов, например
                                  0
                                  Для каких, например, ресурсов может не хватать обычных сессионных токенов и необходим offline_access?
                                    0
                                    Например, пользователь не заходил неделю, а вашему приложению нужен его список друзей. В документации есть в связи friends запись о валидном токене. У вас токен пользователя истекает намного раньше.
                                    Согласен, токен не нужен для многих полей. Но не для всех так.
                                      0
                                      Антон, я даю ссылку на этот комментарий уже в четвёртый раз: habrahabr.ru/blogs/facebook/124195/#comment_4082353

                                      В том коде — получение френдов без offilne_access
                                        0
                                        Прости, не видел новые комментарии, пока было открыто окно. Я изучу опыт в приложении, а также посмотрю всю информацию, что же такое дает offline_access. Пока понятно что работает и то и другое.
                                          0
                                          понятно, есть два вида access_token — с сессией и для приложения. для получения первого требуется, чтобы пользователь был залогинен, второй же формируется банально как "#{appId}|#{apiSecret}" и по нему доступны не все данные, в частности получить «user_id/home» не даёт с ошибкой 'You can only access the «home» connection for the current user.', «me/home» — 'An active access token must be used to query information about the current user.'.
                                          offline_access`у всё-таки быть?
                                            0
                                            Я не отрицаю, что ситуации, когда ему быть бывают.

                                            Очевидно, что для эндпоинта home нужна сессия, потому что существует только me/home, но не uid/home.

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

                                            Именно поэтому я никогда не авторизую приложения, которым нужен оффлайн аксес :-)

                                            А то так не долго до того, что все приложения будут без разбора просить и оффлайн, и read_mailbox, чтобы читать и стену, и приватные сообщения :-)
                                          0
                                          ps: в строке с френдами написано Any valid access_token.

                                          Т.е. любой токен, которому были даны пермишны.

                                          В случае с приложением этот токен может быть банальной строкой «appid|secretid»

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

                                    Самое читаемое