2015年6月20日 星期六

使用parse.com Cloud Code Hosting進行Facebook登入存取 - 2

延續上一篇,成功使用facebook登入parse.com的使用者資訊後,接著就是怎麼從使用者資訊中取得facebook的資料了。

以上圖的Facebook Test Users為例,建立完的使用者可以由parse.com的Data中看到,不過authData卻只顯示了Facebook的ID,因此我們可以先透過API Console來對users作存取,這裡要注意的是Use Master Key記得要選Yes,否則會沒有權限看authData的內容;users後面的參數為objectId,若不放置則會列出全部符合的資料。
 在Response中的內容:
{
  "authData": {
    "facebook": {
      // 不要想對這組access_token亂來,因為是test user XD
      "access_token": "CAAMCk3Pv7SkBAEjfvRaG4SrC8k3CXak1843iisuUJiIK9gYV9PNFRraXi9gxYVBJO83zsvzFO91dcACevKwinxAVPNCUeEv0UPWsmv7DZBlqPjtZCCnEBcMBKpU7ikoj9OKo1ZCwzi3wmTycsB2avHT1SiBxLUF5ZAHTaT9XDNtz1phGZCk0lltOY5agj0JGQ9ezNGmOsvUmdpKFASx5K",
      "expiration_date": "2015-08-15T17:52:46.495Z",
      "id": "118563748477765"
    }
  },
  "createdAt": "2015-06-16T17:52:48.623Z",
  "name": "Super Mario",
  "objectId": "wmVm7Qb1Fc",
  "sessionToken": "jEKKzfbDcIN0CmBIvsdZR9Aoc",
  "updatedAt": "2015-06-17T07:57:08.934Z",
  "username": "3GwDpgmuqmfnyGYINNI27W9fO"
}
已經知道存放在哪裡之後,接下來就是利用cloud code function建立資料存取了!在這裡我用名字與圖片作範例,參考了stackoverflow這篇的回答稍微修改了一下:
當然,別忘記userMasterKey...

Parse.Cloud.define("facebook", function(request, response) {
  Parse.Cloud.useMasterKey();
 
  new Parse.Query(Parse.User).get(request.params.user_id).then(function(user) {
    var authData = user.get("authData");
 
    // Quit early for users who aren't linked with Facebook
    if (authData === undefined || authData.facebook === undefined) {
      response.success(null);
       return;
    }
 
    return Parse.Cloud.httpRequest({
      method: "GET",
      url: "https://graph.facebook.com/me",
      params: {
        access_token: authData.facebook.access_token,
        fields: "name, friends",
      },
    });
 
  }).then(function(json) {
    response.success(json.data);
 
  // Promises will let you bubble up any error, similar to a catch statement
  }, function(error) {
    response.error(error);
  });
});
在Express中call建立好的cloud host function:
app.get('/test', fbLogin, function(req, res) {
  var user = Parse.User.current();
  Parse.Cloud.run('facebook', { user_id: user.id }, {
    success: function(results) {
      res.send('Congrats, you are logged in, ' + results.name + '!' +  '');
    },
    error: function(error) {
      console.log("error :" + error);
    }
  });
});
若是成功的話就能在自己的URL中看到如下圖的結果了!

UPDATE:使用parse.com Cloud Code Hosting進行Facebook登入存取 - 3

使用parse.com Cloud Code Hosting進行Facebook登入存取 - 1

parse.comJavascript SDK中提供了使用者的存取,其中包含Facebook的整合,但Javascript終究是前端,有些不想讓client end知道的還是放在後端處理比較好。然而parse.com所提供的cloud code所使用的目前雖是node.js,會讓開發者很想直接把Javascript SDK的Facebook部分塞進去看能不能跑,乍看之下很合理,但實際上就是不行,因為以parse.com Javascript SDK在要求登入時會跳出另一個瀏覽器視窗以要求登入facebook及權限給予,而這個視窗當然沒有辦法在server end中呈現並要求client end進行認證。

在官方論壇上也有人發表過此問題:Interacting with the Facebook API in Cloud Code
所得到的回答是:
Unfortunately, the Facebook JavaScript SDK is not made to work outside of a browser, so using it directly from Cloud Code is not supported at the moment.

You can, however, get the authData from the current user in cloud code and use that to make a REST call to Facebook's graph API manually.

因此我轉而研究使用OAuth方式來登入Facebook,除了跳轉出的頁面比較美觀外(不會產生另一個瀏覽器視窗),也不用擔心暴露資訊給clent end,參考資料有這兩篇:
網站利用 Facebook 帳號登入 (使用 OAuth)
10分鐘理解OAuth和facebook登入原理
這篇以python Django framework實作,其實看code好像也蠻容易理解的:Ghetto Facebook Registration with Django

後來正當我開始打算實作時,我找到了parse-facebook-user-session,原來parse.com早就把這個寫好了,根本不用自己去寫了,只需要按照他的說明一步一步來就行了(吧)!

結果證明事情果然不是我想的這麼簡單,不管怎麼弄就是跳出209 invalid session token,花了一段時間後找到parse.com自己發的文章Session Migration Tutorial,才知道把這個選項關掉就行了,我花了這麼久到底在幹麻!

總之,關閉這個選項後就成功了,parse.com的資料庫也會成功紀錄登入過的使用者,事情完成一半,其餘的就是登入的使用者資料該怎麼讀取出來了~

UPDATE:使用parse.com Cloud Code Hosting進行Facebook登入存取 - 2

UPDATE:在GitHub上新增了範例程式:demo, GitHub