私は自分のアプリにJWTを実装していますが、できる限り安全にしたいと考えています。私は計画しているすべてのものをレイアウトします。この実装のセキュリティに関する提案があれば大いに感謝します。これは私のサイトです。フロントエンドとバックエンドの両方のあらゆる側面に完全にアクセスできます。
これは、APIを使用してバックエンドにアクセスするSPAです。 JWTを使用して、APIヒットごとにDB呼び出しを保存しています。
JWTはaccess_token
Cookieに保存されます。最初に署名され、次に jose-jwt を使用して暗号化されます。署名アルゴリズムはHS256、暗号化はDIRです。これには、ユーザーのID、有効期限exp
クレーム、およびその他のいくつかのカスタムクレームが含まれます。 JWTは30分で期限切れになり、JWT Cookieは7日で期限切れになります。
(短縮版):
exp
クレームは30分後に設定されますJWTには、ランダムに生成されたCSRFトークンを格納するcst
クレームが含まれています。 CSRFトークンは、ログイン時と新しいJWTの発行時に応答本文で送信されます。 CSRFトークンはブラウザのlocalStorageに保存されます。リクエストごとに送信され、JWTの値に対して検証されます。
(短縮版):
JWTは30分で有効期限が切れるので、更新する必要があります。 JWTには、ランダムなリフレッシュトークンを格納するrfs
クレームが含まれています。この更新トークンは、DB(複数のセッションを可能にするユーザーとは別のテーブル)にも格納されます。 JWTの有効期限が切れた場合(exp
クレームに基づいて)、DBがチェックされ、ユーザーがまだ有効であることを確認します(アカウントが削除されていない、パスワードが変更されていないなど)。ユーザーが有効な場合、更新トークンが検証され、新しいJWT/CSRFトークンが生成されて応答で返されます。ユーザーが無効な場合、access_token
は0
のような任意の値で送り返され、有効期限は過去に設定されるため、ブラウザーはそれをクリアします。 CSRFトークンは空に戻されるため、localStorageからクリアされます。ユーザーのすべての更新トークンがDBから消去されます。
(短縮版):
exp
日付でJWTを再発行しますあなたはいくつかの異なるテクノロジーを混同しているようであり、なぜこれらのテクノロジーを選択したのか、なぜそれらが保護しようとしている脅威を制御しているのか明確にしていない。
JWTはaccess_token Cookieに格納されます。最初に署名され、次にjose-jwtを使用して暗号化されます。
暗号化される理由はありますか?署名は、データの整合性を確認する場合に使用されます。つまり、データが鍵なしでだれによっても変更されていない場合です。暗号化は、データの機密性を保護する場合に使用されます。つまり、キーがないと誰も読み取ることができません。トークンにエンドユーザーが読み取ることができないはずのものがない場合、暗号化する理由はありません。
JWTには、ランダムに生成されたCSRFトークンを格納するcstクレームが含まれています。 CSRFトークンは、ログイン時と新しいJWTの発行時に応答本文で送信されます。 CSRFトークンはブラウザのlocalStorageに保存されます。リクエストごとに送信され、JWTの値に対して検証されます。
これは Double Submit Cookie CSRFコントロールの実装のように聞こえます。 localStorageは Same Origin Policy によって保護されており、ユーザーのブラウザーの別のWebセッションがトークンにアクセスできないようにします。
CSRFトークンに少なくとも128ビットのエントロピーがあることを確認してください。
JWTは30分で有効期限が切れるので、更新する必要があります。 JWTには、ランダムなリフレッシュトークンを格納するrfsクレームが含まれています。この更新トークンは、DB(複数のセッションを可能にするユーザーとは別のテーブル)にも格納されます。 JWTが(expクレームに基づいて)期限切れになると、DBがチェックされ、ユーザーがまだ有効であることを確認します(アカウントが削除されていない、パスワードが変更されていないなど)。ユーザーが有効な場合、更新トークンが検証され、新しいJWT/CSRFトークンが生成されて応答で返されます。
これは物事が混乱するところです。セキュリティモデルは、クライアント側セッションまたはサーバー側セッションのどちらかを決定する必要があります。前者には通常JWTが使用されます。つまり、サーバーでのみ利用可能なキーで署名されたトークンがクライアントにある場合、アプリケーションは、このトークンの存在が有効なセッションを示し、有効期限が切れておらず、署名が有効であることを信頼している必要があります。
この方法の欠点は、トークンを取り消すことが難しいことです。ユーザーアカウントが侵害され、ユーザーがパスワードを変更した場合、有効で期限切れではない署名済みトークンがまだあるため、攻撃者のセッションは30分間アクティブのままになります。
これに対する修正は、代わりにサーバー側セッションを実装することです。たとえば、データベーステーブルでセッションを追跡します。つまり、データベースの行を削除することで、セッションから即座にログアウトできます。セッショントークンは128ビットのエントロピーランダム文字列で、Cookieのクライアント側として提供され、データベースからのデータ漏洩を軽減するためにSHA-256サーバー側でハッシュされて保存されます。いつでもプレーンテキストの有効期限をCookieと一緒に送信できるため、クライアントはいつトークンを更新する必要があるかを知ることができます。例えばトークンのHttpOnly Cookie、および有効期限が含まれる非HttpOnly Cookie。これにより、クライアント側のJavaScriptがそれを読み取ることができます。 HttpOnly Cookieは、XSS欠陥の影響を軽減するのに役立ちます。
したがって、サーバー側でセッションを追跡している場合、署名されたJWTをクライアント側に持つ利点はほとんどありません。コードが増えると、攻撃対象が増え、余剰コードに脆弱性が導入される可能性が高くなります。多くの場合、アプリケーションの複雑さはセキュリティの逆です。
セッション状態のサーバー側セッションと組み合わせてDouble Submit Cookieを使用している場合は、CSRFトークンに別のCookieを使用することをお勧めします。これにより、セッション識別子トークンを危険にさらすことなく、クライアント側コードを使用してヘッダーとしてCSRFトークンを追加できます。 CORSを実装せずにカスタムヘッダーを設定する場合は、 これによりCSRFが多少緩和される であることに注意してください。ただし、Flashのようなテクノロジーはブラウザーのセキュリティを混乱させる傾向があるため、トークンも使用することをお勧めします(Flashはより多くのコードを実行し、より多くのコードはより多くの攻撃面を提供し、より多くのコードは脆弱性の可能性を意味します)。
これは、リフレッシュトークンの部分まではかなり健全に聞こえます(CSRFソリューションもかわいいです)。
JWTベースのシステムで私が目にする利点の1つは、アクセストークンが定期的に期限切れになることです。つまり、侵害されたJWTアクセストークンは、攻撃者に数分または数時間のみアクセスを許可します。
JWTに更新トークンを含めると、攻撃者はJWTを危険にさらして簡単にそれを更新して、有効期限を無効にすることができます。
アクセストークンは、新しいアクセストークンを付与できません。新しいアクセストークンを付与できるのは、更新トークン(または完全認証)のみです。
コメントからの集計:
他にすべきこと: