パスワード/ログアウトの変更中にdbを押すことなくJWTを無効にするためのベストプラクティスを知りたいです。
ユーザーデータベースにアクセスして、上記の2つのケースを処理するためのアイデアを以下に示します。
1.パスワードを変更する場合、ユーザーdbに保存されているパスワード(ハッシュ)を確認します。
2.ログアウトの場合、ユーザーdbに最後のログアウト時間を保存するため、トークンの作成時間とログアウト時間を比較することで、このケースを無効にできます。
ただし、これら2つのケースでは、ユーザーがapiをヒットするたびにユーザーdbをヒットするという犠牲が伴います。ベストプラクティスを歓迎します。
PDATE: dbを押すことなくJWTを無効にできるとは思わない。そこで私は解決策を思いつきました。回答を投稿しました。懸念がある場合は、大歓迎です。
更新トークンを使用しない場合:
1。パスワードを変更している間:ユーザーがパスワードを変更するときは、ユーザーdbのパスワード変更時間に注意してください。そのため、パスワード変更時間がトークン作成時間よりも長い場合、トークンが無効です。したがって、残りのセッションはすぐにログアウトされます。
2。ユーザーがログアウトするとき:ユーザーがログアウトするとき、別のDBにトークンを保存します(たとえば、InvalidTokenDBで、トークンの有効期限が切れたらDbからトークンを削除します)。したがって、ユーザーはそれぞれのデバイスからログアウトし、他のデバイスでのセッションはそのまま残りました。
したがって、JWTを無効にしながら、以下の手順に従います。
上記の方法に関する懸念:
更新トークンが使用される場合:アクセストークンの有効期限が1日の場合、更新トークンは有効期間として有効
1。パスワードの変更中:ユーザーがパスワードを変更した場合、ユーザーの更新トークンを変更します。したがって、残りのセッションはすぐにログアウトされます。
2。ユーザーがログアウトするとき:ユーザーがログアウトするとき、トークンを別のDBに保存します(たとえば、InvalidTokenDBで、トークンの有効期限が切れたらDbからトークンを削除します)。したがって、ユーザーはそれぞれのデバイスからログアウトし、他のデバイスでのセッションはそのまま残りました。
したがって、JWTを無効にしながら、以下の手順に従います。
上記の方法に関する懸念:
注:Hanzは Token-based AuthenticationでのRefeshトークンの使用は安全ですか? でリフレッシュトークンを保護する方法を提案しましたが、理解できませんでした彼が言っていること。どんな助けも大歓迎です。
だから誰かがニースの提案を持っているなら、あなたのコメントは大歓迎です。
UPDATE:アプリがライフタイムの有効期限が切れる更新トークンを必要としない場合に備えて、回答を追加しています。この回答は、Sudhanshu(- https://stackoverflow.com/users/4062630/sudhanshu-gaur )によって与えられました。スダンシュに感謝します。だから、これがこれを行う最良の方法だと思います。
更新トークンが不要で、アクセストークンの有効期限がない場合:
ユーザーがログインするとき、有効期限なしでユーザーデータベースにログイントークンを作成します。
したがって、JWTを無効にしながら、以下の手順に従ってください。
したがって、このアプローチでは、有効期限までデータベースにログアウトトークンを保存する必要も、上記の場合に必要であったパスワードを変更するトークン作成時間を保存する必要もありません。ただし、この方法は、更新トークンが不要で、トークンの有効期限がないアプリに要件がある場合にのみ有効だと思います。
誰かがこのアプローチに懸念がある場合は、お知らせください。あなたのコメントは大歓迎です:)
何らかの方法でデータベースに関与することなく、トークンを勝手に無効にする方法はありません。
複数のデバイスでサービスにアクセスできる場合は、アプローチ2に注意してください。次のシナリオを検討してください...
- ユーザーはiPadでサインインし、トークン1を発行して保存します。
- ユーザーがウェブサイトにサインインします。トークン2が発行されました。ユーザーがログアウトします。
- ユーザーがiPadを使用しようとしました。ユーザーがWebサイトからログアウトする前にトークン1が発行されましたが、トークン1は無効と見なされました。
refresh tokens のアイデアを見たいかもしれませんが、これらもデータベースストレージを必要とします。
here も参照してください。同様の問題、特定のdb呼び出しを保存する特定のIanBのソリューションに関するSOの良い議論について。
提案された解決策個人的には、これは私がそれに近づく方法です...ユーザー認証、短い有効期限(15分など)でアクセストークンを発行し、更新トークンは、より長い期間または無期限に有効です。この更新トークンのレコードをdbに保存します。
ユーザーが「アクティブ」な場合は常に、新しい認証トークンを毎回発行します(毎回15分間有効です)。ユーザーが15分以上アクティブでない状態でリクエストを行った場合(期限切れのjwtを使用する場合)、リフレッシュトークンの有効性を確認します。有効な場合(dbチェックを含む)、新しい認証トークンを発行します。
ユーザーがデバイス上またはWebサイト経由で「ログアウト」した場合、クライアント側のアクセスリフレッシュトークンの両方を破棄し、使用されたリフレッシュトークンの有効性を大幅に無効にします。ユーザーがいずれかのデバイスでパスワードを変更した場合、アクセストークンの有効期限が切れるとすぐに、すべての更新トークンを取り消して、再度ログインするように強制します。これは「不確実性の窓」を残しますが、毎回dbを押すことなく避けられません。
また、このアプローチを使用すると、多くの主要なWebアプリで見られるように、ユーザーが必要に応じて特定のデバイスへのアクセスを「取り消す」ことができる可能性が広がります。
ここで何かが欠けているかどうかはわかりませんが、受け入れられた答えは必要以上に複雑であることがわかります。
各apiリクエストのトークンを検証または無効にするにはdbを押す必要があることがわかりますが、ここで見たように、全体のプロセスはより単純でした。
ログイン時またはパスワードの変更/リセット時にjwtが作成されるたびに、jwtをユーザーIDとともにテーブルに挿入し、jwtごとにjti(基本的にはuuid番号)を維持します。同じjtiもjwtペイロードに入ります。実質的にjtiはjwtを一意に識別します。アカウントに複数のデバイスまたはブラウザーからアクセスする場合、ユーザーは同時に複数のjwtを持つことができます。その場合、jtiはデバイスまたはユーザーエージェントを区別します。
したがって、テーブルスキーマはjti |ユーザーID。 (および主キーのコース)
各APIについて、jtiがテーブルにあるかどうかを確認します。これは、jwtが有効なものであることを意味します。
ユーザーがパスワードを変更またはリセットしたら、そのuserIdのすべてのjtiをdbから削除します。新しいjtiを使用して新しいjwtを作成し、テーブルに挿入します。これにより、パスワードを変更またはリセットしたものを除く、他のすべてのデバイスおよびブラウザーからのすべてのセッションが無効になります。
ユーザーがログアウトしたら、そのユーザーの特定のjtiを削除しますが、すべてではありません。シングルログインがありますが、シングルログアウトはありません。そのため、ユーザーがログアウトするとき、すべてのデバイスからログアウトするべきではありません。ただし、すべてのjtisを削除すると、すべてのデバイスからもログアウトされます。
したがって、1つのテーブルであり、日付比較はありません。また、更新トークンが使用されているかどうかも同じです。
ただし、dbの干渉と遅延の可能性を最小限に抑えるために、キャッシュの使用は確かに処理時間の前に物事を緩和するのに役立ちます。
注:投票する場合は、理由を付けてください。
ユーザーがパスワードを変更している場合は、そこでデータベースにアクセスします。しかし、認証のためにデータベースにアクセスしたくないですか?
ユーザーごとの文字列を格納することの利点を発見しました。また、ハッシュされたグローバル共有文字列を使用すると、JWT実装で最大の柔軟性が得られます。この特定のケースでは、グローバル文字列で使用するパスワードのハッシュを保存し、JWTシークレットのためにそれらを一緒にハッシュします。