web-dev-qa-db-ja.com

JWT認証と更新トークンの実装

REST独自の認証および承認メカニズムを備えたアプリケーションを開発しています。認証にJSON Web Tokenを使用したいと思います。以下は有効で安全な実装ですか?

  1. A REST APIは、ユーザー名とパスワードを受け入れて認証を行うために開発されます。使用されるHTTPメソッドはPOSTなので、キャッシングはありません。また、 、輸送時のセキュリティのためにSSLが存在します
  2. 認証時に、アクセストークンと更新トークンの2つのJWTが作成されます。更新トークンの有効期間は長くなります。両方のトークンはCookieに書き込まれるため、後続のすべてのリクエストで送信されます
  3. REST API呼び出しごとに、トークンはHTTPヘッダーから取得されます。アクセストークンの有効期限が切れていない場合は、ユーザーの権限を確認し、それに応じてアクセスを許可してください。アクセストークンの有効期限が切れている場合しかし、リフレッシュトークンは有効であり、新しいアクセストークンとリフレッシュトークンを新しい有効期限で再作成し(認証のためのユーザー権限が取り消されていないことを確認するために必要なすべてのチェックを行います)、Cookieを介して送り返されます。
  4. ログアウトを提供するREST Cookieをリセットするため、ログインが完了するまで後続のAPI呼び出しは拒否されます。

ここでの更新トークンの私の理解は:

リフレッシュトークンが存在するため、アクセストークンの有効期間を短くして、ユーザーがまだログインを許可されているかどうかを(アクセストークンの期限切れ時に)頻繁に確認できます。

私が間違っていたら訂正してください。

12
Saptarshi Basu

A REST APIは、ユーザー名とパスワードを受け入れて認証を行うために開発されます。使用されるHTTPメソッドはPOSTなので、キャッシングはありません。また、 、輸送時のセキュリティのためにSSLが存在します

これがほとんどの方法なので、あなたはここで上手です。

認証時に、アクセストークンと更新トークンの2つのJWTが作成されます。更新トークンの有効期間は長くなります。両方のトークンはCookieに書き込まれるため、後続のすべてのリクエストで送信されます

トークンをCookieに保存すること自体は危険ではありませんが、サーバーのJWTモジュールにトークンを読み取らせると、Webページがユーザーのブラウザーをトリガーしてフォームを送信し、サイトのCookieを送信するCSRF攻撃に対して脆弱になります。 CSRFトークンを使用しない限り、サーバー。そのため、一般的にそれらはlocalStorageに格納され、毎回リクエストヘッダーに「手動で」追加されます。

REST API呼び出しごとに、トークンはHTTPヘッダーから取得されます。アクセストークンの有効期限が切れていない場合は、ユーザーの権限を確認し、それに応じてアクセスを許可してください。アクセストークンの有効期限が切れている場合しかし、リフレッシュトークンは有効であり、新しいアクセストークンとリフレッシュトークンを新しい有効期限で再作成し(認証のためのユーザー権限が取り消されていないことを確認するために必要なすべてのチェックを行います)、Cookieを介して送り返されます。

クッキーの危険性は別として、それは安全に思えます。

ログアウトを提供するREST Cookieをリセットするため、ログインが完了するまで後続のAPI呼び出しは拒否されます。

API呼び出しを行う必要さえありません。単にCookieまたはlocalStorageオブジェクトをパージし、欠落しているトークンでクライアントが壊れないようにすることができます。

Express-jwtモジュールの標準では、トークンが独自の「Authorization:Bearer [Token]」ヘッダーにあると想定しています。これは、Cookieよりも強くお勧めします。 localStorage APIは IE8 までずっと利用できるので、あなたは良いはずです。

編集:

XSS攻撃とCSRF攻撃は同じものであると考えられることが多いため、最初にXSS攻撃とCSRF攻撃の違いを理解することが重要です。

XSSは、ユーザーが他のユーザーのブラウザーでドメイン上で安全でないJSを実行しているときに発生します。それが発生すると、localStorageのJWTもセッションもJCookieも安全ではありません。 CookieにhttpOnlyフラグを使用すると、Cookieに直接アクセスすることはできませんが、ブラウザはAJAXリクエストをサーバーに送信してそれらを送信します。これが発生した場合、通常は運が悪かります。これを防ぐには、ブラウザに送信された場合は、すべてのユーザー入力をエスケープしてください。

スクリプトタグまたはiframeを使用してサードパーティのJSをロードする場合、注意しない限りlocalStorageが危険にさらされる可能性がありますが、私はこれを手助けするのに十分に機能していません。

CSRFは、他のドメインがブラウザにCookieを自動的に送信させることにより、通常のHTMLフォームをサーバーに送信しようとしている場合のみです。フレームワークは、一意のランダム文字列を非表示フィールドとして挿入し、送信時にそれらを再度チェックすることにより、これを防ぎます。 localStorage内のJWTは、各ドメインが独自のlocalStorage領域を取得するため、これから安全です。

しかし、結局のところ、これはすべて、サービスが単一のドメインを使用するかどうかに依存します。その場合、httpOnly Cookieは十分に安全で設定が簡単になりますが、api.domain.com + appのような複数のドメインにサービスを広げたい場合.domain.comを使用するか、JWTをlocalStorageまたはその他のネイティブストレージ領域に保存するように強制されるネイティブアプリを追加します。

お役に立てれば!

12
Hjort-e

ここでの更新トークンの私の理解は:

リフレッシュトークンが存在するため、アクセストークンの有効期間を短くして、ユーザーがまだログインを許可されているかどうかを(アクセストークンの期限切れ時に)頻繁に確認できます。

私が間違っていたら訂正してください。

OAuth(およびOAuth 2.0プロトコル)に従うことを強くお勧めします)でベアラトークンとしてJWTを使用することについて話していると仮定すると、そうです。

JWTに追加のauth-time(認証のタイムスタンプ)クレームを使用すると、2番目のトークンをドロップして、アクセスをリフレッシュトークンとして送信することもできます(トークンが有効な場合、auth-serverは新しいアクセストークンを発行できます) &auth-timeが許可された範囲内)...しかし、確かに、標準に従うことも良いです;)

とにかく、JWTをリフレッシュトークンとして使用する前に考慮する必要のある特定の追加の側面(JWTの基本的な考え方に反することもある)があります。これは、基本的に長寿命のJWTを導入することを意味します。

  • サブジェクトごとにユーザーのログアウト/トークンの取り消しを強制するようなものが必要ですか(ユーザーが不正であると識別された場合など)?
  • 特定のトークンの取り消しなどが必要ですか(ユーザーがデバイスを紛失した場合など)?
  • ...

ユースケースに応じて、考えられるすべての影響を検討する必要があります。存続期間の長いトークンには通常、サーバー側で何らかの種類の状態を導入する必要がある(たとえば、取り消し/ブラックリストを許可する)必要があるためです。 JWTコンセプトの美しさとセキュリティは、存続期間の短いJWTにあることに留意してください。

1
jbspeakr

私は2年前にこの質問をし、その回答も受け入れました。しかし、過去2年間の私の経験と研究に基づいて、誰かが同じ質問でこのスレッドにつまずいた場合に備えて、これに答えたいと思います。

質問で述べたアプローチは、「リソース所有者パスワード資格情報」付与タイプOAuth 2.0に似ています。ただし、代わりに「認可コード付与」タイプとCookieを使用することをお勧めしますブラウザlocalStorageまたはsessionStorageの代わりにトークンを保存します このStackOverlowの回答 に、理由、実装ポイント、セキュリティに関する考慮事項および参照の詳細を記載しました。

1
Saptarshi Basu