web-dev-qa-db-ja.com

JWTトークンを取り消すにはどうすればよいですか?

Spring Security OAuth2およびJWTトークンを使用しています。私の質問は、どのようにJWTトークンを取り消すことができますか?

ここで述べたように、 http://projects.spring.io/spring-security-oauth/docs/oauth2.html 、失効は更新トークンによって行われます。しかし、うまくいかないようです。

55
sabu

一般的に最も簡単な答えは、JWTトークンを取り消せないということですが、それは単に真実ではありません。正直な答えは、JWT取り消しをサポートするコストは、ほとんどの場合価値がないか、JWTの代替案を明確に再検討しないために十分に大きいということです。

そうは言っても、いくつかのシナリオでは、JWTと即時トークン取り消しの両方が必要になる可能性があるため、必要な処理を実行しますが、最初にいくつかの概念を説明します。

JWT( Learn JSON Web Tokens )は、トークン形式を指定するだけです。この失効問題は、自己完結型または値渡しトークンとして通常知られている形式でも使用されます。後者の用語は、参照トークンと非常に対照的であるため、気に入っています。

by-value token-トークンの有効期間を含む関連情報はトークン自体に含まれており、情報は信頼できるソース(デジタル救助への署名)

by-reference token-関連情報はサーバー側のストレージに保持され、トークン値をキーとして使用して取得されます。サーバー側のストレージであるため、関連する情報は暗黙的に信頼されます

JWT Big Bangの前に、認証システムで既にトークンを処理していました。アプリケーションがユーザーのログイン時にセッション識別子を作成するのが一般的であり、ユーザーが毎回ログインプロセスを繰り返す必要がなくなるように使用されます。これらのセッション識別子は、サーバー側のストレージのキーインデックスとして使用され、これが最近読んだものに似ているように聞こえる場合は正しいです、これは実際に参照トークンとして分類されています。

同じ類推を使用して、参照トークンの失効を理解することは簡単です。そのキーにマップされたサーバー側のストレージを削除するだけで、次回キーが提供されたときに無効になります。

値ごとのトークンの場合は、逆を実装するだけです。トークンの失効をリクエストすると、そのトークンを一意に識別できるものを保存して、次回トークンを受け取ったときに、失効したかどうかをさらに確認できるようにします。このようなものがスケーリングしないと既に考えている場合は、トークンの有効期限が切れるまでデータを保存するだけでよく、ほとんどの場合、常にトークンのハッシュを保存して、既知のサイズのもの。

最後の注意として、これをOAuth 2.0に集中させるため、値によるアクセストークンの取り消しは現在標準化されていません。それにもかかわらず、OAuth 2.0トークン取り消し承認サーバーとリソースサーバーの両方がこれを処理するカスタム方法に同意する限り、それはまだ達成できると具体的に述べています:

前者の場合(self-contained tokens)、即時アクセストークンの取り消しが必要な場合、承認サーバーとリソースサーバー間の一部の(現在標準化されていない)バックエンド対話を使用できます。

承認サーバーとリソースサーバーの両方を制御する場合、これは非常に簡単に実現できます。一方、Auth0などのクラウドプロバイダーまたはSpring OAuth 2.0などのサードパーティコンポーネントに承認サーバーロールを委任する場合は、おそらく、すでに標準化されているものを取得します。

興味深いリファレンス

この記事では、それを行う別の方法について説明します。 Blacklist JWT 興味深い例とパターンに続いて RFC752

71
João Angelo

以下は、新しい交換スキーマ用にJWT oldと呼ばれるソリューションです

有効期限が切れる前に発行されたトークンを無効にできないため、常に30分などの短時間トークンを使用します。トークンの有効期限が切れると、古いトークンを使用して新しいトークンを交換します。重要な点は、1つの古いトークンが1つの新しいトークンを交換できることですonly

センター認証サーバーでは、次のようなテーブルを維持します。

table auth_tokens(
    user_id,
    jwt_hash,
    expire
)

jWT文字列に含まれるuser_id。 jwt_hashは、SHA256などのJWT文字列全体のハッシュ値です。期限切れフィールドはオプションです。

