UIデザインにセキュリティ要件を反映させる(認証機能編)

KeijiroToyoda
19 min readFeb 24, 2022

はじめに

こんにちは。株式会社Flatt Securityの @toyojuni です。 職業はUIデザイナーですが、現在はデザイン以外のあれこれの仕事の方が多いです。

本記事では、Webサービスにおけるシンプルな認証機能(サインアップ/サインイン/パスワードリセット)を題材にして、UIデザイナーがデザインカンプ作成時に気をつけるべきセキュリティ観点を6つ紹介しようと思います。

TL;DR

  1. メールアドレスが本人のものであるかの確認をサインアップフローに挟む
  2. 多要素認証やreCAPTHA等セキュアなオプションに関して検討する
  3. パスワード入力はマスクする
  4. エラーメッセージやリアルタイムバリデーションでパスワード強度は適切ものを検討する
  5. 第三者に登録情報を可視化しない
  6. サインインにおける試行回数制限をデザインに反映する

なぜデザイナーがセキュリティの話を?

デザイナーがデザインカンプを作成する時に、セキュリティ要件が反映されていないような設計・仕様になっていると、実装時にエンジニアからダメ出しをもらい、最悪画面構成のレベルから手戻りになってしまう可能性があります。

また、最悪のケースとして脆弱な仕様が見過ごされたまま実装され、そのままリリースされてしまうことがあります。

まずUIデザインよりも上流の工程で完璧な要求・要件(セキュリティのような非機能要件を含む)・仕様が定義されている場合にはそのような心配は理論上ないかもしれませんが、現実は完璧ではありませんし、昨今はデザイナーが作成したプロトタイプを起点にUXを重視したプロダクト開発を行う組織というのも少なくないかと思います。

そう考えると、開発組織としてのスループット最大化のためにデザイナーが最低限のセキュリティ知識を持つというのも妥当性がありそうです。(もちろん、大前提としてプロダクトや顧客を守るためにはデザイナーに限らない全員がセキュリティに対して当事者意識を持つ必要があるでしょう。)

認証機能をテーマに選んだ理由

認証機能、すなわちサインアップやサインインはその業種に関わらずほとんどのWebサービスが持つ、非常に普遍的な機能です。普遍的だからこそ、車輪の再発明を防ぐためにも必要な知識は定型化されているべきです。

例えば、セキュリティ以外でデザイナーが意識すべきことは以下のようなツイートで(細かな点も考えるとこれで全てでは無いにせよ)まとまっていますよね。

また、先日会社の技術ブログでエンジニア向けに似たような発信を行いましたが、こちらも非常に好評で、記事の公開後1週間で10,000PVを突破しました。

セキュリティ屋としては「定番」の内容でも、世の中に十分に浸透されているとは言えないのかもしれません。認証機能にまつわる話は、車輪の再発明を防ぐために、発信する価値のある情報かなと思っています💪

なお、認証機能開発における車輪の再発明をしないという意味では、独自開発を行わずにIDaaSを利用するという選択肢もありますね。実際、弊社の提供する「KENRO」というサービスの認証は「Auth0」を採用しています。

記事のゴール

ということで、本記事のゴールは「認証機能デザインの際にセキュリティ要件起因の手戻りを産まないようにする」こと。そして「UIデザイナーがセキュリティと仲良くなる一歩を踏み出す」です。

普段の業務の中ではセキュリティを意識することは少ない人が多いかなと思いますので、本記事で興味を持ってもらえれば幸いです。

本記事のカバー範囲

今回の記事のコンセプトは「デザインカンプにセキュリティ要件を反映させる」なので、あくまでGUI上に現れる話題だけが取り扱う範囲となります。また、メールアドレスとパスワードのみのシンプルな認証を前提とします。

フロントエンドのうちGUIに現れない部分、サーバーサイドの話題は取り扱っていないので、本記事を読んでいいなと思ったら是非上記の弊社ブログ記事や、以下のQiitaを社内のエンジニアにシェアしてもらえたらと思います🧑‍💻

その上で「これも追加したほうがいいんじゃない?」というのがあれば是非シェアコメントなどで教えてください🙏

では、以下より観点の紹介です。

観点1: メールアドレスが本人のものであるかの確認をサインアップフローに挟む

概要

