web-dev-qa-db-ja.com

このパスワードなしの認証フローは安全ですか?

ユーザーがメールのリンクをクリックするだけでログインできるモバイルアプリにパスワードなしの認証フローを実装したいのですが、Slackが認証を処理する方法と似ています。この実装では、nodejwtを使用します。

安全なデザインは思いついたと思いますが、何か不足していると思います。コミュニティからの批評が大好きです。

さあ行こう:

  • ユーザーがモバイルアプリを開きます。
  • ユーザーがローカルストレージにトークンを持っているかどうかを確認します。
  • その場合、そのトークンをヘッダーに追加して、アプリのホームページに送信します。
  • それ以外の場合は、開始するために電子メールを入力するように促します
  • [送信]をクリックすると、サーバー上のrequestMagicLinkエンドポイントにPOST that email addressします。
  • サーバーはデータベースにそのemail addressを持つユーザーを確認します
  • そのメールのユーザーを見つけたら、そのユーザーからidを取得します
  • ユーザーが存在しない場合は、新しいユーザーを作成し、それを取得しますid
  • JWTを使用して、id1 hourの後に期限切れになるsecretでトークンを生成します
  • そのトークンは、メールのリンクを介してユーザーに送信されます。
  • クリックされると、そのリンクはmagicLoginエンドポイントのクエリパラメーターにtokenを含むGETリクエストをサーバーに送信します
  • JWTとsecretを使用して、トークンが正しいことを確認します。
  • 検証に失敗した場合、ユーザーを画面にリダイレクトし、開始するために電子メールでプロンプトを表示します。
  • 成功した場合は、idsecret that doesn't have an expirationを使用して新しいJWTトークンを生成し、それをリダイレクトするURLのパラメーターでユーザーに返します。アプリの成功ページに移動します。
  • アプリは、ユーザーがログアウトすることを選択し、ユーザーがホームページにリダイレクトされるまで、パラメーターからトークンを取得してローカルストレージに保存します。
  • APIへのリクエストはすべてヘッダーにトークンが含まれるようになり、ユーザーは問題なく進むことができます。

編集(追加の考えを追加):より安全にするために私が検討しているもの:トークンを2つに分割し、半分をモバイルデバイスに送信し、残りの半分をメールに送信するとどうなりますか。このようにして、その電子メールへのアクセスとその特定のデバイスへのアクセスを持つユーザーのみが認証できます。

7
klinore

フロー(マジックリンク)の主な概念は、認証のためのよく知られたパスワードなしの代替手段の1つです。一般的なコンセンサスは、このようなスキームのセキュリティ(コメントに記載されている)のセキュリティは、「パスワードを忘れた」電子メールリセットメカニズムを許可するシステムのセキュリティよりも悪くないようです。これは、障害の原因が電子メール部分にあることを考えると理にかなっています。

電子メールサーバーは通常暗号化されておらず、メールはユーザーのメールクライアントなどの安全でない場所に保存される可能性があります。また、ユーザーがメールアカウントを安全に設定する方法も制御できません。 どれほど難しいか パスワードのリセットを安全に実装することは、(それと比較されることが多いため)役立つかもしれません。最後に、これが心配する必要があるかどうかは、実際には脅威モデルとアプリのデータの値に依存しています。

マジックリンクやその他のパスワードなしのスキームをサポートしていることがわかっているソースのほとんどは、このシステムの独自の実装をプッシュすることに強い関心を持つベンダーからのものです(例 Authokta =)そして、Amazon-cognitoのようにすでにサポートしているビッグネームがいくつかあります。このスタックから同様の質問を確認することもできます。

Webアプリでのパスワードなしの認証-どのくらい安全ですか?

電子メールによるパスワードなしのログイン-セキュリティに関する考慮事項

