web-dev-qa-db-ja.com

RESTful APIでのトークンの更新/セッションの有効期限の処理

ユーザー認証にJWTトークンを使用するRESTful APIを構築しています(loginエンドポイントによって発行され、その後すべてのヘッダーで送信されます)。トークンは一定時間後に更新する必要があります(renewエンドポイントを呼び出し、更新されたトークン)。

トークンの有効期限が切れる前にユーザーのAPIセッションが無効になる可能性があるため、すべてのエンドポイントは、1)トークンがまだ有効であり、2)ユーザーのセッションがまだ有効であることを確認することから始まります。クライアントがトークンをローカルに保存するため、トークンを直接無効にする方法はありません。

したがって、すべてのエンドポイントは、クライアントに2つの可能性のある状態を通知する必要があります。1)トークンを更新するときです。2)セッションが無効になり、システムへのアクセスが許可されなくなります。私のエンドポイントが2つの条件のいずれかが発生したときにクライアントに信号を送るための2つの代替案を考えることができます(クライアントがいずれかのオプションに適応できると仮定します)。

  1. トークンの期限が切れ、renewエンドポイントを呼び出して200(ok)コードを返すときに、セッションが無効になった場合はhttp 401コード(無許可)を返すか、412コード(前提条件が満たされていない)を返します。
  2. セッションが無効であるか、トークンの有効期限が切れていることを通知するために401を返します。この場合、クライアントはすぐにrenewエンドポイントを呼び出し、200を返した場合はトークンが更新されますが、renewも401を返した場合は、クライアントがシステムの外にいることを意味します。

上記の2つの選択肢のどちらをお勧めしますか?より標準的で理解しやすい、および/またはRESTfulなものはどれですか。または、まったく別のアプローチをお勧めしますか?どちらのオプションでも明らかな問題やセキュリティリスクはありますか?回答にあなたの意見を裏付ける外部参照が含まれている場合の追加のポイント。

[〜#〜]更新[〜#〜]

皆さん、本当の質問に集中してください-更新/セッションの無効化を通知するための2つのhttpコードの選択肢のうち、どちらが最適ですか?私のシステムがJWTを使用しているという事実を気にしないでくださいおよびサーバー側セッション。これは、非常に具体的なビジネスルールに対する私のAPIの特殊性であり、私が助けを求めている部分ではありません;)

17
Óscar López

これはauthenticationauthorizationの場合のように聞こえます。

JWTは、要求の発信者に関する暗号で署名されたクレームです。 JWTには、「このリクエストはユーザーXを対象としています」や「ユーザーXは管理者の役割を持っている」などのクレームが含まれる場合があります。パスワード、署名、およびTLSを介してこの証明を取得および提供することは、authenticationのドメインであり、本人であることを証明します。

それらがサーバーに対してmeanと主張していること-特定のユーザーとロールに許可されていること-authorizationの問題です。 2つの違いは、2つのシナリオで説明できます。ボブが自分の会社の倉庫の制限された保管区画に入りたいと考えているが、最初に彼はジムという名前の警備員に対処しなければならない。

シナリオA-認証

  • Bob:「こんにちはジム、制限付きストレージに入りたいのですが。」
  • ジム:「バッジをお持ちですか?」
  • Bob:「いや、忘れた」
  • ジム:「申し訳ありませんが、バッジがないとエントリーできません。」

シナリオB-承認

  • ボブ:「こんにちは、ジム、制限付きストレージに入りたいのですが、これが私のバッジです。」
  • ジム:「ねえボブ、ここに入るにはレベル2のクリアランスが必要です。申し訳ありません。」

JWTの有効期限は、他のユーザーがそれらを盗むのを防ぐために使用される認証デバイスです。すべてのJWTの有効期限が5分の場合、それらが盗まれても、すぐに役に立たなくなるため、それほど大きな問題にはなりません。ただし、説明する「セッションの有効期限」ルールは、承認の問題のように聞こえます。状態の一部の変更は、ユーザーXが以前は実行可能であった何かを実行することをもはや許可されないことを意味します。たとえば、ユーザーBobが解雇された可能性があります。単にBobであるだけではもはや会社に対する権限が与えられないため、バッジが彼がBobであると言っていても問題ありません。

これら2つのケースには、401 Unauthorized403 Forbiddenという別個のHTTP応答コードがあります。あいにく名前が付いた401コードは、資格情報の欠落、期限切れ、または失効などの認証の問題用です。 403は認証用で、サーバーはあなたが誰であるかを正確に知っていますが、あなたがしようとしていることをすることは許可されていません。ユーザーのアカウントが削除された場合、エンドポイントでJWTを使用して何かを実行しようとすると、403 Forbidden応答が返されます。ただし、JWTが期限切れの場合、正しい結果は401 Unauthorizedになります。

