ログインフローを手動で構築する

モバイルアプリの場合は、iOSおよびAndroid用のFacebook SDKを使用し、これらのプラットフォーム用の個別のガイドに従ってください。

一方、Windows 8などのネイティブデスクトップアプリ用のウェブビューや、サーバーサイドのコードを用いるログインフローのように、FacebookのSDKを使用しないブラウザーベースのログインをウェブアプリまたはデスクトップアプリに実装する必要がある場合は、ブラウザーのリダイレクトを使用して自分でログインフローを構築できます。このガイドでは、ログインフローのステップに沿って、FacebookのSDKを使用せずにログインを実装する方法を説明します。

デスクトップアプリでFacebookログインを使用するには、ログイン処理を実行するアプリ内に、ウェブブラウザー(ウェブビューとも呼びます)を埋め込む必要があります。

ログインステータスの確認

FacebookのSDKを使用するアプリは、組み込み関数により、利用者がログインしているかどうかを確認できます。それ以外のアプリはすべて、いつ利用者がログインしたかを独自の方法で格納する必要があります。ログインしたことを示すものがなければ、ログアウトしているという前提で処理を進めることになります。利用者がログアウトしている場合は、適切なタイミングで(たとえばログインボタンをクリックしたとき)、アプリによってログインダイアログにリダイレクトされます。

利用者のログイン

アプリにもFacebookにもログインしていない場合、アプリとFacebookの両方にログインするためのログインダイアログを使用できます。利用者がFacebookにログインしていない場合は、まずFacebookにログインすることを促し、その後アプリにログインするよう誘導します。これは自動的に検出されるため、この動作を可能するために特別な設定は必要ありません。


ログインダイアログの呼び出しとリダイレクトURLの設定

アプリは、ログインダイアログを表示するエンドポイントへのリダイレクトを開始する必要があります。

https://www.facebook.com/v10.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ログイン][設定]の順にクリックしてください。[クライアントOAuth設定]セクションの[有効なOAuthリダイレクトURI]を確認します。
  • state: リクエストとコールバック間の状態を維持するためにアプリによって作成される文字列の値。このパラメーターはクロスサイトリクエストフォージェリを防ぐ目的で使用され、変更されずにそのままリダイレクトURIに返されます。

たとえば、次のようなログインリクエストがあるとします。

https://www.facebook.com/v10.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パラメーターとURLフラグメントのどちらに含めるかを決めます。アプリがどの種類を使用すべきかを選択するには、「IDの確認」セクションをご覧ください。以下のいずれかを指定します。
    • 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/v10.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の末尾に、(選択されているresponse_typeに応じて)URLパラメーターまたはURLフラグメントが追加されます。これをキャプチャする必要があります。

ウェブアプリではコード言語のさまざまな組み合わせを使用できるため、このガイドでは具体例は挙げませんが、最近の言語の大半では、次のようなURL解析が可能です。

クライアントサイドのJavaScriptはURLフラグメント(jQuery BBQなど)をキャプチャできます。一方、クライアントサイドとサーバーサイドのコードはどちらもURLパラメーター(PHPの$_GETjQuery BBQのjQuery.deparamNode.jsのquerystring.parsePythonのurlparseなど)をキャプチャできます。Microsoftは、「オンラインプロバイダー」(この場合はFacebook)に接続するWindows 8アプリ用のガイドとサンプルコードを提供しています。

デスクトップアプリを使用してログインした利用者を、Facebookは前述のredirect_uriにリダイレクトして、アクセストークンとその他のメタデータ(トークンの有効期限など)をURIフラグメントに挿入します。

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

アプリはこのリダイレクトを検出し、使用しているOSと開発フレームワークが提供するメカニズムを使用してURIからアクセストークンを読み取る必要があります。その後は、途中の手順をスキップしてアクセストークンの検査に進むことができます。


ログインがキャンセルされた場合

アプリの利用者がログインダイアログで承認せずにキャンセルをクリックした場合、次のようにリダイレクトされます。

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

利用者がログインを拒否した場合のアプリの対処方法については、不足しているアクセス許可の処理をご覧ください。

IDの確認

このリダイレクトフローでは、ブラウザがログインダイアログからアプリ内URLにリダイレクトされるため、トラフィックは架空のフラグメントやパラメーターでこのURLに直接アクセスすることになります。アプリがこれを有効なパラメーターだと認識してしまうと、この架空のデータがアプリに悪用される可能性が生じます。したがって、アクセストークンの生成前に、アプリの利用者が応答データの対象である人物と同一かどうかを確認する必要があります。IDの確認は、前述の手順で受け取ったresponse_typeに応じた方法で行われます。

  • codeを受け取った場合は、エンドポイントを使用してアクセストークンと交換する必要があります。app secretを扱うため、呼び出しはサーバー間で行わなければなりません(app secretがクライアントコードに含まれないようにしてください)。
  • tokenを受け取った場合は、検証が必要です。トークンがどのアプリによって誰のために生成されたかを示す検査エンドポイントに対してAPI呼び出しを行う必要があります。このAPI呼び出しはアプリアクセストークンを使用する必要があるため、絶対にクライアントから呼び出さないでください。app secretを安全に格納できるサーバーから呼び出します。
  • codetokenの両方を受け取った場合は、両方の手順を実行する必要があります。

