Windows 8などのネイティブデスクトップアプリ用のウェブビューや、完全にサーバー側のコードを使用するログインフローのように、FacebookのSDKを使用しないブラウザーベースのログインをウェブアプリやデスクトップアプリに実装したい場合、ブラウザーのリダイレクトを使って自分でログインフローを構築できます。このガイドでは、ログインフローの各ステップと、FacebookのSDKを使用せずにそれぞれを実装する方法を説明します。
デスクトップアプリでFacebookログインを使用するには、ログイン処理を実行するアプリ内にウェブブラウザー(ウェブビュー)を埋め込む必要があります。
FacebookのSDKを使用するアプリは、組み込み関数を使って、利用者がログインしたかどうかを確認できます。それ以外のすべてのアプリでは、利用者がいつログインしたかを保存する独自の方法を作成する必要があります。ログインしたことを示すものがない場合、ログアウトしている前提で進められます。利用者がログアウトしている場合、適切なタイミングで(ログインボタンをクリックしたときなど)、アプリによってログインダイアログにリダイレクトする必要があります。
利用者がアプリやFacebookにログインしていなくても、ログインダイアログを使い、両方にログインするプロンプトを出すことができます。利用者がFacebookにログインしていない場合は、最初にFacebookへのログイン、次にアプリへのログインを促すプロンプトが表示されます。これは自動的に検出されるため、この動作を有効にするために特別な設定は必要ありません。
アプリで、ログインダイアログを表示するエンドポイントへのリダイレクトを開始する必要があります。
https://www.facebook.com/v21.0
/dialog/oauth?
client_id={app-id}
&redirect_uri={redirect-uri}
&state={state-param}
このエンドポイントには次の必須パラメーターがあります。
client_id
: アプリのID。アプリダッシュボードで確認できます。redirect_uri
: ログインする利用者のリダイレクト先のURL。このURLはログインダイアログからの応答をキャプチャします。これをデスクトップアプリ内のウェブビューで使用する場合、https://www.facebook.com/connect/login_success.html
に設定してください。このURLがアプリに設定されているかは、アプリダッシュボードで確認できます。アプリダッシュボード左側のナビゲーションメニューの[製品]で、[Facebookログイン]、[設定]の順にクリックします。[クライアントOAuth設定]セクションで[有効なOAuthリダイレクトURI]を確認します。state
: リクエストとコールバック間の状態を維持するために、アプリで作成される文字列。このパラメーターはクロスサイトリクエストフォージェリを防ぐために使用する必要があり、変更されずにリダイレクトURIに返されます。例えば、次のようなログインリクエストがあるとします。
https://www.facebook.com/v21.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アプリのログインを構築する場合、redirect_uri
としてパッケージセキュリティ識別情報を使用できます。WebAuthenticationBroker.AuthenticateAsync
を呼び出してログインダイアログを起動し、ログインダイアログエンドポイントをrequestUriとして使用します。JavaScriptの例を示します。
var requestUri = new Windows.Foundation.Uri(
"https://www.facebook.com/v21.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
}
);
成功した場合は制御フローがアクセストークンとともにアプリに返され、失敗した場合はエラーが返されます。
ログインフローのこの時点で、利用者にはログインダイアログが表示され、キャンセルするか利用者のデータへのアクセスをアプリに許可するかを選択できます。
アプリの利用者がログインダイアログでOKを選択すると、公開プロフィールや友達リストへのアクセスと、アプリがリクエストするその他のアクセス許可を付与することになります。
いずれの場合もブラウザーはアプリに戻り、利用者が接続またはキャンセルしたことを示す応答データが返されます。アプリが前述のリダイレクト方法を使用する場合、アプリが戻すredirect_uri
の末尾に、(選択したresponse_type
に応じて) URLパラメーターまたはURLフラグメントが追加されます。これをキャプチャする必要があります。
ウェブアプリではコード言語のさまざまな組み合わせを使用できるため、このガイドで具体的な例は取り上げません。現代語の大半では、次のようなURL解析が可能です。
クライアント側のJavaScriptは、URLフラグメント(jQuery BBQなど)をキャプチャできます。一方、クライアント側とサーバー側のコードはどちらもURLパラメーター(PHPの$_GET
、jQuery BBQのjQuery.deparam
、Node.jsのquerystring.parse
、Pythonの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.
利用者がログインを拒否した場合のアプリの対処方法については、不足しているアクセス許可の処理をご覧ください。
このリダイレクトフローでは、ブラウザーがログインダイアログからアプリのURLにリダイレクトされるため、トラフィックは架空のフラグメントまたはパラメーターでこのURLに直接アクセスすることになります。アプリがこれらを有効なパラメーターであることを前提とすると、この架空のデータがアプリにより悪用される可能性があります。そのため、アクセストークンを生成する前に、アプリの利用者が応答データの対象と同じ人物であることを確認する必要があります。IDの確認は、前述の手順で受け取ったresponse_type
に応じた方法で行われます。
code
を受け取った場合、エンドポイントを使用してアクセストークンを交換する必要があります。app secretが関係するので、呼び出しはサーバー間で行わなければなりません(app secretがクライアントコードに含まれないようにしてください)。token
を受け取った場合、検証が必要です。トークンがどのアプリで誰に生成されたかを示す、検査エンドポイントに対する呼び出しを行っていください。このAPI呼び出しではアプリアクセストークンを使用する必要があるため、クライアントからこの呼び出しを行わないでください。app secretを安全に保管できるサーバーからこの呼び出しを行ってください。code
とtoken
の両方を受け取ったら、両方のステップを実行する必要があります。独自のstate
パラメーターを生成してログインリクエストで使用し、CSRF保護を提供することもできます。
アクセストークンを取得するには、以下のOAuthエンドポイントに対してHTTP GETリクエストを実行します。
GET https://graph.facebook.com/v21.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
が付与されず、却下されたことがわかります。
利用者がアプリに対して却下したアクセス許可の付与をもう一度リクエストすることはできます。その場合は、アクセス許可の付与が必要な理由を説明する画面を表示して、再リクエストします。ただし、前回と同じ方法でログインダイアログを呼び出しでも、そのアクセス許可のリクエストはされません。
これは、利用者がアクセス許可を一度却下すると、却下されたアクセス許可の再リクエストを明示的にダイアログに指示しない限り、ログインダイアログで同じアクセス許可を再度リクエストすることはないためです。
再リクエストするには、次のようにauth_type=rerequest
パラメーターをログインダイアログURLに追加します。
https://www.facebook.com/v21.0
/dialog/oauth?
client_id={app-id}
&redirect_uri={redirect-uri}
&auth_type=rerequest
scope=email
これにより、却下されたアクセス許可がログインダイアログで再度リクエストされます。
フローのこの時点で、利用者は認証とログインを完了しています。アプリ側では、利用者に代わってAPI呼び出しを行う準備が整っています。呼び出しを行う前に、アクセストークンとアプリ利用者のログインステータスを保存してください。
前のステップでアプリがアクセストークンを受け取った後、アプリのあらゆる部分のAPI呼び出し時に使用できるように、アクセストークンを保存する必要があります。このステップには特定のプロセスはありませんが、一般にウェブアプリを構築している場合は、特定のユーザーのブラウザーセッションを識別するために、トークンをセッション変数として追加するとよいでしょう。ネイティブのデスクトップアプリやモバイルアプリを構築している場合は、アプリで利用可能なデータストアを使用してください。さらにアプリは、ユーザーを識別するuser_id
と一緒に、トークンをデータベースに保存する必要もあります。
アクセストークンのドキュメントに記載されたアクセストークンのサイズに関する注記をご覧ください。
前述のように、アプリは利用者のログインステータスを保存する必要があります。これにより、ログインダイアログの呼び出しを繰り返す必要がなくなります。どの手順を使うとしても、ログインステータスを確認できるように調整してください。
追加したログインステータスのインジケーターの設定を解除すると、利用者をアプリからログアウトさせることができます(ログインしていることを示すセッションを削除するなど)。保存されているアクセストークンを削除する必要もあります。
利用者をログアウトさせることは、ログイン許可の取り消し(以前に付与した認証を削除すること)とは異なり、個別に行うことができます。そのため、ログアウトした利用者を強制的にログインダイアログに戻す自動処理を行わないようにアプリを構築してください。
ユーザーはアプリ自体で操作することなく、Facebook.comからアプリをアンインストールできます。この操作が実行されたときにそれをアプリ側で検出できるようにするため、アプリでコールバックURLの許可取り消しを実行することが可能です。
Appダッシュボードでコールバックの許可取り消しを有効にすることができます。
利用者はアプリに対し、Facebookから受け取った利用者に関する情報すべてを削除するようリクエストできます。このようなリクエストの対応については、データ削除リクエストのコールバックをご覧ください。