Google Cloud Platform

ユーザー アカウント、承認、パスワード管理に効く 12 のベスト プラクティス

アカウント管理、承認、パスワード管理をうまくこなすにはコツが必要です。多くの開発者にとってアカウント管理は、十分な注意が払われていない “ダーク コーナー” になっています。製品マネジャーやお客様の中には、期待を裏切られるようなアカウント管理の経験がある方も少なくないでしょう。

幸い、Google Cloud Platform(GCP)には、ユーザー アカウント(本稿では、お客様であれ社内ユーザーであれ、システムに対して自分の身元を証明したうえでアクセスする人々を指します)の作成、セキュアな処理、そして適切な認証に役立つツールが用意されています。

この投稿記事では、Google Kubernetes Engine にホストされているウェブ サイト、Apigee の API、Firebase を使うアプリケーションなど、認証されたユーザーを扱うサービスを開発している人々のために、アカウント認証システムを安全かつスケーラブルで、使用に耐えうるものにするためのベスト プラクティスを紹介します。

1. パスワードをハッシングする

アカウント管理で最も重要なのは、パスワードをはじめとするユーザーの機密情報を安全に格納することです。この種のデータは不可侵のものとして適切に扱わなければなりません。

いかなる場合であっても、パスワードを平文で格納してはなりません。暗号学的に強く、復元不可能なハッシュでパスワードを格納するようにしましょう。ハッシングには、たとえば PBKDF2、Argon2、Scrypt、Bcrypt を使い、必ず認証情報ごとに固有のソルトを使用してください。MD5 や SHA1 など非推奨のハッシュ関数を使ってはなりません。復元可能な暗号化アルゴリズムを使ったり、独自のハッシュ アルゴリズムを作ろうとしたりするのも厳禁です。

システムはいずれ不正利用されると想定して設計することが重要です。「もし自社データベースが流出したら、このサービスやユーザーが使っている他のサービスでユーザーの安全とセキュリティが脅かされるのではないか。漏洩が発生したときの被害を緩和するために何ができるのか」ということを自問自答しましょう。

もう 1 つ重要なポイントがあります。平文のパスワードが再現できるようであれば(パスワードの入力直後を除く)、実装に問題があるということです。

2. 可能なら、サードパーティの ID プロバイダーを許可する

サードパーティの ID プロバイダーを使用すると、信頼できる外部サービスにユーザーの認証を任せることができます。よく使われる ID プロバイダーは Google、Facebook、Twitter などです。

Firebase Authentication などのプラットフォームを使えば、既存の内部認証システムとともに外部 ID プロバイダーを実装できます。Firebase Authentication には、管理の簡素化、攻撃面の縮小、マルチプラットフォーム SDK などの利点があります。こうした利点には後ほど触れていきます。わずか 1 日で Firebase Authentication の統合に成功した企業の事例もご覧ください。

3. ユーザー識別情報とユーザー アカウントの両概念を区別する

ユーザーとは、メール アドレスでも電話番号でも OAUTH レスポンスから与えられる一意の ID でもありません。あなたのサービスに含まれる個人固有のデータとエクスペリエンスの集積体です。適切に設計されたユーザー管理システムは、ユーザー プロフィールのさまざまな部分の間で疎結合と高凝集性を実現しています。

ユーザー アカウントと識別情報の概念をきちんと区別すると、サードパーティ ID プロバイダーを利用したり、ユーザー名の変更を認めたり、複数の識別情報をリンクして 1 つのユーザー アカウントを構成したりするための作業が大幅に簡素化されます。実務的に言い換えれば、すべてのユーザーを対象にグローバルな ID を 1 つ用意したうえで、プロフィールや認証用の識別情報を 1 つのレコードに積み上げていくのではなく、そのグローバル ID にリンクしていくとよいでしょう。

4. 1 つのユーザー アカウントで複数の識別情報を持てるようにする

ユーザーは、アカウントを重複して作ることになるかもしれないなどとは考えずに、認証画面で自分のユーザー名とパスワードを入力したり、Google ログインを使ったりするものです。同様に、サービスに複数のメール アドレスを対応づけたいと思うもっともな理由がユーザーにはあるかもしれません。ユーザー アカウントと識別情報を適切に分けていれば、1 人のユーザーに複数の識別情報をリンクするのは簡単なことです。