サインアップの際に連絡手段として入力されたメールアドレスが本人のものであるか、疎通確認をするステップをサインアップのフローに挟みます。

ユーザーの機微な情報を取り扱う場合、メールアドレスとパスワードを入力しただけですぐにサービスが利用開始できる仕様は推奨されません。

防ぎたいリスク

上記のQiita記事で詳しく紹介されていますが、takashi0401@example.comのような名前 + 日付 のようなメールアドレスをユーザーが使用している時、打ち間違いで他人のアドレスを登録してしまう可能性は十分にあり得ます。

この時、入力されたメールアドレスの所有者がパスワードリセット機能を悪用することでアカウントを乗っ取ることが可能になります。仮にこのサービスがECサイトで、ユーザーが氏名と住所の登録を済ませていた時点でパスワードをリセットされると、アカウントだけでなく個人情報まで第三者に漏洩する形になります。

ユーザーにまつわる機微な情報を一切入力しないカジュアルゲームのようなサービスであれば省略の選択肢も出てくるかもしれませんが、多くの場合そのような判断はできないでしょう。

このリスクに対処するため「メールアドレスがユーザー本人のものか」を確認するフローが必要になってきます。UX観点ではステップは減らしたいところでしょうが、疎通確認をしないままアカウント乗っ取りを防ぐには複雑な対応が必要になってくるので是非ともフローに織り込みたいところです。

なお、パスワードリセット機能を封印しておくことで、疎通確認タイミングは後ろにずらすことができますが、疎通確認前かつパスワードを忘れてしまったユーザーの救済ができなくなるので総合的にUXを検討してみてください。

デザイナーがすべきこと

① 疎通確認の方法をエンジニア/PMと相談する

独断で決める部分では無いと思うので、まずは相談しましょう。以下のような方法がメジャーかと思います。

  1. メールアドレスに送付したリンクをクリックしてもらう
  2. メールアドレスに送付した認証コードを入力してもらう

1は入力されたメールアドレスに対してメールで「アカウント有効化のためのリンク」を送付し、そのクリック後にサインインが可能になるパターンです。仮に第三者にメールが届いてアカウントが有効化されたとしても、その第三者はパスワードを知り得ないのでサインインはできません。

2はサインアップを行った画面で認証コードの入力フォームを表示し、一方メールアドレスには認証コードを送付するパターンです。仮に第三者にメールが届いて認証コードを知り得たとしても、その第三者は認証コードの入力画面にたどり着けません。

② 疎通確認方法が確定したら、それを織り込んで画面遷移を設計する

これはやるだけです。

1のパターンならリンククリック後の画面をデザインする必要があり、2のパターンなら認証コードの入力画面をデザインする必要があります。

おまけ: SUZURIの認証コード入力のUXが良かった話

SUZURIは2のパターンを採用しており、6桁の認証コードがメールで送付されてきます。で、その時に認証コードがメールタイトルの先頭に含まれているんですね。

このようにしてあるとわざわざメールアプリを開かずとも、スマホの通知を見るだけで認証コードの入力ができたので、体験がいいなぁと感じました。さすがペパボさんです。

また、疎通確認画面を閉じてしまった場合の指示なども丁寧に書いてあっていいですね。参考になります。

観点2: 多要素認証やreCAPTHA等セキュアなオプションに関して検討する

認証機能を堅牢なものにするために、世の中には先人たちが編み出した素晴らしいソリューションがあります。ユーザーからは面倒に思われることもありますが、そのユーザーを守ることが目的なので、これらの採用も視野に入れましょう。

オプション1: 多要素認証

パスワードのような知識情報(Something You Know)だけでなく、スマートフォンのようなハードウェアの所持情報(Something You Have)、指紋のような生体情報(Something You Are)を組み合わせて、複数要素で多段階の認証を行うことを多要素認証と言います。

以下のような二段階認証が最もメジャーですね。

  1. パスワードを用いて認証
  2. スマートフォンに対してSMSでワンタイムパスワードを送信 / AuthyやGoogle Authenticatorのようなアプリでワンタイムパスワードを生成し、それを用いて認証

この時デザイナーのやるべきこととしては、ワンタイムパスワードの入力画面のデザインが必須となります。

また、これはサインインやサインアップからは外れる余談ですが、ユーザーが2段階認証を有効化する画面のデザインもあり得ますし、高度なセキュリティ要件が求められるBtoB SaaSであれば、利用企業の管理者がメンバーに対して二段階認証を強制する機能のデザインが必要になってくるでしょう。

