web-dev-qa-db-ja.com

JWTトークン認証を使用する場合、更新トークンは本当に必要ですか?

JWTでのリフレッシュトークンの使用について説明している別のSO投稿を参照しています。

JWT(JSON Web Token)有効期限の自動延長

私のクライアント(Webおよびモバイル)がREST APIと通信し、サービス層とデータ層と通信するという非常に一般的なアーキテクチャーのアプリケーションがあります。

enter image description here

JWTトークン認証は理解していますが、リフレッシュトークンの使用方法に少し混乱しています。

JWT認証に次のプロパティを設定します。

  1. JWTトークンの有効期限は2時間です。

  2. トークンは、クライアントによって1時間ごとに更新されます。

  3. ユーザートークンが更新されず(ユーザーが非アクティブでアプリが開いていない)、有効期限が切れた場合、再開するたびにログインする必要があります。

リフレッシュトークンの概念を使用してこれをより良いエクスペリエンスにすると主張している人はたくさんいますが、これの利点はわかりません。それを管理しなければならないという複雑さが増しているようです。

私の質問は次のとおりです。

  1. リフレッシュトークンを使用する場合でも、そのトークンの適切な運用のために長期間の有効期限を設定することはまだ有益ではないでしょうか?
  2. 更新トークンを使用する場合、そのトークンはuserIdまたはJWTトークン、あるいはその両方で永続化されますか?
  3. トークンを1時間ごとに更新すると、どのように機能しますか? JWTトークンまたは更新トークンを受け取るエンドポイントを作成しますか?これにより、元のJWTトークンの有効期限が更新されますか、それとも新しいトークンが作成されますか?
  4. これらの詳細を考えると、更新トークンが必要ですか?ユーザーがJWTトークンを使用して新しいトークンを取得している場合(上記のリンクによる)、更新トークンは廃止されているようです。
31
TheJediCowboy

少し後で質問にお答えします。まず、更新トークンの目的全体について実際に説明します。

つまり、状況は:

ユーザーはアプリを開き、ログイン認証情報を提供します。現在、アプリはRESTバックエンドサービスと対話しています。RESTステートレスであるため、APIへのアクセスを承認する方法は実際にはありません。したがって、 、これまでの説明では、承認されたユーザーが実際にAPIにアクセスしているか、または単にランダムなリクエストが通過しているかどうかを確認する方法はありません。

この問題を解決できるようにするには、リクエストが承認されたユーザーからのものであることを知る方法が必要です。そこで、アクセストークンと呼ばれるものを導入しました。したがって、ユーザーが正常に認証されると、アクセストークンが発行されます。このトークンは長く、非常にランダムなトークンであると想定されています(推測できないようにするため)。ここで、JWTが重要になります。ここで、ユーザー固有の詳細をJWTトークンに格納する必要がある場合とそうでない場合があります。理想的には、JWTに非常に単純で非常に機密性の低い詳細を格納するだけです。他のユーザーの詳細(IDORなど)を取得するためのJWTハッシュの操作は、JWT(使用されているライブラリー)自体によって処理されます。

したがって、今のところ、許可されたアクセスの問題は解決されています。

次に、攻撃シナリオについて説明します。上記のすべてのユーザーを使用していて、アプリを使用しているアリスが承認されたアクセストークンを持っていて、彼女のアプリがすべてのAPIにリクエストを発行し、彼女の承認に従ってデータを取得できるとします。