バックエンドは、システム内の既存アカウントにリンクされていない新しいサードパーティ アカウントをユーザーが使おうとしていると判断する前に、ユーザーがサインアップ プロセスを全部通過してきたか、一部だけしか通過していないかを判断する必要があります。これは、メール アドレスや電話番号、ユーザー名などの識別情報の入力をユーザーに求めることで簡単に実現できます。それがシステム内の既存ユーザーのものと一致した場合は、既知の ID プロバイダーを使った認証を要求し、新しい ID を既存アカウントにリンクする必要があります。

5. 長いパスワードや複雑なパスワードの使用を許可する

NIST(米国立標準技術研究所)は先ごろ、パスワードの複雑さと強度に関するガイドラインを改訂しました。パスワードの格納時には強力な暗号化ハッシュを使っている(あるいはすぐに使う)はずなので、従来の多くの問題が解決されます。

ハッシュは、入力の長さがどうであれ、決められた長さの出力を生成することから、ユーザーが望むのであれば、いくらでも長いパスワードを認めるようにすべきです。どうしてもパスワードの長さを制限する必要がある場合は、サーバーで許容される POST サイズの上限に基づくようにしてください(ただし、POST サイズの上限は一般に 1 MB 以上です)。

ハッシュ化されたパスワードは、既知の ASCII 文字の一部だけで構成されます。そうでなくても、バイナリ ハッシュは簡単に Base64 に変換できます。

こうした点を踏まえると、ユーザーが使いたいあらゆる文字をパスワードに使用できるようにするべきです。KlingonEmoji、両端に空白を含む制御文字をパスワードに含めたいユーザーがいたとしても、それを拒む技術的理由はないはずです。

6. ユーザー名に関する不合理な規則を強制しない

サイトやサービスにおいて 2~3 文字以下のユーザー名を拒否したり、隠し文字や先頭と末尾の空白を禁止したりする合理的な理由はありません。しかし一部のサイトでは、8 文字以上のユーザー名を要求したり、7 ビット ASCII 英数字以外の文字を禁止したりしています。

ユーザー名に厳格な制限を設けると開発者にとっては楽かもしれませんが、ユーザーに犠牲を強いることになり、極端な場合には一部のユーザーを取り逃がすことになります。

サービス側でユーザー名を割り当てるのが最もよいという考え方もありますが、その場合でも、ユーザー名を覚えたり人に教えたりする必要がユーザーにはあることを考慮し、ユーザー フレンドリーな名前を割り当てるようにしましょう。

英数字の ID を割り当てるときは、“Il1O0” のような間違いやすい文字は避けてください。また、無作為に生成した文字列に対して意図しない変なメッセージが入り込まないように、辞書を使って確認すべきです。自動生成のパスワードにも同じガイドラインが当てはまります。

7. ユーザー名の変更を認める

メール アカウントを提供する古いシステムやプラットフォームの中には、ユーザー名の変更を禁止しているものが驚くほどたくさんあります。廃止されたユーザー名を自動的に再利用してはならないことには非常にもっともな理由がありますが、システムを長く使ってきたユーザーの側からすると、新しいアカウントは作りたくないものの、正当な理由で別のユーザー名を必要とすることもあります。

別名を作ってその中からメインの名前を選ぶことを認め、ユーザーの希望を尊重しましょう。そのうえで必要なビジネス ルールを設けるようにします。ルールとしては、ユーザー名の変更を年 1 回に制限したり、メインのユーザー名以外のものを表示することを禁止したりといったことが考えられます。メール プロバイダーは、ユーザーがアカウントから古いユーザー名を切り離すか、古いユーザー名の切り離し自体を禁止する前に、リスクの周知徹底を図るべきです。

プラットフォームに適したルールを選ぶとともに、ユーザーが時間とともに成長、変化することを認めるようにしましょう。

8. ユーザーにアカウントの削除を認める

驚くべきことに、ユーザーが自分でアカウントとデータを削除しようとしても、多くのサービスではその手段が用意されていません。ユーザーがアカウントを永遠に閉じて個人データをすべて削除したいと思う理由はいくつもありますが、多くのサービスではそれが叶わないのです。