オプション2: reCAPTHA

出典: https://www.google.com/recaptcha/about/

みなさんご存知の「私はロボットではありません」です。ブルートフォースアタック(総当たり攻撃)への対策になります。

こちらの導入もチームで相談しましょう、以上にここで言うことはないですが、ふと思ったので探してみたらFigma Communityで見た目を再現したComponentを配布してる人はいました。

オプション3: ソーシャルログインやその他のプロトコルによるSSO

SSO(シングルサインオン)は一つの認証情報で複数のサービスを利用できる仕組みのことです。BtoCサービスでは一般的な存在のソーシャルログインはOAuthという認可の仕組みによって実現するSSOですし、BtoB SaaSだとSAMLやOpenID Connectを用いたSSOを実装することも珍しくありません。

パスワードレスな仕組みはセキュリティ的メリットも大きいですし、登録率増加などのビジネス的メリットも大きいでしょう。この記事では踏み込んだ議論はしませんが、選択肢として認識しておきましょう。

観点3: パスワード入力はマスクする

これは知らない人はいないでしょうが、一応解説です。

概要

サインアップ/サインインにおけるパスワード入力欄においては、入力されたパスワードはデフォルトでは「●●●●●●●」のようにマスクされた表示になるようにします。

防ぎたいリスク

第三者にパスワードを盗み見られる、いわゆるショルダーハックを防ぎます。

デザイナーがやるべきこと

デザインカンプを作る際にパスワード入力に関してはマスクされた表示にしましょう。

なお、このマスクは独自実装するものではなく、HTMLであれば <input type="password"> とするだけで自動でそのような表示となるので、デザインカンプにおいて変に凝った独自のマスキングを考えるのはやめましょう。

備考: パスワードの表示/非表示切り替えに関して

出典: Googleアカウントのサインインフォーム

マスクされたテキストは、その入力内容が長いほどタイプミスを誘発しやすくなるので、表示/非表示を切り替えられるとUXが良いでしょう。後ほど引用する NIST SP 800–63B でも推奨されていました。

目のアイコンのトグルで表現されることも多いですが、上のGoogleの例のようにチェックボックスでやるのが無難ですかね 🤔

観点4: エラーメッセージやリアルタイムバリデーションでパスワード強度は適切ものを検討する

概要

パスワードが弱すぎるときにエラーメッセージを出したり、強固なパスワード設定をサポートするためにリアルタイムでパスワードの強度メーターを表示したりすることがありますよね。この際、表示される内容はデザインカンプの時点で適切なものであるべきという話です。

防ぎたいリスク

不適切なパスワードポリシーが実装され、ユーザーが脆弱なパスワードを設定してしまう or 強固なパスワードを設定することができない状態を防ぎます。

では、適切なパスワードポリシーとは何なのでしょうか。一意にこれ、ということはできないのですが信頼できる機関が発行しているガイドラインは存在します。

ここではNIST(米国標準技術研究所)によるNIST Special Publication 800–63B Digital Identity Guidelines(以下SP 800–63B)を見てみましょう。

これが全てでは無いですが、パスワードに関して以下のようなことが書かれています。

  • 8文字以上の入力を必須にする
  • 少なくとも64文字の長さを許容すべき
  • 英字に加えて数字や記号を混ぜなければいけない等の条件は無し
  • 推測可能であったり漏洩済みであったりするパスワードの使用を許可してはならない
  • 定期的な変更をユーザーに強制するべきではない

3番目の、文字種の混合に関して特に条件がないのは意外ですよね。以下のような記事で他のガイドラインと見比べてみると面白いと思います。

デザイナーがやるべきこと

チームで仕様を相談の上、エラーメッセージやリアルタイムバリデーションの表示において弱すぎるポリシーを表示することがないように、デザインカンプを作成しましょう。

観点5: 第三者に登録情報を可視化しない

概要

メールアドレスが原因でエラーメッセージを表示する際に、当該メールアドレスによるアカウントの有無が第三者に判別がつかないようにする。

防ぎたいリスク

冒頭で触れたQiita記事で詳しくリスクが解説されていますが、ざっくり言うと以下の2点です。

  • 当該メールアドレスが「サービスに登録されている」という事実が漏洩
  • リスト型攻撃の攻撃準備に悪用されてしまう

