企業向けのモバイルアプリケーションを開発しています。会社の全員が @company.com の電子メール アドレスを持っています。アプリ自体は機密情報であるため、従業員のデバイスにのみインストールされます。このアプリは、外部サーバーと通信してデータを保存および取得します。
理想的には、ユーザーがパスワードなしで電子メール アドレスを入力するだけでアプリにログインできるようにすることを実現したいと考えています。これが私の現在の考えです:
- 新規ユーザーが特定のデバイスで初めてアプリを開き、メール アドレスを入力します。電子メール アドレスは、アプリケーションに埋め込まれた静的トークン (アプリケーションのすべてのインスタンスで同じ) と共にサーバーに送信されます。
- サーバーは、トークンと、電子メール アドレスが @company.com であることを確認します。クライアントは、そのユーザーとデバイスでのみ使用する新しいトークン/キーで応答します。これは、クライアントがローカルにプレーン テキストで保存します。そのキーは事実上、ユーザーのパスワードです。これはハッシュされ、サーバー データベースに保存され、無効としてマークされます。
- この時点で 2 つの可能性があります。
- サーバーは、新しいデバイスにログインすることを確認する電子メールをそのアドレスに送信します。電子メールにはリンクが含まれており、クリックするとキーが有効とマークされます。アプリに埋め込まれたトークンが誰かに発見された場合に、スパムの被害に遭わないように、新しいデバイス リクエストのレートを制限する必要があります。
- 管理者は、新しいデバイスのリクエストを明確に承認します。
- サーバーへの後続のすべてのクライアント要求には、キーが含まれている必要があります。
すべての通信が SSL 経由であると仮定すると、これは安全な戦略のように聞こえますか? より安全でシンプルなアプローチはありますか?
さらに、クライアント側に保存されるトークンを生成する最良の方法は何ですか? アプリを初めて使用するときだけユーザーにメール アドレスを入力してもらいたいので、このトークンは変更されることはないと思います。Drupal の drupal_get_token() に大まかに基づいた現在のアルゴリズム (PHP) を次に示します。
// Usage: get_token($email) or get_token($client_token)
function get_token($value = '') {
$salt = hash('sha256', 'Some static, predefined phrase');
$hmac = base64_encode(hash_hmac('sha256', $email, $salt, TRUE));
return $hmac;
}
ご覧のとおり、並列攻撃に対しては保護されません (たとえば、誰かが定義済みのフレーズとアルゴリズムを見つけ出し、データベースにアクセスできた場合、ハッシュを生成し、データベースに保存されているものと比較できます)。キー値はすでに長いです。これは、通常のパスワードに対する場合ほど効果的ではないと思います。さらに、攻撃者がデータベースにアクセスできる場合にまだアクセスできない動的ソルトを作成する方法がわかりません(または、データベースにアクセスするとデータが公開されるため、その時点で問題になるかどうかは正直に言えば)とにかく秘密を守ろうとしています)。