[〜#〜] somehow [〜#〜]アリスがアクセストークンを失うか、別の言い方をすると、攻撃者のボブがアリスのアクセストークンにアクセスするとします。これで、ボブは無許可であるにもかかわらず、実際にアリスが許可されたすべてのAPIにリクエストを行うことができます。

何かWE理想的には望まない。

今、この問題の解決策は次のとおりです。

  1. このようなことが起こっていることを検出してください。
  2. 攻撃ウィンドウ自体を減らします。

アクセストークンだけを使用すると、上記の条件1を達成するのは困難です。これは、AliceとBobのどちらでも、使用されている同じ承認済みトークンであり、2人のユーザーからの要求を区別できないためです。

したがって、上記の2を達成しようとするため、アクセストークンの有効性に有効期限を追加します。たとえば、アクセストークンは「t」(存続期間)有効です。

それはどのように役立ちますか?まあ、ボブがアクセストークンを持っている場合でも、ボブはそれが有効になるまでしか使用できません。それが期限切れになるとすぐに、彼は再びそれを取得する必要があります。もちろん、彼は最初に手に入れたのと同じ方法でそれを手に入れることができると言えるでしょう。しかし、それでも100%のセキュリティに勝るものはありません。

上記のアプローチにはまだ問題があり、実際には許容できない場合もあります。アクセストークンの有効期限が切れると、ユーザーはログイン資格情報を入力し、承認されたアクセストークンを再度取得する必要があります。これは、少なくともモバイルアプリの場合、ユーザーエクスペリエンスが悪い(許容できない)ものです。

Solution:これが更新トークンの出所です。これもランダムな予測不可能なトークンであり、最初にアクセストークンと共にアプリにも発行されます。この更新トークンは非常に長期間有効な特別なトークンであり、アクセストークンの有効期限が切れるとすぐにサーバーに新しいアクセストークンを要求するため、ユーザーがログイン資格情報を再入力して既存のアクセストークンの有効期限が切れると、新しい認証済みアクセストークン。

ボブは、アクセストークンを侵害したのと同じように、リフレッシュトークンにもアクセスできます。はい。彼はできます。ただし、アクセストークンだけでは不可能だったこのような発生を簡単に特定し、被害を軽減するために必要な措置を取ることが容易になりました。

方法?

すべての認証済みユーザー(モバイルアプリの場合)に対して、1対1のマップされた更新トークンとアクセストークンのペアがアプリに発行されます。したがって、任意の時点で、単一の認証済みユーザーの場合、更新トークンに対応するアクセストークンは1つだけになります。ここで、ボブがリフレッシュトークンを危険にさらした場合、それを使用してアクセストークンを生成するとします(APIを介してリソースへのアクセスが許可されているのはアクセストークンだけだからです)。ボブ(攻撃者)が新しく生成されたアクセストークンを使用して要求を行うとすぐに、アリス(正規ユーザー)のアクセストークンがまだ有効であるため、サーバーはこれを異常と見なします。一度にアクセストークン。異常を特定すると、サーバーは問題の更新トークンを破棄し、それに関連して、それに関連付けられているすべてのアクセストークンも無効になります。したがって、リソースを必要とする許可への、正規または悪意のある、それ以上のアクセスを防止します。ユーザーAliceは、自分の資格情報でもう一度認証し、更新トークンとアクセストークンの有効なペアをフェッチする必要があります。

もちろん、ボブがリフレッシュトークンとアクセストークンの両方に再度アクセスして上記のストーリー全体を繰り返すことができ、実際の本物の顧客であるアリスのDoSにつながる可能性があると主張することはできますが、100%のセキュリティはありません。 。

また、有効な方法として、かなり長いものですが、更新トークンにも有効期限があります。

40
qre0ct

このシナリオでは、アクセストークンのみを使用して作業することで、クライアントの生活を楽にし、更新トークンのセキュリティ上の利点を維持できると思います。

これはどのように機能するかです:

  1. ユーザーが資格情報(ユーザー名/パスワード)でログインすると、有効期間が短いJWTが返されます。また、保存する場所にdbレコードを作成します。

    • JWT ID
    • ユーザーID
    • IPアドレス
    • ユーザーエージェント
    • validフラグ(デフォルトはTRUE)
    • createdAt
    • updatedAt
  2. クライアントはすべてのリクエストでJWTを送信します。 JWTの有効期限が切れていない限り、JWTはリソースにアクセスできます。 JWTの有効期限が切れた場合は、バックグラウンドで更新し、リソースと追加のX-JWTヘッダーの両方を新しいJWTで返します。

  3. クライアントがX-JWTヘッダーを含む応答を受信すると、古いJWTを破棄し、将来の要求に新しいJWTを使用します。

サーバーでJWTを更新する方法

  1. JWT IDを使用して一致するdbレコードを探します。
  2. validフラグがまだ真であるかどうかを確認し、そうでない場合は拒否します。
  3. 必要に応じて、リクエストIPアドレスとユーザーエージェントを、保存されているIPアドレスとユーザーエージェントと比較し、何かが怪しいと思われる場合は拒否することを決定できます。
  4. オプションで、dbレコードのcreatedAtフィールドまたはupdatedAtフィールドを確認し、時間が経過しすぎた場合に更新しないことを決定できます。
  5. DbレコードのupdatedAtフィールドを更新します。
  6. 新しいJWT(基本的には期限切れのJWTのコピーですが、有効期限が延長されたもの)を返します。

この設計では、ユーザーのすべてのトークンを取り消すこともできます(たとえば、ユーザーが電話を紛失した場合やパスワードを更新した場合)。

利点:

  • クライアントは有効期限を確認したり、更新トークンを要求したりする必要はありません。クライアントが行うのは、応答のX-JWTヘッダーを確認することだけです。
  • IPアドレス、ユーザーエージェント、最大トークン保存期間、またはそれらの組み合わせに基づいて、カスタム更新ロジックを追加できます。
  • ユーザーの一部またはすべてのトークンを取り消すことができます。
8
alexishevia

リフレッシュトークンを使用する場合でも、そのトークンの適切な運用のために長期間の有効期限を設定することはまだ有益ではないでしょうか?

更新トークンは存続期間が長く、アクセストークンは存続期間が短いです。

更新トークンを使用する場合、そのトークンはuserIdまたはJWTトークン、あるいはその両方で永続化されますか?

これは、JWTとともにクライアント上の個別のトークンとして永続化されますが、JWT内には永続化されません。 UserID/UIDは、JWTトークン自体に格納できます。

トークンを1時間ごとに更新すると、どのように機能しますか? JWTトークンまたは更新トークンを受け取るエンドポイントを作成しますか?これにより、元のJWTトークンの有効期限が更新されますか、それとも新しいトークンが作成されますか?

はい、トークンを発行して更新する別のサービスが必要です。既存のJWTトークンの有効期限は更新されません。トークンは、base64でエンコードされた単なるJSONフィールドと値のペアです。したがって、データを変更すると、出力も変更されます。トークンには発行日もあり、少なくとも新しい発行(更新)ごとに変更されます。したがって、すべてのトークンは一意で新しいものになります。古いトークンは自動的に期限切れになるため、すべてのアクセストークンで期限切れにする必要があります。そうしないと、永久に残ります。

ここでの他の答えは、新しいトークンを発行すると古いトークンが破棄されることです。それは単にそうではありません。トークンは破棄できません。実際、常に認証サーバーにアクセスし、更新トークンを使用して新しい新しいトークンを要求することで、何百ものトークンを収集できます。これらのアクセストークンはそれぞれ、有効期限が切れるまで有効です。したがって、有効期限は必須であり、短くする必要があります。

これらの詳細を考えると、本当に更新トークンが必要ですか?ユーザーがJWTトークンを使用して新しいトークンを取得している場合(上記のリンクによる)、更新トークンは廃止されているようです。

JWTトークンにはクライアント要求があります。例えば ​​is_manager:true JWTトークンの要求により、マネージャーレベルの機能へのアクセスが許可される場合があります。ユーザーをマネージャーから請負業者に降格した場合、すぐには有効になりません。ユーザーはまだ古いトークンを使用している可能性があります。最後に、有効期限が切れると、認証サーバーにアクセスしてトークンを更新します。認証サーバーは管理クレームなしで新しいトークンを発行し、ユーザーは管理機能にアクセスできなくなります。これにより、ユーザーの要求がサーバーと同期していないウィンドウが作成されます。これは、アクセストークンの有効期間が短く、同期が頻繁に発生する理由を説明しています。

基本的には、承認チェックを15分ごとに更新します。これは、リクエストごとにチェックするのではなく(通常のセッションベースの認証のしくみです)。 15分ごとの更新ではなくリアルタイムのアクセス許可が必要な場合は、 JWTは適切ではない可能性があります

0
aleemb