web-dev-qa-db-ja.com

更新トークンを保護する方法は?

アプリのユーザー認証にJWTを使用しています。ユーザーがログインすると、アクセストークンと更新トークンが付与されます。更新トークンを安全に保つために、クライアント側には保存しませんが、バックエンドにアカウントと共に保存するので、簡単にアクセスできません。リフレッシュトークンのセキュリティについて混乱していますが、リフレッシュトークンの使用方法に関するオンラインリソースを読んだときに理解しているロジックは次のとおりです。

  1. 認証する
  2. アクセストークン+更新トークンをどこかに保存します(私の場合、フロントエンドにアクセストークン、バックエンドに更新トークン)
  3. aPIリクエストを実行するときに、API側でアクセストークンを検証します
  4. アクセストークンの有効期限が切れている場合は、更新トークンを使用して新しいアクセストークンと新しい更新トークンを生成し、アクセストークンをクライアントに送信します。
  5. 以前と同じようにトークンを保存し、繰り返します

私が心配しているセキュリティの問題は、他の誰か(ハッカー)がアクセストークンを取得し、それを使用してAPIにリクエストを送信した場合、トークンが期限切れの場合、APIは更新トークンを使用して新しいアクセスを取得することですトークン+新しい更新トークン。少なくともアクセストークンをハッカーに返します。

私は this の記事を約5-6回読み、 this の記事を数回読みます、そして主題に関する他のいくつかの記事を読みます、彼らはすべて、

更新トークンは長期間有効であるため、安全に保管してください。access_tokenは有効期間が短いため、それほど大きな問題ではありません。

ただし、上記で説明したフローによれば、アクセストークンの有効期間が短いかどうかは関係ありません。更新トークンは、新しいアクセストークンを取得して永久にアクセスできるようにするために使用されます。

行方不明のものはありますか?ハッカーが期限切れのアクセストークンを入手した場合、APIは誰がリクエストを送信しているかをどのようにして知るのでしょうか?更新トークンを使用して新しいものを送信します。誰かがリクエストを送信していることをどういうわけか検証するはずですか?


更新

新しいアクセストークンが要求されたときに、更新トークン、クライアントID、およびクライアントシークレットを送信する必要があることを理解しています。以前と同様に、ハッカーは私のAPIサーバーにリクエストを送信でき、サーバーはハッカーからハイジャックされたアクセストークンを取得し、期限切れであると認識し、更新トークンを送信します。 auth APIへのclientID/client secret(環境変数として保存されています)を使用して、新しいアクセストークン/更新トークンを取得します。これにより、同じ問題に戻ることができます。


アップデート2

主題に関するいくつかの興味深い質問:

  1. なぜOAuth v2はアクセストークンと更新トークンの両方を持っているのですか?
  2. https://security.stackexchange.com/questions/87119/how-secure-are-expiring-tokens-and-refresh-tokens

2番目の質問と回答によると、更新トークンはアクセスを維持するためのより安全な方法ではないようです。認証/更新トークンが要求され続け、他のトークンを無効にするため、ハッカーを検出するのは簡単です。この問題は、2人のユーザーが同時にリソースにアクセスしようとしている場合にのみ発生します-特定の期間にハッカーのみがアクティブである場合、元のユーザーが使用するまで、ハッカーは元のユーザーデータに無制限にアクセスできます。アプリと保護されたリソースへのアクセス

6
duxfox--

トークンをサーバーに保存しないでください。クライアントはトークンを認証して取得します。トークンは、ブラウザのcookieまたはlocalStorageに保存します。各リクエストはトークンで承認されます。 sslなしで暗号化されていないチャネルを介して送信する場合、傍受される可能性があります。トークンを入手したハッカーは、ユーザーになりすますことを許可します。期限切れのトークンでは、ユーザーの資格情報を再入力しない限り、再認証を許可しないでください。期限切れのトークンは無視してください。

1
Adrian Brand

これらのアプリケーションのベストプラクティスについて説明している優れたドキュメント ブラウザベースのアプリのOAuth 2. があります。

トークンをクライアントとサーバーのどちらに保持するかを選択します。それを混合すると(サーバーに更新トークンを保持し、ブラウザーにアクセストークンを保持)、独自の脆弱性を持つ独自のプロトコルを作成します。