CSRF保護のために、stateパラメーターを独自に生成してログインリクエストで使用することもできます。

コードをアクセストークンと交換する

アクセストークンを取得するには、以下のOAuthエンドポイントに対してHTTP GETリクエストを行います。

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

このエンドポイントに必要なパラメーターは次のとおりです。

  • client_id: アプリのID。
  • redirect_uri: この引数は必須であり、OAuthログインプロセスの開始時に使用した元のrequest_uriと同じであることが必要です。
  • client_secret: 固有のapp secret。アプリダッシュボードに表示されます。このapp secretは、クライアントサイドのコードや逆コンパイルが可能なバイナリに含めないようにしてください。このapp secretは、アプリとすべてのアプリ利用者のセキュリティの中核を成すため、機密保持を徹底することが非常に重要です。
  • code: 前述のログインダイアログのリダイレクトから受け取ったパラメーター。

注: v2.3以降、このエンドポイントでは固有のJSON応答が返されます。呼び出しでバージョンを指定しなかった場合は、デフォルトで、利用できる最も古いバージョンが設定されます。

応答

このエンドポイントから受け取る応答はJSON形式で返されます。成功すると、以下のようになります。

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

成功しなかった場合は、その旨を説明するエラーメッセージが表示されます。

アクセストークンの検査

ログインダイアログから受け取るresponse_typeとしてcodeまたはtokenのどちらを使用するかにかかわらず、アプリはアクセストークンを受け取ります。グラフAPIエンドポイントを使用して、トークンの自動チェックを実行できます。

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

このエンドポイントは次のパラメーターを受け取ります。

  • input_token: これが検査対象のトークンになります。
  • access_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/v10.0/dialog/oauth?
    client_id={app-id}
    &redirect_uri={redirect-uri}
    &auth_type=rerequest
    scope=email
   

これにより、却下されたアクセス許可がログインダイアログで再度リクエストされるようになります。

アクセストークンとログインステータスの保存

フローのこの段階で利用者が認証され、ログインします。アプリ側では、利用者に代わってAPI呼び出しを行う準備が整います。その前に、アクセストークンとアプリ利用者のログインステータスを保存する必要があります。

アクセストークンの保存

前の手順でアプリがアクセストークンを受け取った後は、API呼び出しの際にアプリのあらゆる場面で使用できるよう、アクセストークンを保存する必要があります。このステップには特定のプロセスはありませんが、一般的に、ウェブアプリを構築する場合は、特定の利用者のブラウザーセッションを識別するために、トークンをセッション変数として追加するとよいでしょう。ネイティブのデスクトップアプリまたはモバイルアプリを構築する場合は、アプリが利用できるデータストアを使用してください。また、トークンを識別するためのuser_idとともに、トークンをデータベースに格納してください。

アクセストークンのドキュメントに記載されているアクセストークンのサイズに関する注記をご覧ください。

ログインステータスのトラッキング

前述のように、アプリは利用者のログインステータスを保存する必要があります。それにより、ログインダイアログの呼び出しを繰り返し行う必要がなくなります。使用する手順に関係なく、ログインステータスを確認できるように設定してください。

利用者のログアウト

追加したログインステータスのインジケーターの種類を問わず、インジケーターの設定を解除すると、利用者をアプリからログアウトできます(ログインしていることを示すセッションを削除するなど)。保存されているアクセストークンは削除する必要があります。

ログアウト処理は、ログインのアクセス許可の取り消し処理とは異なり(付与済みの認証の削除)、個別に行うことができます。したがって、ログアウトした利用者を強制的にログインダイアログに戻す自動処理を行わないようにアプリを構築してください。

アプリのアンインストールの検出

利用者はアプリ側で操作することなく、Facebook.comからアプリをアンインストールできます。アンインストールが行われたときにアプリが検出できるように、アプリで認証取り消しコールバックURLを指定できるようになっています。これは、アンインストールが発生するとpingされます。

承認取り消しコールバックは、アプリダッシュボードで有効にできます。アプリにナビゲートして、[製品][Facebookログイン][設定]の順に選択してください。[承認取り消しコールバックURL]のテキストフィールドが用意されています。

利用者がアプリの承認を取り消すと必ず、このURLに署名付きリクエストを含むHTTP POSTが送信されます。署名付きリクエストをデコードして、コールバックをトリガーした利用者のユーザーIDを調べる方法については、署名付きリクエストの解析に関するガイドをご覧ください。

ユーザーデータ削除リクエストへの対応

利用者は、Facebookから受け取った自分に関するすべての情報を削除するようアプリにリクエストできます。このようなリクエストへの対応方法については、データ削除リクエストコールバックをご覧ください。