Backend-авторизация в facebook через OAuth 2.0

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

{
   "id": "712392972",
   "name": "Pov",
   "first_name": "Po",
   "last_name": "V",
   "link": "http://www.facebook.com/pov",
   "about": "http://pov.gov",
   "verified": true,
}

Впрочем проблем с прошлого раза не убавилось и каша как со стандартами, так и с документацией остаётся — API меняется так часто, что документация в wiki не поспевает, интернет полон старых решений и разобраться в элементарных вещах не так то просто.

Связка

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

  1. Ставим URL приложения. Копируем appId и secret к себе в код — это наш ключ приложения (consumer key)
  2. Проверяем в приложении есть ли у нас сохранённый где-то access key и если нет то редиректимпользователя на https://graph.facebook.com/oauth/authorize с параметрами
    • client_id — приложение
    • redirect_uri — куда вернуться
    • scope — прав, мне к примеру понадобятся постоянный доступ и создание событий (offline_access, create_event)
  3. Пользователь получает диалог, подтверждает и возвращается к нам с code параметром — ключём запроса, который мы обменяем на ключ доступа (access key) по https://graph.facebook.com/oauth/access_token, передав следующие данные…
    • client_id
    • client_secret
    • code
    • redirect_uri
    • Если вы передадите ещё и type=client_cred то ключ доступа будет урезанным (вида 134790075639751|e9PC-PhvPnOvlVbgbLmITd24hnQ) и вы будете действовать не столько от имени пользователя, сколько от имени приложения. Поэтому лучше этот параметр не указывать и получать полный ключ (вида  134790075639751|ad22e11d67b06933774e26da-712393972|D8PoAPDdvv8onIAf_CasljjK7Pk )

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

if(!$token){
    if($_REQUEST['code']){
        $token = file_get_contents('https://graph.facebook.com/oauth/access_token?client_id='.CONSUMER_KEY.'&client_secret='.CONSUMER_SECRET.'&code='.$_REQUEST['code'].'&redirect_uri='.CONSUMER_URL);
    }
    else header('Location: https://graph.facebook.com/oauth/authorize?client_id='.CONSUMER_KEY.'&scope=offline_access,create_event,publish_stream,user_events&redirect_uri='.CONSUMER_URL);
}

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