ブラウザーアプリケーションがバックエンドにアクセスするためだけにアクセストークンを必要とする場合は、バックエンドをOAuth2クライアント(認証コードを受け取る)として使用し、ユーザーのIDを取得し、ブラウザーとブラウザー間のセッションを維持するCookieを発行することを検討できます。バックエンド。 OAuth2トークンの交換、更新、検証よりもはるかに簡単です。

ブラウザーアプリケーションをトークンを受信するOAuth2クライアントとして維持したい場合は、 PKCE拡張 を使用する必要があります(ネットワークキャッシュとブラウザー履歴に保持されている認証コードを使用してトークンを取得することはできません)。新しいアクセストークンごとに新しいリフレッシュトークン- リフレッシュトークンの章 をご覧ください。

承認サーバーは、ブラウザベースのアプリケーションに更新トークンを発行しないでください。

承認サーバーがブラウザーベースのアプリケーションに更新トークンを発行することを選択した場合、すべてのアクセストークンの更新応答で新しい更新トークンを発行する必要があります。これにより、攻撃者と正当なクライアントの両方が同じリフレッシュトークンを使用しようとした場合に、リークリフレッシュトークンが検出される可能性があるため、リークリフレッシュトークンのリスクが軽減されます。

ブラウザーアプリケーションは、トークンをsessionStorageに保持して、ページの再読み込みに耐えることができます。

1
Ján Halaša

リンクした2番目の記事では、トークンを更新するには更新トークンを投稿する必要があると言われていますand client_id and client_secretので、基本的にアクセスを更新するときにユーザーを再認証しますトークン。

更新トークンを使用するには、grant_type = refresh_tokenを使用してサービスのトークンエンドポイントにPOSTリクエストを送信し、更新トークンとクライアント認証情報を含めます。

0
guuus

使用するアクセストークンと更新トークンは次のとおりです。

  1. ユーザーログイン時に期限切れのアクセスと更新トークンを生成し、フロントエンドアプリ(Android、IOS、Webアプリ)に送信します。
  2. フロントエンドアプリは、更新トークンをデータベースに安全に保存しました。
  3. フロントエンドアプリはすべてのリクエストでアクセストークンを送信し、JWTはデータベースにアクセスすることなくそれを検証します。
  4. 認証は、アクセストークンの定義された時間で機能します。
  5. 有効期限が切れると、フロントエンドアプリが更新トークンをサーバーに送信します。さらに、JWTを使用して更新トークンを確認し、データベースでそれが等しいかどうかを確認します。
  6. サーバーは新しいアクセストークンなどを生成します。

PS:通信全体はHTTPSを介して行われる必要があります。

上記のロジックに基づいて、30分ごとに期限切れになるアクセストークンと、有効期間が1年の更新トークンを使用した実装があります。

また、データベースを使用した更新トークンの検証で重要なことは、ユーザーのログインプロセスを制御でき、同じアカウントでアプリを使用できるデバイスの数を制限できることです。

ユーザーが再度ログインリクエストを送信するたびに、サーバー上の更新トークンを更新する必要があります。

0
Aditya T

更新トークンをサーバーに保存する場合、サーバーはユーザーを識別するために、認証応答に安全なセッションCookieを含める必要があります。 HttpOnlyフラグでCookieを設定することにより、攻撃者が安全なセッションCookieを抽出するのを防ぐことができます。

https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Secure_and_HttpOnly_cookies

Cookieは更新トークンにはなりません。他の種類のセッションCookieになります。更新トークンがユーザーに返されない1つのアプリケーションフローは、単一ページのアプリケーションフローです。

https://auth0.com/docs/flows/concepts/single-page-login-flow

このフローでは、トークンの更新は「サイレント認証」を通じて行われます。

https://auth0.com/docs/api-auth/tutorials/silent-authentication#initiate-a-silent-authentication-request

成功した認証応答ユーザーが既にAuth0で有効なセッションを持っている場合で、同意やその他のプロンプトは必要ありません。

したがって、ユーザーIDを保存してセッションを維持する必要があります。

0
chris.va.rao