一般的なJWTパターンは、「長命」と「短命」のトークンを持つことです。存続期間の長いトークンは、存続期間の短いトークンと同様にクライアントに保存されますが、スコープが制限されており、許可システムでonlyを使用して、存続期間の短いトークンを取得します。名前が示すように、存続期間の長いトークンには非常に長い有効期限があります。それらを使用して、何日も何週間も新しいトークンを要求できます。短命のトークンとは、あなたが説明しているトークンであり、非常に短い有効期限でシステムと対話するために使用されます。存続期間の長いトークンは、Remember Me機能を実装するのに役立ちます。そのため、新しい存続期間の短いトークンを取得するために5分ごとにパスワードを入力する必要はありません。

あなたが説明している「セッションの無効化」の問題は、存続期間の長いJWTを無効化しようとするのと同じように聞こえます。そのようなシステムでは、取り消された長期間有効なトークンで資格情報を取得しようとすると、401 Unauthorizedが発生します。これは、ユーザーが技術的に資格情報を取得できる可能性があるが、使用しているトークンがタスクに適していないためです。次に、ユーザーがユーザー名とパスワードを使用して新しい長期トークンを取得しようとすると、システムから追い出された場合、システムは403 Forbiddenで応答する可能性があります。

22
Jack

APIセッションは、RESTfulな世界ではまったく存在すべきではないものです。 RESTfulな操作はステートレスであることが想定されており、セッションには状態が含まれるため、RESTfulな世界では場所がありません。

JWTは、ユーザーがまだエンドポイントにアクセスする資格があるかどうかを判断する唯一の方法である必要があります。セッションは、その中でまったく役割を果たすべきではありません。含まれている場合、RESTful APIはありません。

RESTful APIを目的としている場合に行う必要があるセッションを完全に排除し、認証要素としてJWTのみを使用する場合、ユーザーはエンドポイントの使用を許可されるかどうかのどちらかです。その場合、401 Unauthorized応答コードが適切です-renewエンドポイントをgrant_type=refresh_tokenまたは使用している更新のIDで呼び出す必要があります.

更新:

コメントから、現在使用しているJWTの検証フローが正しくないようです。検証は次のようになるはずです。

  Client        RESTful API      JWT Issuer
     |              |                |
     |----- 1. ---->|                | 
     |              |------ 2. ----->|-----
     |              |                | 3. |
     |              |<----- 4. ------|<----
-----|<---- 5. -----|                |
| 6. |              |                |
---->|----- 7. ---->|                |
     |              |------ 8. ----->|-----
     |              |                | 9. |
     |              |<----- 10. -----|<----
     |              |                |
     |              |------          |
     |              | 11. |          |
     |<---- 12. ----|<-----          |
     |              |                |
     .              .                .

1. Ask RESTful API for a JWT using login endpoint.
2. Ask Issuer to create a new JWT.
3. Create JWT.
4. Return JWT to the RESTful API.
5. Return JWT to Client.
6. Store JWT to append it to all future API requests.
7. Ask for data from API providing JWT as authorization.
8. Send JWT to Issuer for verification.
9. Issuer verifies JWT.
10. Issuer returns 200 OK, verification successful.
11. Retrieve and format data for Client.
12. Return data to Client.

サーバーRESTful APIは、承認として送信されているトークンの有効性を確認する必要があります。それはClientの責任ではありません。現在、これを行っていないようです。この方法でJWTの検証を実装すると、セッションはまったく必要ありません。

16
Andy

だから、私はあなたがすでにセッションでREST慣習を破っているとき、どのアプローチが最もRESTfulであるかについて心配することはあまり意味がないと告白しますが、満足できることを理解していますあなたのビジネス要件。

RESTの観点から見ると、クライアントは認証されているか、そうでないかのどちらかです。アーキテクチャは理由(不必要な状態を注入している)をあまり気にしないので、主な質問に答えるには、エンドポイントを更新する必要があります。ログインしたクライアントは常にJWTを送信し、サーバーは常にそれを検証し、アクション200、201などに基づいて適切な成功コードを送信して受け入れるか、401または403で拒否します。適切な。

これで、JWTは何らかのアカウントに関連付けられます。そのアカウントはロックまたは調整されている可能性があるため、トークン自体は有効である可能性がありますが、アクションは他の場所で拒否されます。ビジネスルールのためにユーザーアカウントがロックされている場合でも、クライアントに提供する情報の量によっては、401または403のままです(企業ごとに意見が異なります)。

最後に、アカウントがロック解除されて有効である可能性があるが、JWTを取り消す必要があると主張している場合は、401または403をそのまま使用して、無効なJWTの証明書失効リストのようなものを維持できます。 、JWTが期限切れになったときに自分自身をクリーンアップする限り(ほとんどのデータベースにそれを行う方法があるか、アプリのコードにイベントを含めることができます)。

1
Paul