web-dev-qa-db-ja.com

oauth2のデータベースにaccesstokenを保存する必要がありますか?

WebアプリケーションにFacebookおよびGoogleログインを実装する必要があります。ユーザーのFacebook/Google +フレンドリストにもアクセスする必要があります。 FacebookとGoogleの完全なOAuth2ドキュメントを確認しました。基本的な考え方はわかった。たとえば、Facebookログインの手順は次のとおりです。

  1. ユーザーは「FBログイン」ボタンをクリックします。
  2. ユーザーはFacebookにログインして許可を求められます。ユーザーが許可すると、認証コードが返されます。
  3. 次に、認証コードを使用してアクセストークンを取得します。
  4. アクセストークンをセッションに保存して、ユーザーセッションを開始できます。
  5. これで、アクセストークンを使用して、さまざまなユーザーリソースにアクセスできます。

ステップ3の後で混乱が生じました。ユーザーがログインするたびにアクセストークンを生成するか、アクセストークンをDBに保存する必要がありますか?

アクセストークンをDBに保存する場合、ユーザーが10日後にサイトにアクセスしたときに(ブラウザーのCookieをクリアしたとしましょう)、トークンを再利用するには、[FBログイン]ボタンをもう一度クリックします。ユーザーが[FBログイン]ボタンをもう一度クリックすると、新しい認証コードを取得し、プロセス全体をもう一度開始する必要があるためです。このユーザーが私のDBにすでにアクセストークンを持っていることをどのようにして認識できますか?

どんな助けでも大歓迎です。

90

技術的には、データベースにアクセストークンを保存し、有効期限が切れるまでAPI呼び出しに使用できます。しかし、それはその価値よりも面倒かもしれません。

1つには、Jonathanが上記のコメントで述べているように、データベースとそのデータの保護について心配する必要があります。これらのトークンは、ユーザーに関するかなり特権的な情報へのアクセスを提供します。もちろん、セッション構成によっては、単にトークンをセッションストレージに保存するだけでも、ディスクに保存される場合があります。使用していない間は暗号化しておくことをお勧めします。

ユーザーがCookieをクリアして戻ってくることについて提案されたシナリオも問題です。データベースからアクセストークンを取得してCookieに貼り付けることもできますが、その前に、相手が本人であることを確認する必要があります。次に、パスワードを提供するためだけに別のパスワード層を実行する必要があります。彼らがすでにあなたに与えたトークンへのアクセス。

彼らが戻ってきて、もう一度ログインボタンをクリックするときに、認証フローを再実行するほうがよいでしょう。それはそれ高価ではありません。しかし、それが本当に魅力的な場合は、トークンを保存することもできます。関連するすべての問題に対処するために本当に注意する必要があります。

34
Bruce

私はこれについて考えていて、私たちにとってうまくいく答えを思いついたかもしれませんが、それがあなたにとってうまくいくかどうかはわかりません。

私たちの環境では、アクセストークンを使用する必要がある主な理由は、一部の自動化プロセスまたはバックエンドプロセスが完了した後、またはスケジュールに従ってユーザーの代わりに操作することです。このようなシナリオでは、ユーザーがこのワークフローに直接関与していないため、ユーザーに再度ログインするように単純に要求することはできません(作業の完了を要求したが、完了してもそこにいないため)。そのため、どういうわけかアクセストークンにアクセスする必要があります。

もちろん、問題が発生しない限り、可能であれば再認証はスキップします。

しかし、アクセストークンを使用するために必要なすべてのものをWebサーバーに格納するという考えも好きではありません。そのため、データベース内のアクセストークンを暗号化しても、暗号化キーがWebサーバーに格納されている場合、私の不安は和らぎません。クライアントシークレットとアプリIDもあるので、これですべてです。

だからここに私の提案した解決策があります、それは4人の俳優を必要とします:

Webサーバーは、appid、secret、およびデータベース接続文字列を(もちろん)保存します。アプリトークンを取得すると、ランダムな対称暗号化キーを生成し、アクセストークンを暗号化します。 データベースは暗号化されたアクセストークンを取得し、暗号化キーはクライアントCookieに保存されます。同時に、Webサーバーは暗号化キーとユーザーIDをペアでバックエンドシステムに送信します。

クライアントがサイトを使用している場合、クライアントCookieを使用してデータベース内のアクセストークンを復号化することにより、再認証を回避できます。 Cookieがなくなると、再認証は何が行われなければなりません。バックエンドシステム(Webサーバーより攻撃範囲がはるかに小さい)にもDB接続文字列があるため、ユーザー情報とやり取りするために必要なすべての情報が存在する唯一の場所です。アクセストークンの有効期間中は、自由に情報を使用できます。

これにより、任意のアクセストークンへの一時的なアクセスのみがWebサーバーに残り、トークンがクライアントに保存されることはありません。それは私にはかなり安全なようですが、多分それは過剰に設計されていると言うかもしれません。考え?

13
Dominic P

セキュリティ上の問題を引き起こす可能性のあるアクセストークンとその使用方法について、いくつかの混乱があると思います。

トークンがセキュリティリスクになる可能性があることは正しいですが、これはサービスから要求する情報によって異なります。たとえば、友達リストは姓名よりも多くの情報ですが、その情報は個人情報ほど重要ではありません。どちらの場合も、実際のアクセストークンを公開する必要はありません。これは、アプリケーションにパスワードを公開するようなものです。

私は、必要に応じて、有効期限が切れるまでユーザーを識別するセッション値(Cookie内の暗号化されたセッション値など)を保持する2次的な「トークン」を作成することを選択します。そのため、ユーザー情報にアクセスできるデータベース(おそらく安全のために暗号化する必要があります)にアクセストークンがあります。

トークンを使用して、個人のIDを取得することもできます。少なくともこれをデータベースに保存すれば、取得したトークンをその人のIDで照合できます。これにより、アクセストークンのコードを交換するときに、IDを比較して適切なレコードを見つけることができます。

3
Mark

これらの回答の多くは、JSON Web Token(JWT)が広く採用される前に作成されたため、古くなっています。

Access_tokenは、電子メール/パスワードのペアを手に持っているのと同じように扱う必要があるため、安全に保存して送信する必要があります。 access_tokenには多くの情報を含めないでください。JWTのsubスコープ内のユーザーIDで十分です。 JWTはペイロードの悪意のある変更を防止するため、そこに格納されている許可とIDを安全に使用できます。

ほとんどのアプリケーションでは、access_tokenに短い有効期限を使用し、代わりにrefresh_tokenを保存することができる(DB呼び出しの頻度が少ない)ため、access_tokenをサーバーに保存するのは少し重いかもしれません。ユーザー情報が必要な場合は、それをIDトークンに格納し、認証されたユーザーに関する情報の表示にのみ使用します。

その情報を更新したいときはいつでもIDトークンを再リクエストし、APIにid_tokenを送信しないでください。

今日、賢い開発者はOpenID Connectを実装して、ユーザー情報とアクセス許可をOAuth 2.0に加えて標準化しています。ほとんどの識別プロバイダー(IdP)がこの仕様(Google、Facebook、 Auth0、YourServiceHere)。

1
SacWebDeveloper

使用しているアプリケーションでトークンの最大リースに達する可能性がある場合は、トークンを保存することをお勧めします。ただし、データベースではなく、Redisの使用をお勧めします。トークンが失われた場合、アプリは実行を継続するように設定する必要があるため、長期間持続する必要はなく、Redisはデータベースを使用するよりもはるかに高速です。立ち上がって実行します。

1
Dean Swiatek