web-dev-qa-db-ja.com

REST SPAのJWTおよびCSRF保護によるAPI認証

RESTバックエンドでSPAを開発していて、単純なトークンベースの認証を取得したいと考えています。REST backedの目標はステートレスであることです。セキュリティモデルを作成し、設計中に行われた決定についてすべてのソースを参照するようにしてください。全体のセットアップについてコメントし、いくつかの特定の質問に答えたいと思います。

要約

認証は専用のエンドポイント(/ auth/loginなど)で行われます。ログイン情報はJSONオブジェクトとして渡されます。情報にはユーザー名とパスワードが含まれます。ログインに成功すると、署名されたJWTトークンが発行されます。このトークンは、REST APIへの以降のアクセスに使用されます。

アプリケーションはHTTPSを使用し、すべてのサブドメインを制御します。

仕様

[〜#〜] jwt [〜#〜]

  • 有効期限時に発行されたユーザー名が含まれています
  • アプリケーション内のロールメンバーシップに関するクレームが含まれています
  • CSRFトークンが含まれています(暗号的に安全な疑似乱数ジェネレーターからランダムに生成されます)
  • サーバーでのみ使用可能なHMAC(SHA256)キーで署名

有効期限

トークンは、短い有効期限(30分など)で発行されます。新しい有効期限の更新されたトークンは、リクエストごとに(スライディングウィンドウの有効期限)、妥当な期限(たとえば8時間)で発行されます。プロセスフローは次のようになります。

  1. 最初のログインリクエストは30分の有効期限でトークンを発行します
  2. 次のリクエストでは、トークンの有効期限が切れているかどうかを確認します。有効期限が切れている場合、アクセスはブロックされます。そうでない場合、要求は満たされます。その時点で、トークンの有効期限のチェックが行われます。

    • 経過時間が期限内(8時間未満)である場合は、さらに30分の新しい有効期限を含む更新されたトークンが生成されます。当時発行されたものは、元のトークンと同じままです。
    • トークンの有効期限が過ぎると、更新されたトークンは生成されず、ユーザーは再度ログインする必要があります。

根拠:トークンが危険にさらされた場合に備えて、短い有効期限でトークンを保護したい。また、ユーザーに頻繁に再ログインを強制したくありません。攻撃者は、トークンの有効期限よりも短い時間枠で新しいトークンを要求する必要があります。攻撃者がなんとかそうした場合、彼/彼女がトークンを使用できる最大時間は締め切りによって定義されます。ユーザーは、設定された期限の期間、オンラインにとどまることができます。ビジネスアプリケーションの場合、8時間または1日の期限で十分です。 この実装は安全ですか?考えられる欠点と脆弱性は何ですか?

JWTトランスポートおよびストレージ

JWTはhttpOnly Cookieとしてクライアントに転送され、ブラウザのCookieリポジトリに保存されます。

理論的根拠:localStorage/sessionStorage内に保持された場合にトークンを危険にさらすXSS攻撃からトークンを保護するため。これは this 記事の推奨事項です。 CSRF攻撃への実装を開く以外に、このアプローチに何か問題がありますか?

CSRF保護

JWTトークンをCookie内に格納すると、実装がCSRF攻撃を受ける可能性があります。この問題を軽減するために、二重送信Cookieメソッドが実装されています。 CSRFトークンが生成され、JWTトークン内に含まれます。このトークンは、ログイン要求への応答のJSONオブジェクトでクライアントアプリケーションにも提供されます。アプリケーションはCSRFをlocalStorageに保存し、カスタムヘッダー内のすべてのリクエストで送信します。

理論的根拠: this 質問への回答 この論文 に対する回答のとおり、効果的なCSRF保護のために、CSRFトークンをセッションID /認証Cookieと暗号で結び付ける必要があります。 JWT内にトークンを含めた場合、それは暗号的にセキュリティセッションに関連付けられていると見なされますか?

概念的には、この実装に問題があると思いますか?

11
Marko Vodopija

この実装は安全ですか?考えられる欠点と脆弱性は何ですか?

JWTは自己記述型のベアラートークンです。 JWTの2つの主な欠点は、古いトークンと、トークンをオンデマンドで期限切れにできないことです。

古いトークン

ユーザーの役割が変更された場合、発行されたトークンには反映されません。新しいものを発行する必要があります。理想的には、以前の有効期限が切れて、次の問題が発生することになります。

オンデマンドの有効期限なし

JWT自体はステートレスであるため、オンデマンドで期限切れにすることはできません。これを解決するアプローチはJWTブラックリストですが、サーバーのステートレス性が失われます。これは、トークンをオンデマンドで無効にできないため、ユーザーがアプリケーションから本質的にログアウトできないことも意味します。

存続期間の短いトークンについて。攻撃者が存続期間の短いトークンを所有している場合、攻撃者が許可する限り(8時間または1日)、APIをクエリして「存続させる」ことができます。

これで十分かどうかを判断する必要があります。それはすべて、あなたが喜んで行うトレードオフに依存します。

実装をCSRF攻撃に開放する以外に、このアプローチに何か問題がありますか?

これは完全に機能します。多くのウェブサイトがそれを使用しているのを見てきました。ただし、CSRFについては心配する必要があります。 APIがJSONでない限り。 こちらをご覧ください

JWT内にトークンを含めた場合、それは暗号的にセキュリティセッションに関連付けられていると見なされますか?

はい。ただし、上記で説明したオンデマンドの終了の問題のため、このシークレットを効果的にローテーションすることはできません。これもまた、トレードオフです。

概念的には、この実装に問題があると思いますか?

私は、あなたが述べたことは完全に合理的だと思います。それには欠点とトレードオフがありますが、サポートする必要がある正確なビジネスケースを知っているのはあなただけです。ログアウト、古いトークン、およびセッションごとの固定CSRFトークンが受け入れられない場合は、問題ありません。

4
Daniel Szpisjak