カスタム実装に関しては、言及する価値のあるいくつかの懸念事項があります。

  • 既存のメールアドレスがない場合は、ユーザーを作成しないでください。エンドポイントとWebフォームは定期的にスパム送信され、DBはジャンクでいっぱいになっています。
  • メールでトークンを送信する必要はなく、リンクを直接送信する必要がある場合があります。リンクURLがランダムに生成され、有効期限が使用不可に設定されていることを確認してください。
  • 上記のとおり、電子メールは簡単に危険にさらされる可能性があるため、緩和するために有効期限を短く設定する必要があります。ほとんどの場合、ユーザーはとにかくメールに直接アクセスするので、5〜10分の範囲に保ちます。
  • ログイン後、JWTは長いものであっても有効期限が切れているはずです。トークンを無期限に有効にしてほしくない。

正直なところ、回避できるのであれば自分で設定することはお勧めしません。この機能をすでにサポートしているライブラリを探してみてください。

6
AlphaD

だからあなたがしようとしていることは、新しい「セキュリティプロトコル」を実装することです。 stackexchangeに関する質問よりも多くの調査とQAが必要だと思うので、私はこれについて悪い気持ちを抱いています。新しいプロトコル(Auth2)またはアルゴリズム(AES)は、一般に「承認済み」または「安全」と見なされる前に、調査に多くの時間と労力を費やします。

一般に、メールはアクセストークンを共有する最良の方法ではないと思います。たとえば、シークレットを使用してトークンを作成し、このトークンをクエリパラメータとしてメールアドレスにリンクを送信すると、ユーザーがこのリンクをクリックすると、ユーザーは認証済みと見なされます。また、クリアテキストのパスワードをユーザーに送信し、クエリパラメータを介してこのパスワードをネットワークに送信しますか?それが本当に悪い習慣であるのであなたがそうしないことを望みます、しかし私があなたが正しいと理解しているなら、あなたはまさにこれをしたいと思います:メール経由でクリアテキストであなたのアプリへのユーザーアクセスを提供する「チケット」を送ってください。暗号化されているとしても、それは良い習慣ではありません。

また、不明なメールアドレスでrequestMagicLink-endpoitにPOSTを受け取った場合、新しいユーザーを自動的に「作成」しないでください。これにより、攻撃者がメールでデータベースにスパムを送信する機会が与えられます。 -アプリでメールアドレスを使用したくないユーザーからのアドレス;-)

私が自発的に考える他のいくつかの落とし穴:

  • メールの送信は常にトリッキーです-メールは暗号化されていないため、ハッカーは偽のメールをユーザーに送信したり、送信されたメールをキャプチャして読み取ることができます
  • リダイレクトは常にトリッキーです-ハッカーは、適切に実装されていないシステムを侵害して、ユーザーの制御下にある侵害されたWebサイトにユーザーをリダイレクトできます。
  • プロセスの存続期間をできるだけ短くします-ユーザーが10分後にメールのリンクをクリックしなかった場合は、拒否します
  • GETリクエストでも他のすべてのメソッドでも、クエリパラメータを介してプライベートデータを送信しないでください
  • トークンを複数回使用できる場合のリプレイ攻撃の可能性

ユーザーがパスワードを入力できないようにするために独自のメカニズムを作成するのではなく、何年も使用および検証されている認証のベストプラクティスプロトコルおよび方法を使用することをお勧めします。そうでなければ、本当にこのようにしたいのであれば、専門家と協力し、メカニズムのセキュリティを確保するために多くの時間と労力を費やす必要があります。

2
Alex

アクセストークン/シークレットをローカルストレージに配置しない

アクセストークンをローカルストレージに配置すると、JavaScriptを介してアクセスできます。つまり、トークンは[〜#〜] xss [〜#〜]Cross-Site Scripting)で盗まれる可能性があります。また、認証はJavaScriptが有効になっている場合にのみ機能します。

悪意のあるブラウザ拡張機能がアクセストークンを抽出し、攻撃者に送信する可能性があります。これは、あなたが言うように、アクセストークンの有効期限が切れていない場合に特に重要です。

XSSのリスクを回避するには、HttpOnlyフラグが設定されたトークンにCookieを使用することをお勧めします。 (Secureフラグを使用して、すべての接続にHTTPSを強制することもできます)

注:ローカルストレージの代わりにCookieを使用する場合は、考慮して -[〜#〜] csrf [〜#〜]Cross-Site Request Forgery)攻撃。


便利なリソース:

1