ワークフローは次のとおりです。

  1. ユーザーがユーザー名とパスワードを使用してログインAPIを要求し、認証サーバーが1つのトークンを発行し、トークンを登録します(テーブルに1行追加します。)
  2. トークンの有効期限が切れると、ユーザーは古いトークンを使用して交換APIを要求します。最初に、認証サーバーは有効期限のチェックを除いて古いトークンを通常どおり検証し、次にトークンハッシュ値を作成してから、ユーザーIDでテーブルの上を検索します:
    • レコードが見つかり、user_idとjwt_hashが一致する場合、新しいトークンを発行してテーブルを更新します。
    • レコードが見つかったが、user_idとjwt_hashが一致しない場合は、誰かが以前に交換された新しいトークンを使用したことを意味します。トークンをハッキングし、user_idでレコードを削除し、アラート情報で応答します。
    • レコードが見つからない場合、ユーザーは再度ログインするか、パスワードのみを入力する必要があります。
  3. 使用時にパスワードを変更するか、ログアウトした場合、ユーザーIDでレコードを削除します。

トークンを継続的に使用するには、合法的なユーザーとハッカーの両方が新しいトークンを継続的に交換する必要がありますが、どちらかが成功すると、どちらかが失敗すると次の交換時に再度ログインする必要があります。

したがって、ハッカーがトークンを取得した場合、それは短時間使用できますが、トークンの有効期間が短いため、合法的なユーザーが次回新しいトークンを交換した場合、新しいトークンと交換することはできません。この方法の方が安全です。

ハッカーがいない場合、通常のユーザーも30分ごとなど、定期的に新しいトークンを交換する必要があります。これは、自動的にログインするようなものです。追加の負荷は高くないため、アプリケーションの有効期限を調整できます。

ソース: http://www.jianshu.com/p/b11accc40ba7

15
Huanghq

これは、Springフレームワークに関する質問に正確に答えているわけではありませんが、JWTを取り消す機能が必要な場合は、そもそもJWTを使用せず、代わりに通常の不透明なベアラートークン。

https://www.dinochiesa.net/?p=1388

9

JWTを取り消す1つの方法は、更新トークンが取り消されたときにサービスに通知する分散イベントシステムを活用することです。 IDプロバイダーは、更新トークンが取り消され、他のバックエンド/サービスがイベントをリッスンするときにイベントをブロードキャストします。イベントを受信すると、バックエンド/サービスは、更新トークンが取り消されたユーザーのセットを保持するローカルキャッシュを更新します。

このキャッシュは、JWTを無効にする必要があるかどうかを判断するためにJWTが検証されるたびにチェックされます。これはすべて、JWTの期間と個々のJWTの有効期限に基づいています。

この記事 Revoking JWTs は、この概念を示し、Githubにサンプルアプリがあります。

7
kstra

JWTアクセストークンを取り消す手順は次のとおりです。

  1. ログインすると、クライアントへの応答として2つのトークン(アクセストークン、更新トークン)を送信します
  2. アクセストークンの有効期限は短くなり、リフレッシュの有効期限は長くなります。
  3. クライアント(フロントエンド)は、リフレッシュトークンをローカルストレージに保存し、アクセストークンをCookieに保存します。
  4. クライアントはアクセストークンを使用してAPIを呼び出します。ただし、有効期限が切れたら、ローカルストレージから更新トークンを選択し、認証サーバーAPIを呼び出して新しいトークンを取得します。
  5. 認証サーバーには、更新トークンを受け入れ、その有効性をチェックして新しいアクセストークンを返すAPIが公開されます。
  6. 更新トークンの有効期限が切れると、ユーザーはログアウトされます。

詳細が必要な場合はお知らせください。コードも共有できます。

0
Bhupinder Singh

問題を解決する方法の1つを見つけました Javaを使用して既に生成された既存のJWTトークンを期限切れにする方法?

この場合、任意のDBまたはインメモリを使用する必要があります。

ステップ1:トークンがユーザーに対して初めて生成されるとすぐに、トークンとともにdbに格納し、それが「issuedAt()」時間。

このJSON形式でDBに保存し、

Ex:{"username" : "username", "token" : "token", "issuedAt" : "issuedAt"}

ステップ2:検証するトークンを持つ同じユーザーのWebサービスリクエストを取得したら、 "issuedAtを取得します。 () "トークンのタイムスタンプと、stored(DB/in-memory)発行タイムスタンプと比較します。

ステップ3:保存された発行済みタイムスタンプが新しい場合(after()/ before()メソッドを使用)、トークンが無効であることを返します(この場合、実際にトークンを期限切れにすることはありませんが、そのトークンへのアクセス権の付与を停止しています)。

これが問題の解決方法です。

0
Sindhu Raju