登録状況が可視化されてしまうのは以下のようなパターンです。

  1. サインアップフォームに登録済のメールアドレスを入力して送信した時、「登録済のメールアドレス」といった旨のエラーメッセージを表示してしまった時
  2. サインインフォームにおいて未登録のメールアドレスを入力して送信した時、「未登録のメールアドレス」といった旨のエラーメッセージを表示してしまった時
  3. パスワードリセットフォームにおいて未登録のメールアドレスを入力して送信した時、「未登録のメールアドレス」といった旨のエラーメッセージを表示してしまった時

正しい挙動は以下のようであるべきです。

  1. UI上では「入力されたメールアドレスにメールを送信しました」の旨を表示し、メールでは「当該メールアドレスは登録済です」の旨を表示する(観点1で紹介した疎通確認のメールは実はこの観点でも必要ということです)
  2. UI上で「メールアドレスもしくはパスワードが間違っています」とぼかしたエラーメッセージを表示する
  3. UI上では「入力されたメールアドレスにメールを送信しました」の旨を表示し、実際にはメールを送信しない

デザイナーがやるべきこと

デザインカンプにおいて正しいエラーメッセージの表示を心がけましょう。

観点6: サインインにおける試行回数制限をデザインに反映する

概要

総当たり攻撃を防ぐためにも同一メールアドレスに対して例えば「30分以内に15回ログインに失敗した」ようなケースにおいてはアカウントロック機能が働くことが望ましいです。

例として、Twitterでは一定回数サインインに失敗するとこのような画面が表示され、1時間サインインができなくなります。表示されている文章の通り、回数制限に達した場合以外でも使用される画面のようですね。

防ぎたいリスク

アカウントロックによって、同一のメールアドレス(ID)に対する総当たり攻撃、ブルートフォースアタックを防ぐことができます。

ただし、パスワードをありそうなもの(例: ‘password’, ‘aaaaaa’)に固定してID側を総当たりで変更していくリバースブルートフォースアタックにはこれでは対処できないので、先ほど紹介したような多要素認証・reCAPTHAなどの対策を合わせて検討する or とりあえずはそちらだけ導入するという方針が考えられそうです。

デザイナーがやるべきこと

アカウントロック時の画面をデザインしましょう。

この時、悪意のないユーザーが不安にならないようなUXライティングが必要になるでしょう。上のTwitterの例でも、理由を明示して「自動的に解除されます」と書いてありますね。

また、Twitterではそのような機能はなかったですが、アカウントロックが迫っている時に「残りN回サインインに失敗するとアカウントがロックされます」といった表示があるとより親切と言えるでしょう。

SP 800–63Bでも「残された試行回数について,明確で有意義なフィードバックを提供する」という推奨がなされています。

まとめ

というわけで以下の6点に関して、その理由と対策についてまとめてみました。

  1. メールアドレスが本人のものであるかの確認をサインアップフローに挟む
  2. 多要素認証やreCAPTHA等セキュアなオプションに関して検討する
  3. パスワード入力はマスクする
  4. エラーメッセージやリアルタイムバリデーションでパスワード強度は適切ものを検討する
  5. 第三者に登録情報を可視化しない
  6. サインインにおける試行回数制限をデザインに反映する

省略しましたが「パスワードマネージャを利用するユーザーのためにパスワードのコピペを許可する」などもデザインカンプに反映するものではないものの、認識しておきたい方針ですね。

他にもポイントがあれば随時追記しますので、ぜひ教えてください。

ですが、まず目指すはこの記事が完璧なチートシートになることよりも、皆さんが普段デザインやプロトタイピングを行う上で働かせる想像力の補助輪になることかと思います。ぜひご活用ください。

最後に宣伝ですが、弊社Flatt Securityではプロダクト開発組織の様々な悩みに寄り添うセキュリティサービスを提供しています。特にセキュリティ診断は新サービスのリリースや大規模なアップデート前には必須と言えるサービスです。是非ご検討ください。

ブログや事例など頻繁に更新しておりますので、公式Twitterから是非確認してください。

ではでは。またネタが思いついたら書いていきます。

--

--

KeijiroToyoda

デザインに多少詳しくて、サイバーセキュリティの仕事をしています