Help us understand the problem. What is going on with this article?

iPhoneでFacebook認証したTokenをNode.jsのサーバで受けてサーバ側で認証してみる

More than 5 years have passed since last update.

はじめに(ごめんなさい的な)

自分なりにいろいろ調べてやってるんですが、もっと効率的な方法はある気がしてます。
そもそも間違っているところもあるかもしれないので、気づかれた方は是非ツッコミをお願いします。

やりたいことのイメージ

やりたいことはこれ。

  • iPhoneアプリをFacebook認証を使って使用させたい。
  • Facebook認証の後、アプリ操作でFacebook友達情報を取得したり、その友達とのつながりを使った機能を提供したい。

ちょっと図示してみました。
この記事でのポイントは、下記のです。
Facebook認証の話なんかは他にもいっぱいあるので、特に触れません。
(ただ、やってるときにFacebook SDKのバージョンが上がっちゃって面倒だったけど…)

figure.png

①iPhoneアプリ上で、Facebook SDKを使ってAuth Requestを送信
②FacebookからAccess Token(図中はAuthToken)を受け取る
③取得したAccess Token(図中はAuthToken)をサーバ(Node.js)に送信
④受け取ったAccess Tokenを使って、iPhoneユーザの情報を取得するようFacebook graphにリクエストする
⑤Facebookからユーザ情報を受け取る

AccessTokenは同一アプリの範疇なら使い回しOKなので、この方法で認証してみたいと考えました。

サーバ側の実装で困っていたこと

これはただ自分が無知ゆえに困っちゃってたんですが。。

Node.jsはノンブロッキング処理でポンポン進んじゃうわけで、
④のFacebook Graph APIにアクセスしたときに、⑤が返ってくる前に先に進んでしまう。
Callback関数の使い方とか、いまいちちゃんとわかっていない証拠ですな。

試行錯誤して次のような実装にしました。

サーバ(Node.js側)の実装

asyncモジュールのseries、といっても1個だけなんですが、
⑤が返ってくるまで待つようにしたつもりです。実際、下記でちゃんと取れています。

なお、Facebook Graph APIのアクセスにはHTTPアクセスをするのにいろんな方法があるっぽいが、
requestモジュールを使いました。
(返って深くなっちゃう理由になった気もしますが。。。)

var async = require('async');

var accessToken = "FACEBOOKのACCESS_TOKEN";

async.series([
    function(callback) {
        var qs = require('querystring');
        var request = require('request').defaults({strictSSL:true});

        debug('ACCESS_TOKEN: ' + accessToken);

        var apiUrl = 'https://graph.facebook.com/v2.3/me?' +
            qs.stringify({ access_token: accessToken });

        var options = { url: apiUrl, json: true };

        request.get(options, function(err, resp, data) {
            if(err) {
                // (1) Error handling
                debug('ERROR');
                callback(err, null);
            } else if(resp.statusCode !== 200) {
                // (2) Unsuccessful handling
                debug('UNSUCCESSFUL');
                callback(new Error('Unsuccessful'), null);
            } else {
                // (3) SUCCESSFUL
                debug('SUCCESSFUL');
                callback(null, data);
            }
        });
    }
],function(err, results) {
    if(err) {
        //Case in (1) and (2)

        //[A] ERROR PROCESS
    } else {
       //Case in (3)

       //[B] SUCCESSFUL PROCESS
    }
});

(1)はrequest.get()処理のなかでエラーが起きた状態。
(2)はちゃんと答えが返ってきたけど、ResponseCode:200以外なので、APIから期待する結果が返ってこない状態。
(3)は期待通りの答えが得られている状態。

(1),(2)はエラーの類として[A]で処理をします。
(3)のみが正常系として[B]で処理されます。

そんな流れです。

課題というか、理解不足

要はAPIからResponseが返ってきたら次にいくような同期処理だったらいいわけなんですが、
requestモジュールを使うと、すでに非同期で取ってくるので全体として非同期になってしまいます。

本来Nodeのいいところは、イベント駆動・ノンブロッキング処理ができるところだという理解なんですが、
これをうまく制御できないと、いいところがうまく生かせないもんね。

もっとちゃんと勉強していきたいと思います。

※自身の理解度確認も含めてこの記事を書いています。しつこいようですが、謝りに気づかれた方は是非ご指摘いただけると幸いです。

yosi-q
インド資本の入った米国クラウドコンサルティングファームの東京オフィスに所属し、山形県鶴岡市からリモートワークしながら、ちょっとしたwonder探ししてます。 Qiitaは記録も含めてやったことをちょこちょこ残しています。 ここで記載した記事は私感や私自身の実施した内容の記録として記載しており、所属する組織とは関係ありません。
http://yosi-q.me
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした