web-dev-qa-db-ja.com

JWTによる有効期限/「記憶」機能の処理

概念的には、REST etc(状態がサーバー側に保存されていない、すべての関連データがトークンに含まれている)のステートレス性に沿っているため、私は本当にJWTが好きです。

不明な点:接続されていないときにトークンの有効期限をどのように処理しますか(つまり、「記憶」機能)?

WebでJWTの報道が増えていますが、有効期限の質問に答えた人はまだ見つかりませんでした。

説明:トークンがすぐに期限切れになるまでの処理方法ではなく、トークンの期限が切れた場合(ユーザーがしばらくの間Webサイト/アプリを閉じた場合)に何をすべきかを尋ねています。私の頭に浮かぶ最も簡単な解決策は、ユーザーの資格情報をキャッシュすることです。これはかなり安全ではありません。

46
arnuschky

フォローするかどうかは定かではありませんが、思うことを書いていきます。

トークンをホテルのカードとして想像してみてください。あなたは5日間前払いします(私が5日に期限切れになるように設定されていることを思い出してください)。建物、ガレージ、部屋などに5日以内に入ることができますが、5日を過ぎると機能しなくなります。

トークンの有効期限が切れている場合はどうすればよいですか?何もありません。

私がそれらの5日間を支払うと想像してみてください、私は緊急を要し、私は家に帰ります(カードをポケットに入れたまま)。ホテルはまったく気にせず、5日が経過してもカードは役に立たないプラスチック片にすぎないので、ホテルで使用しようとしても何も起こりません。

Web開発に戻ります。リメンバーミーサービスを提供している場合は、有効期限を7日としましょう。ユーザーがトークンを持っている限り、問題なくサービスにアクセスできます。トークンを失った場合は、再度ログインする必要があります。トークンを使用していて有効期限が切れている場合は、再度ログインする必要があります。

ログインした場合、7日間トークンを取得します。トークンを使用しなくなった場合、20日後に再びログインする必要があるため、サーバーはログインするまで申請を拒否します。

フロントエンドでangularのようなものを使用する場合、私は何をしますか?起動時にトークンの検証をチェックして、素晴らしいユーザーエクスペリエンスを実現することです。

あなたの質問について私が理解していないのは、デキャッシングのことです。

8
Jesus Rodriguez

@ Jesus answer に加えて、更新トークンシステムの実装について考えることができます: https://auth0.com/blog/refresh-tokens-what-are-they-and-いつ使用するか/

ホテルの例では、ホテルカード(アクセストークン)はX時間後に無効になりますが、フロントではパスポート(更新トークン)を使用して新しいホテルカードを再度取得できます。

ユーザーが使用しているデバイスに関する追加データを含む更新トークンをデータベースに保存すると、盗まれた場合にデバイスを無効にすることができます。

例:

  1. 最初の正しいクライアントログイン:永久に有効な更新トークンを作成します(削除または無効化されるまで)
  2. データベースに更新トークンを保存する
  3. 有効期限付きのアクセストークン(JWT)をクライアントに返します(このトークンはデータベースに保存されません)
  4. 次のリクエストでは、クライアントはアクセストークンを送信します

  5. 次に、アクセストークンが期限切れかどうかを確認します。

    5.1アクセストークンの有効期限が切れていない、すべて問題ない

    5.2アクセストークンが期限切れです。データベースに更新トークンがあるかどうかを確認してください

    5.2.1更新トークンはデータベースにあり、新しいアクセストークンを返します

    5.2.2データベースに更新トークンがない、401 /ログアウトを返す、ユーザーは再度ログインする必要がある

お役に立てれば。

5
Felix Hagspiel

JWTをクライアントに永続化して、ページの読み込み全体で利用できるようにする必要があります。最も安全な戦略はHTTPSのみのCookieです。これにより、リクエストごとにJWTがサーバーに送信され、サーバーはトークンの有効性を確認し、有効期限が切れている場合は拒否できます。有効期限の処理方法は、使用しているWebアプリのタイプによって異なります。

単一ページのアプリケーション(Angular.jsアプリなど)の場合、アプリケーションを構造化して、残りのアプリケーションをブートストラップする前にサーバーの初期リクエストを行うようにします。サーバーは、この要求のJWTが期限切れであることを検出すると、401応答を発行します。アプリケーションは、ログインフォームをレンダリングすることにより、この応答に応答します。それ以外の場合は、JWTが有効であり、必要なリソースにアクセスするために使用できるという前提で続行されます。いつでもアプリが401を検出した場合、ユーザーをログインフォームに戻す必要があります。

サーバー上にページをレンダリングする従来のWebアプリの場合:(Cookieから読み取られた)期限切れのJWTを含む要求の場合、サーバーはログインフォームに302リダイレクトを発行する必要があります。

3
robertjd

私は1つの方法を考えることができますが、それは実際には標準を定義していません。

クレームに寿命の異なる別の種類の有効期限を追加するのはどうですか? 2つのクレームを使用すると、短い方をリソースアクセスの有効期限として扱い、長い方を更新の有効期限として扱うことができます。

{
    "iat": /* current time */,
    "bbf": /* current time + 1 hour -- expired means no resource access */
    "exp": /* current time + 1 week -- expired means cannot refresh */
}

(注:有効期限を短くするためにbbfを使用します。長さが3文字だからといって、特別な理由はありません。)

したがって、「remember me」がチェックされていると、ユーザーが再接続したときに、同じトークンを使用して新しいトークンを要求できますが、リソースにアクセスすることはできません。これにより、すべての関連データがトークン内に含まれます。追加のトークンは必要ありません。

最後に、「覚えている」がチェックされていない場合は、bbfexpに同じ寿命を使用します。

1
hiapay

私があなたが求めているのは、長い有効期限トークンのためにJWTサーバー側を無効にする方法だと思います(たとえば、「remember me」機能)。

私は最近この問題に遭遇し、一意のユーザーシークレットを使用してトークンを無効にしてしまいました。ユーザーが古いシークレットで作成されたトークンを検証しようとすると失敗します。ユーザー名は、デコードされたJWT事前検証に含まれています。

おそらくこれにユーザーのパスワードソルトを使用することもできます。これにより、ユーザーがパスワードを変更したときに現在のJWTが無効になります(同時にソルトも変更すると想定)、これはパスワードハッシュとJWTとして問題になる可能性があります密結合になる

1
Daniel Landers

Remember-me機能を理論的に実装する方法の特定の問題に対する白黒の答えはありません。なぜ何かをすべきでないのかについて多くの理論的議論が与えられていますが、同時に、それが実際にどのように行われなければならないかについての問題に対する明確な答えはありません。

Remember-meには暗黙的にトークンの有効期限のより長い時間枠が必要であるという問題が伴いますが、これを回避する方法はありません。最も安全な方法は、ユーザーに定期的に短い有効期限を与えてログインさせることです。しかし、実際にこれを好む人はいないので、-tradeoffが作成され、理論上の安全な完成度が実際の対策と比較されます。

このトレードオフが機能する方法は、トークンの有効期限が長くなることに伴う欠陥にパッチを適用することです。しかし、それについて誤解しないでください有効期限が長いjwt/cookieが必要になります(2つのトークンを使用するか、いくつかの二次的な更新メカニズムを実装するかどうかにかかわらず、最後に同じ問題が発生します)!
他の人がそれをどのように行ったかについて私が読んだ記事に基づいて、これはそれが行われた方法です。

これを実装する方法は、ユーザーが記憶を確認したときにhttpOnly /セキュアCookieに保存されているjwtに3か月の有効期限を提供することです。
ログアウト時にCookieをクリアするだけです。
明らかに、上部にhttps/CSRF対策を使用して保護します。

あなたがそれに同意しない場合は、大騒ぎをやめて、私がそれについて読んだ無限の数の議論から明らかではない別の解決策を提供してください。
問題に対する簡単な解決策があったとしても、そもそもそれについてそれほど多くの議論がなされることはおそらくないでしょう。

0
Trace