存続期間の短いアクセストークンと存続期間の長いリフレッシュトークンを使用して、REST APIのトークンベースの認証システムを実装しています。これは、関連するAPIエンドポイントの抽象的な概要です(HTTPSはすべてのエンドポイントに適用されます)。
エンドポイント:
POST /register/
POST /login/
POST /logout/
POST /password/change/
実装:
POST /register/
:
- リクエスト:クライアントがユーザー名、メール、パスワードをJSONで送信します。
- サーバーアクション:
- 入力を検証し、データベースにユーザーを作成します(ユーザーID、ユーザー名、電子メール、パスワードハッシュを格納します)。
- JWT形式で短期間有効なアクセストークンを作成します(ユーザーID、発行日、有効期限が含まれます)。
- 長期間有効な更新トークンをUUID文字列として作成し、データベースに保存します(ユーザーIDと更新トークンを保存します)。
- 応答:サーバーはJSONでアクセストークンと更新トークンを返します。
POST /login/
:
- リクエスト:クライアントはJSONでユーザー名とパスワードを送信します。
- サーバーアクション:
- 入力を検証し、データベースをチェックして資格情報が有効かどうかをチェックします。
- 資格情報が有効な場合、前述のように、有効期間が短いアクセストークンと有効期間が長いリフレッシュトークンを作成します。
- レスポンス:と同じで
/register/
、アクセストークンと更新トークンをJSONで返します。
POST /logout/
:
- 要求:クライアントはヘッダー内の更新トークンをトークン
Authorization
として送信しBearer
ます。 - サーバーアクション:
- 更新トークンデータベースをチェックして、更新トークンを検証します。
- データベースから更新トークンを削除します。
注:これにより、アクセストークンは有効なままになりますが、有効期間は短いため(1時間程度なので、問題ないはずです)。
- 応答:ログアウト要求がJSONで正常に処理されたかどうかを返します。
POST /password/change/
:
- リクエスト:クライアントはアクセストークンを
Authorization
ヘッダーとしてBearer
トークンとして送信し、古いパスワードと新しいパスワードをHTTPS経由でJSONで送信します。 - サーバーアクション:
- アクセストークンをデコードしてユーザーを取得し、ユーザーの古いパスワードをデータベースで確認します。
- データベース内のユーザーのパスワードハッシュを新しいパスワードのハッシュに設定します。
- リフレッシュトークンデータベース内のユーザーに関連付けられたすべてのリフレッシュトークンを削除して、基本的に既存のセッションをログアウトします(有効期間の短いアクセストークンを残します)。
- 応答:パスワード変更リクエストがJSONで正常に処理されたかどうかを返します。
質問:
- このアプローチは安全ですか?具体的には:
- HTTPSを介して行われる場合、JSONを介したユーザー名とパスワードの送信は安全ですか?無許可のドメインがこのエンドポイントに電話をかけることをどのように防ぐことができますか?さらに、プログラムによるログインを防ぐにはどうすればよいですか?
- 更新トークンをデータベースに保存する前にハッシュ化する必要がありますか、それとも単なる偏執狂ですか?
- クライアントがWebブラウザーの場合、更新トークンをクライアントに安全に保存するにはどうすればよいですか?
- リフレッシュトークンを保存するための1つのアイデアは、ユーザーがログインすると、リフレッシュトークンをクライアントに送信するだけでなく、サーバーがトークンをフラグ
HttpOnly
付きのCookieに保存することsecure
です。承認は引き続きAuthorization
ヘッダーを介して行われますが、クライアントが最初に読み込まれるときにGET
、Cookieに有効な更新トークンが含まれているかどうかを確認するリクエストをエンドポイントに送信でき、有効な更新トークンが含まれている場合はJSONでユーザーに返します。つまり、Cookieが実際に使用されるのは、Cookie内の更新トークンをクライアントに返すときだけです。このアプローチは安全ですか?Cookieからリフレッシュトークンを要求するときに副作用がないため、CSRFを防ぐことができると思いますが、攻撃者がリフレッシュトークンを傍受する別の方法があります(HTTPSを想定)?
- リフレッシュトークンを保存するための1つのアイデアは、ユーザーがログインすると、リフレッシュトークンをクライアントに送信するだけでなく、サーバーがトークンをフラグ