ここで説明されているように、Facebook OAuth2認証フローに「コード」と「トークン」の両方が必要なのはなぜですか? https://developers.facebook.com/docs/authentication/
OAuthダイアログリファレンス( https://developers.facebook.com/docs/reference/dialogs/oauth/ )を見ると、あなただけのようですトークンを使用してユーザーに関する情報を取得し、response_type
パラメータとしてtoken
またはcode,token
、その後、初めてトークンを取得します。
なぜトークンを直接取得するのではなく、「コード」を取得し、そのコードを使用して「トークン」を取得する必要があるのですか?
OAuthの仕組みについて基本的なことを誤解しているようですが、https://graph.facebook.com/oauth/access_token
ダイアログで初めてトークンを取得する場合は完全に。
認証コードとアクセストークンを区別する簡単な例を見てみましょう。
ユーザーとして、あなたはHighjackという新しいFacebookアプリを試してみたいと思っています。そのため、アプリケーションとハイジャックアプリをクリックします。 Facebookアカウントにログインするように求められます。完了すると、Facebookが認証コードを生成します。
次に、このコードは、独自のFBクライアントID、FBシークレット、および認証コードを使用してアクセストークンを取得するハイジャックサーバーに渡されます。
上記の例では、認証コードは、ユーザーが有効なFBユーザーであることを確認しています。ただし、2番目のステップでは、「FBユーザーとして、特定のリソースのHighjackアプリへのアクセスを許可しています」と表示されます。
Highjackアプリが暗黙的な許可(つまり、直接アクセストークン)を必要とする場合、アクセストークンはブラウザと交換されるため、ユーザーにも表示されます。これは、アクセストークンを使用して、ハイジャックに代わってすべてのFacebook APIを呼び出すことができることを意味します。 (アクセストークンは個人情報を取得するためにのみ使用できますが、FacebookにはAPIを呼び出しているユーザーを知る方法がありません。)
Facebookで認証する2つのパーティ(YouとHighjack)があるため、この2つのメカニズムがあります。
Salesforceドキュメント から恥知らずに借りた:
認証コード
承認コードは、ユーザーのアクセス許可を表す短命トークンであり、承認サーバーによって作成され、ブラウザーを介してクライアントアプリケーションに渡されます。クライアントアプリケーションは認証コードを認証サーバーに送信して、アクセストークンと、オプションで更新トークンを取得します。
アクセストークンアクセストークンは、エンドユーザーに代わって認証されたリクエストを行うためにクライアントによって使用されます。これは、通常は数分または数時間のオーダーで、認証コードよりも長い寿命を持ちます。アクセストークンの有効期限が切れると、使用しようとして失敗し、更新トークンを介して新しいアクセストークンを取得する必要があります。
OAuth 2.0 Spec から:
認証コードには、クライアントを認証する機能や、リソースオーナーのユーザーエージェントを通過せずに直接クライアントにアクセストークンを送信するなど、いくつかの重要なセキュリティ上の利点があります。 。
それで、基本的に-主な理由は、アクセストークンを取得するアクターの数を制限することです。
「トークン」応答は、主にブラウザに存在するクライアント(例:JavaScriptクライアント)を対象としています。
認証コードのフローOAuth type を見ると、はい、アクチュアリーの2つのステップがあります:
1. <user_session_id, client_id> => authorization_code
2. <client_id, redirect_uri, authorization_code, client_secret> => access_token, refresh_token
ステップ1で、ユーザーはOAuthサーバーに、このcliet(client_id)を認証してリソースにアクセスすることを伝えます。ここに私のauthentication(user_session_idまたはその他)があります]
ステップ2:client(client_id)はOAuthサーバーに「ユーザーに認証(authorization_code)を取得しました。後でアクセスするためにアクセストークンを渡してください。これが私の認証です。 (client_id&client_secret)」
手順2を省略すると、クライアント認証の保証はありません。すべてのクライアントは、異なるclient_idを使用してstep1を呼び出し、自分の代わりにそのclient_idのアクセストークンを取得できます。それがステップ2が必要な理由です。
ステップ1とステップ2を本当に組み合わせたい場合は、次のようなことができます。
<client_id, redirect_uri, client_secret> => access_token, refresh_token
Open Api Platformでこのアプローチを使用していますが、セキュリティの問題はまだ見つかりません。
ところで、実際には Implicit Grant type が存在します。つまり:
<client_id, redirect_uri> => access_token, refresh_token
一般に、サーバーバックエンドを持たないクライアントのみのアプリケーションに適用できます。その場合、OAuthサーバーはリダイレクトURIがそのクライアントに属することを確認する必要があります(たとえば、redirect_uriレジスタと同じ)
混乱は、ユーザーがクライアントサーバーではなく認証サーバー(facebook)に対して認証するために自分自身に代わって発生したためです。クライアントアプリ(httpsを使用)とユーザーエージェント(ブラウザー)を保護するのは非常に簡単です。
IETF-oauth( http://tools.ietf.org/html/draft-ietf-oauth-v2-threatmodel-08#section-3.4 )の元の定式化は次のとおりです。
3.4。認証コード
認証コードは、成功したエンドユーザー認証プロセスの中間結果を表し、クライアントがアクセスおよび更新トークンを取得するために使用します。認可コードは、2つの目的でトークンの代わりにクライアントのリダイレクトURIに送信されます。
ブラウザベースのフローは、URIクエリパラメータ(HTTPリファラー)、ブラウザキャッシュ、またはログファイルエントリを介して、潜在的な攻撃者にプロトコルパラメータを公開し、再生される可能性があります。この脅威を減らすために、トークンの代わりに短命の認証コードが渡され、クライアントと認証サーバー間のより安全な直接接続でトークンと交換されます。
クライアントと許可サーバー間の直接要求中にクライアントを認証する方が、間接許可要求のコンテキストよりもはるかに簡単です。後者にはデジタル署名が必要です。
回答)セキュリティを強化するために、コードとトークンの両方が必要です。
Nate Barbettiniによれば、認証コードはフロントチャネルで使用でき(安全性は低い)、アクセストークンはバックチャネルで使用できる(より安全)ため、アクセストークンの認証コードを交換する追加の手順が必要です。 。
したがって、セキュリティ上の利点は、アクセストークンがブラウザーに公開されないため、ブラウザーから傍受/取得できないことです。バックチャネル経由で通信するWebサーバーをより信頼しています。秘密のアクセストークンは、Webサーバーに残り、ブラウザ(つまり、フロントチャネル)に公開されません。
詳細については、次の素晴らしいビデオをご覧ください。
OAuth 2.0およびOpenID Connect(わかりやすい英語)https://youtu.be/996OiexHze0?t=26m30s (開始26分)
理論的には、
バックエンドのない、または最小限のバックエンドを持つ単一ページのアプリケーションまたはモバイルアプリケーションがある場合、アプリケーションはフロントエンドでユーザーのFBデータに直接アクセスしたい場合があります。したがって、アクセストークンが提供されます。
別の場合、Facebook、Googleなどの外部認証サービスプロバイダーを使用して、ユーザーにアプリに登録/ログインしてもらいたい場合があります。この場合、フロントエンドは、アクセストークンの取得に使用できる認証コードをバックエンドに送信しますサーバーサイドのFacebookから。これで、サーバーからユーザーのFBデータにアクセスできるようになりました。
基本的に、 Lix's answer の拡張として、アクセスコードルートにより、リソース所有者(つまり、Facebookユーザー)がユーザーエージェント(つまり、ブラウザー)の承認を取り消すことができます。オフラインクライアント(つまり、アプリケーション)の承認を取り消さずにログオフする。これが重要でない場合は、アクセスコードルートを使用する必要はありません。
さらに、サーバーに提供されるトークンが、ユーザーエージェント(または中間者)ではなく、リソース所有者(つまりFacebookユーザー)に実際に登録されるようにするために、アクセスコードが提供されます。
これは、暗黙的または許可コード付与フローを選択するという質問に似ているようです。 実際、これは反対の視点のように見えるものです!? 。
また、 Drew前述 のように、
アクセストークンの有効期限が切れると、使用しようとして失敗し、更新トークンを介して新しいアクセストークンを取得する必要があります。
別の部分は更新トークンですが、FBドキュメントではあまり説明されていないようです。私が正しい場合、暗黙的な許可(直接トークン)は本当に短命でなければなりませんが、それは強制されるべきであり、FB.jsはその多くを隠しているようです(これは私が深く見ていません) 。
私が正しければ、code%20token
は、ユーザーエージェントがトークンを持つことと、サーバーが1回のリクエストでトークン交換プロセスを開始することの両方を許可する最適化です(ネットワーク上のIOは、特にユーザーエージェント)。
これは、FBとクライアントのみが知っている共有シークレットを使用して、認証されたクライアント(サードパーティアプリ)にアクセストークンが与えられるためです。ユーザーがアクセストークンを直接要求できる唯一の方法は、共有シークレットを知ることです。これにより、シークレットが公開され、中間者攻撃につながる可能性があります。さらに、FBはユーザーへの安全な接続を保証できますが、FBはクライアントへのトークンのハンドオフが安全であることを保証できません。ただし、FB(およびOAuth2)では、クライアントとFBの間に安全な接続が必要です。アクセストークンはクライアントパブリックID(通常はハッシュ)に関連付けられています。つまり、アクセストークンを取得するための認証コードとともにシークレットが送信されるため、元のクライアントアプリケーションのみがトークンを使用してトークンを要求できます。