この解決にはセキュリティとコンプライアンス ニーズとの間でバランスを取ることが必要ですが、規制が設けられている環境の大半ではデータの保存に関する具体的なガイドラインが設定されています。コンプライアンスやハッキングの問題を防ぐ方法としては、アカウントが自動削除される日時をユーザーに指定してもらうことが一般的です。

データを適切なタイミングで削除してほしいというユーザーの要望に応えることが法的に義務づけられている場合もあります。データ流出を起こしたときに「閉じた」アカウントからの漏洩があると、問題が一気に深刻化することがあります。

9. セッションの長さを意識的に決める

セキュリティと認証で見過ごされがちなのが、セッション時間の長さです。Google の場合、ユーザーが本物だということの確認に多くの労力を費やし、特定の事象や行動に基づいてダブルチェックを行います。ユーザーは、段階を追ってセキュリティを強化することができます。

サービスを提供する側には、必須というほどではないアナリティクス上の目的でセッションを無制限に開いたままにしておく十分な理由があるかもしれませんが、一定期間が過ぎたら、パスワード、第 2 要素、その他のユーザー認証を求めるようにすべきです。

再認証せずにサービスを放置していられる時間をどれくらいにすべきかを検討しましょう。誰かがパスワード リセットを要求したときには、すべてのアクティブ セッションでユーザーの身元を確認してください。ユーザーがプロフィールの重要な部分を変更したり、機密性の高い操作を行ったりしたときには、認証や第 2 要素の入力を要求しましょう。複数のデバイスや場所からの同時ログインを禁止することが妥当かどうかも検討すべきです。

ユーザー セッションが時間切れになる場合や、サービスの再認証が必要になる場合は、リアルタイムでプロンプトを表示するか、未保存の操作内容を格納するためのメカニズムを提供してください。入力フォームのサブミット後にすべての入力が失われて再ログインが必要になったりすると、ユーザーは非常にイライラします。

10. 2 段階認証を使用する

2 段階認証(二要素認証 : 2FA)の方法を選択する際は、ユーザーがアカウントを盗まれたときに実際にどのような影響があるかを考慮してください。

取るに足らないようなサービスの場合、SMS を使った 2FA をユーザーは最もセキュアな方法として受け入れるかもしれませんが、NIST はこの形の 2FA を非推奨にしています。合理的な範囲で最もセキュアな 2FA 認証を選択しましょう。サードパーティの ID プロバイダーを有効にして、その 2FA におんぶさせてもらえば、さほど労力やお金をかけずに簡単にセキュリティを強化できます。

11. ユーザー ID では大文字と小文字を区別しない

ユーザーは、自分のユーザー名において大文字と小文字をどのように使い分けるかを気にしませんし、覚えてさえいないこともあります。したがって、ユーザー名の大文字と小文字を区別するのはやめましょう。ユーザー名とメール アドレスを小文字に変換し、入力については比較の前に小文字に変換するほうが簡単です。

ユーザーが使うデバイスの中ではスマートフォンの割合が増えてきています。大半のスマートフォンは平文フィールドの自動訂正と自動的な大文字変換をサポートしており、UI レベルでこの動作を禁止するのは望ましくなく、うまくいかないこともあるでしょう。意図せず大文字に変換されたメール アドレスやユーザー名にも対応できるように、サービスを堅牢にしておくべきです。

12. セキュアな認証システムを作る

Firebase Authentication などのサービスを使えば、セキュリティ問題の多くは自動的に処理されます。とはいえ、サービスは不正使用の防止に向け、適切に設計、構築する必要があります。特に注意すべきは、パスワードを復旧するのではなく再設定することや、アカウントのアクティビティの詳細なロギング、ログイン試行の速度制限、ログイン失敗が多すぎるときのアカウントのロックアウト、未認識のデバイスや長時間アイドル状態だったアカウントに対する 2 段階認証の要求などです。

認証システムの安全性を高めるうえで検討すべきことは、もっとたくさんあります。詳細は以下の参考文献を参照してください。

参考文献

アカウントと認証管理システムの開発、更新、マイグレートの方法を詳しく教えてくれる優れたリソースがたくさん用意されています。出発点として以下をお勧めします。
* この投稿は米国時間 1 月 29 日、GCP Solutions Architect である Ian Maddox によって投稿されたもの(投稿はこちら)の抄訳です。

- By Ian Maddox, GCP Solutions Architect