私はWebアプリのバックエンドを構築しています。新しいユーザーがサイトにアクセスしてSign Upボタンをクリックすると、ユーザーはユーザー名とパスワードを要求する非常にシンプルなフォームに入力し、彼らは提出します。これにより、サーバーに確認メールをそのメールアドレスに送信するように求められます。次に、メールを確認し、リンク(メールを確認する)をクリックすると、ログインページに転送され、必要に応じてサインインできます。
メールを検証するには、サーバーがメールを生成するときに、検証トークン(おそらくUUID)を作成(および保存)して添付する必要があります。メールのこのリンクにリンクすると、リンクは次のようになります。
ここで、vt=12345
は「確認トークン」です(おそらくUUIDです)。したがって、ユーザーがこのリンクをクリックすると、私のGET v1/users/verify
エンドポイントがトークンを確認し、トークンが有効であることを確認して、ユーザーを「アクティブ化」するためにいくつかのDB更新を行います。ログインできます。
ユーザーが電子メールの受信を解除する場合、またはパスワードを思い出せず、ログインするためにパスワードを回復する必要がある場合の同様のシナリオ。
ユーザーはメールの受信を停止したいが、それでもアプリを使用したい。送信する週刊ニュースレターの「Unsubscribe」リンクをクリックします。このリンクには、上記の確認トークンと同様に、サーバー上に生成され+保存され、ユーザーの電子メールからの退会リクエストを認証するために使用される、同様の「退会トークン」が含まれている必要があります。
ここで、ユーザーは自分のパスワードを忘れており、それを回復する必要があります。そのため、ログイン画面で[Forgot my password]リンクをクリックすると、メールアドレスを入力するフォームが表示されます。サーバーはそのアドレスにメールを送信します。彼らはこのメールをチェックし、新しいメールアドレスを入力できるフォームへのリンクが含まれています。このリンクには、「リセットトークントークン」を含める必要があります。これは、上記の確認トークンと同様に、サーバー上で生成および保存され、ユーザーのパスワード変更リクエストを認証するために使用されます。
したがって、ここには解決すべき3つの非常に類似した問題があり、すべて "one-time only(OTO)security tokens"と呼ばれるものを使用する必要があります。これらのOTOトークン:
security_tokens
テーブルに)私が思いついた解決策はシンプルで、ほとんどシンプルすぎました。
トークンについては、ランダムなUUID(36文字)を生成して、次のフィールドを持つsecurity_tokens
テーブルに格納しています。
[security_tokens]
---
id (PK)
user_id (FK to [users] table)
token (the token itself)
status (UNCLAIMED or CLAIMED)
generated_on (DATETIME when created)
サーバーがそれらを作成すると、それらは「クレームされません」。ユーザーがテーブル内のリンクをクリックすると、「クレーム済み」になります。バックグラウンドワーカージョブは定期的に実行され、CLAIMEDトークンをクリーンアップするか、「generated_on
フィールドに基づいて」「期限切れ」のUNCLAIMEDトークンを削除します。アプリは、以前にクレームされた(まだクリーンアップされていない)トークンも無視します。
私はこのソリューションはうまくいくと思いますが、私はスーパーセキュリティの人ではなく、このアプローチが心配です:
上記の2番目のように、死んでいる単純なUUIDではなく、ハッシュ/ HMAC/JWT関連のメカニズムを使用する必要があるのかどうか疑問に思っています。たぶん、これらのトークンにCLAIMステータスと有効期限を安全/不変の方法で含めるようにする方法を見つけた賢い暗号/セキュリティ担当者がいるかもしれません。
あなたが説明したことにいくつかの懸念があります:
security_tokens
テーブルに「目的」を記述しないでください。これにより、(コードによっては)意図されたものとは異なる目的で誰かがトークンを使用できるようになります。別の解決策は、(たとえば)JWTを使用し、署名付きデータに含めることです。
JWT自体が、有効期限を管理するための機能を提供します。これは「二重に費やす」ことができるトークンを生成しますが、それらが電子メールの検証または購読解除のためである場合、それは問題ではないことに注意してください。 (同じメールを2回検証することは問題ですか?)
これらのトークンの場合、必要なのはアプリケーションサーバーに格納されたシークレットだけであり、トークンを生成または使用するための追加のデータベース書き込みは発生しません。 (これもまた、スケーリングの問題であるため、アプリケーションに適用される場合と適用されない場合があります。)