最高のログインフォームを考える


この記事はエイチーム引越し侍 / エイチームコネクトの社員による、[Ateam Hikkoshi samurai Inc.× Ateam Connect Inc. Advent Calendar 2020](https://qiita.com/advent-calendar/2020/hikkoshizamurai-connect) 16日目の記事です。

## はじめに
WEBサイトのログインフォームは色々なものがありますが、
**使い勝手が良く、セキュリティに強いログインフォーム**は何なのか
自分なりにまとめてみました。

## ログインする目的
原点から考えてみたいと思います。
ログインする目的は、**「認証と認可」**と考えました。

【認証】（通信相手が）誰か識別すること
【認可】（リソースへのアクセスを）許可すること

つまりは、ログインを通じて**「通信相手が誰かを識別できること」**が出来れば、
ログインの目的は達成できそうです。


## 色々なログインフォーム

筆者がよく遭遇する下記３つを対象に、
**ユーザビリティ**をチェックしていき「どのような形が望ましいか」を考えてみます。

- ログイン専用ページがある
    - Google, Amazon, facebook, Apple など
- ログイン画面がモーダルで表示される
    - Twitter (PCはモーダル風UI）
- ログイン画面がヘッダなどで常に表示されている

## ユーザビリティチェック

まずはユーザになりきるため、想定されるユーザを洗い出します。

- ログイン情報を**手動**で入力する人
- ログイン情報を**自動**で入力する人
    - パスワード管理ツール（1Password、ブラウザのパスワードマネージャ等）
    - シングルサインオン（HENNGE、Oktaなど）

**手動・自動** 両方の観点でチェックしてみると良さそうですね！

### いざチェック!
|  | 専用ログインページ | モーダル | 常に表示 |
| --- | :-: | :-: | :-: |
| フォームの存在を認識しやすい | ○ | ○ | ○ |
| 導線クリック時、予想した動きをする | ○ | × | ○ |
| 入力欄を選択しやすい| ○ | ○ | △ |
| パスワード忘れ導線も表示 | ○ | ○ | △ |
| 新規登録したい導線も表示 | ○ | ○ | △ |
| 管理画面へのログイン導線も表示<br>（仲介サイトなどの場合） | ○ | ○ | △ |
| デバイスを問わず使いやすい | ○ | △ | × |
| ログイン専用URLを共有できる | ○ | × | × |
| ブラウザ(JS,バージョン)に依存しない | ○ | △ | ○ |
| パスワードマネージャが対応できる<br>（パスワードの自動入力） | ○ | × | △ |
| 他ページの読み込み速度に影響しない | ○ | × | × |

個人的見解も含まれていますが、
ユーザビリティでは**「専用ログインページを設けるのがベスト」**になりました。

### ポイント
専用ログインページを設けることで、

- **余裕を持って**情報を掲載することができる
- サイト構造がシンプルになり、**影響範囲が最小化**する
- 手動だけでなく**自動パスワード入力**にも対応できる


## セキュリティチェック
ログインフォームといえば、使い勝手も大事ですが**セキュリティ面**がとても大切になります。

先ほどログインの目的は**「認証と認可（通信相手が誰かを識別できること）」**と記載しましたが、第三者がログインできてしまうと、この目的が果たせないことになってしまいます。

**セキュリティとユーザビリティはトレードオフ**とも言いますが、
情報が流出してしまっては元も子もないため、ユーザビリティを意識はしつつも、セキュリティを高め、あるべき姿へ近づけていきたいところです。

### セキュリティアンチパターン
ログインフォームの実装時、チェックできるよう、避けたいアンチパターンをご紹介していきます。

#### 1. 「メールアドレスが既に登録済です」と表示すること
会員登録ページ、ログインページ、パスワード再発行ページなどでよく見る実装ですが、
下記の問題点があります。

- メールアドレスは個人情報に該当することがあり[(総務省)](https://www.soumu.go.jp/main_sosiki/gyoukan/kanri/question03.html)
、望ましくないこと
- 攻撃者が、メールアドレスが有効なことを確認できること
- 攻撃者が、パスワードの推測のみでログインを試行できてしまうこと
- 攻撃者が、「ユーザがサイトに登録していること」を簡単に把握できてしまうこと
    - フィッシングメールをユーザが信じやすくなってしまう

#### 2. 利用できる文字種類、桁数を少なく限定すること
パスワードの組み合わせ数が少なくなり、総当たり攻撃の成功確率が高まってしまいます。

- 4桁数字のみ：10×10×10×10 = 10,000通り
- 8桁以上英数字： 2,821,109,907,456通り（約2.8兆）

IDさえわかっていれば、**4桁数字のみの場合**1日24回の試行で、
**417日目で攻撃が成功**してしまうことになります。

#### 3. デフォルトのパスワードを生年月日にすること

生年月日にするとパターンの組み合わせが極端に減ってしまい、予測がしやすくなってしまいます。
また生年月日は分布していることから、逆総当たり攻撃（パスワードを固定しログインIDを変更し続ける攻撃）の成功確率が飛躍的に高くなってしまいます。

#### 4. ログインIDを連番にすること
こちらも3番と同様で、逆総当たり攻撃の成功確率が高まってしまいます。

#### 5. 同一IPアドレスからの連続ログイン失敗をブロックしないこと
同一IPアドレスから連続ログイン失敗を禁止しない場合、総当たり攻撃やパスワードリスト型攻撃（流出済IDとパスワードの組み合わせを利用する攻撃）を永遠と受け続けてしまう可能性があります。
（色々なIPアドレスから数日おきに攻撃される場合など、感知しにくいこともあります。）

#### 6. 同一IDへの連続ログイン失敗をブロックしないこと
ログインIDが特定されている場合（SNSのアカウント名、メールアドレス）に、攻撃が成功してしまう可能性を高めてしまいます。
（パスワードを固定し、IDを変えて攻撃される場合など、感知しにくいこともあります。）

#### 7. 別環境からのログイン成功/試行を通知しないこと
　普段国内のIPアドレスからしかアクセスがなかったIDが、急に海外のIPアドレスからログインされた場合などは、何かしらの攻撃を受けている可能性も考えられます。IPやOSなどの環境や利用時間が違う場合、ユーザに通知したり、場合によってはユーザビリティは下がりますが、ログイン時や機密性の高い情報へのアクセス時にメールアドレス等による追加認証を要求するのも良いかもしれません。
　LINEは、ログイン成功以外に**ログイン試行のタイミングでも通知**が行われます。
　この機能は何度かアカウントを乗っ取られている筆者にとっては攻撃されていると気づくことができ、また阻止されたことを確認することができるため、筆者がサービスを安心して使うことに大きく影響しています。

## 理想の認証

### ID/パスワード認証の問題点
現状多くのサイトで取られている**ID/パスワード認証**では下記の問題点があると考えています。

- **ユーザ負担が大きいこと**
    - ID/パスワードを管理する必要がある（管理ツールを利用すると負担は軽減）
    - 毎回長い文字列を入力する必要がある
- **パスワードリスト型攻撃に弱いこと**
    - ユーザ負担が大きくなった結果、パスワードの使い回しが発生し、一度あるサイトで流出すると芋づる式に乗っ取られてしまいやすくなります。
    - 対策に力を入れているサイトでは、登録済情報（メールやSMS）による追加認証が行われている印象です。


### 解決策
そんな問題点を解決できる、理想の形は下記だと考えています。

- **デバイスの生体認証でログインができる状態**
    - **FIDO2**によって、デバイスの指紋認証や顔認証でログインが可能に [(参考記事)](https://support.trustlogin.com/hc/ja/articles/360000286501--FIDO2-%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%8B%E3%82%92%E6%AD%A3%E3%81%97%E3%81%8F%E7%90%86%E8%A7%A3%E3%81%99%E3%82%8B-%E3%82%AA%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9%E6%8B%85%E5%BD%93%E8%80%85%E5%BF%85%E8%AA%AD-)
        - ログインIDと生体認証を紐づける方法で、記事によると2019年時点でYahoo! JapanはAndroidアプリでこの対応を始めているようです。

#### 更にセキュリティを強化する場合
ユーザビリティは低下してしまいますが、下記でより強力にすることも可能です。

- パスワードを発行せず
- 電話番号/メールアドレス等に都度ワンタイムコードを送付し、認証を行う

## 最高のログインフォーム
とはいえ上記は、多くのWEBサイトにすぐに適用できる形ではないと思います。
そのため、本記事の目的でもある「最高のログインフォーム」を、チェックリスト形式で最後に考えたいと思います。

### ユーザビリティ
- [ ]  ログインページが独立していること
- [ ]  モーダルが必須導線として登場しないこと
- [ ]  全ての入力必須項目が最初から表示されていること
    - 自動入力でも対応できるように
- [ ]  ログインフォームが複数ページにまたがらないこと
- [ ]  必要な情報にアクセスできる導線があること
    - [ ]  新規登録
    - [ ]  パスワード再発行
    - [ ]  （仲介サイトの場合など）管理者画面へのログインリンク
- [ ]  Tabキーで入力フォームを移動できること（主にPC/業務サイトなどの場合）
- [ ]  Tabキーで移動した際、ID→パスワード→ログインボタンの順に遷移できること
    - （途中でパスワード再発行などにフォーカスが当たらない）※個人的に嬉しいだけです

### セキュリティチェックシート

#### 筆者の必須項目
- [ ]  「個人情報（メールアドレス）が登録済」か推測できないこと
- [ ]  IDやパスワードに利用できる文字数は、最低でも半角英数字 12桁以上あること
    - ただしパスワードの使い回しに備え、「大文字/記号必須」にするのも場合によっては検討
- [ ]  デフォルトでパスワードを設定する場合は、半角英数8~12桁以上など、組み合わせ数を考慮すること
- [ ]  同一IPアドレスからの連続ログインをブロックできること
    - IDを順番に変え、パスワードを固定する場合にも対応できるよう、一定期間内に数回以上失敗すると一定期間ログインができなくなるような仕組みが必要そうです。
- [ ]  同一IDへの連続ログイン失敗をブロックできること
    - 時間を置いて施行する攻撃者の存在を考えると、一定期間内かはチェックせず、一定回数連続で失敗するとパスワードを再設定する形式が望ましそうです。
- [ ]  ログインID(メールアドレス、電話番号)の変更時は、変更前アドレスに認証情報を送信すること
    - IDを変更されると、アカウントが丸々乗っ取られてしまうことがあるため
    - 前の情報にアクセスできないユーザを想定する場合、生年月日など何かしらで追加認証を行う・あるいは確認メール送信から24時間以上経過しないと変更できないなどの仕様もセキュリティ面ではありかもしれません。
- [ ]  ログインIDはシステム等で自動採番したような連番でないこと
    - 連番の場合、攻撃者はIDを変えながらパスワードを固定し探知されにくい状態で攻撃を進めることができます。

#### 筆者の任意項目
- [ ]  ログイン試行をユーザに通知すること
    - ログイン試行IPアドレス、認証情報をメール等に載せると、本人か確認しやすい
        - 銀行やカードの情報を管理できる家計簿アプリなどは、外国のIPアドレスから代理ログインすることもあり、ユーザが誤解しやすいため
        - 時間が経ってから通知を確認した際に、ユーザがログインしたことを覚えていないことがあるため
    - IPアドレス/端末がこれまでログイン成功していなかった場合のみなどに制限するのも
- [ ]  ユーザIDはなるべくユーザに指定させないこと
    - ログインIDをメールアドレス以外にする場合、パスワードリスト型攻撃への耐性は強くなりますが、登録時に「このIDは登録済です」とする必要があり、有効なIDを推測できてしまいます。
- [ ]  アプリの場合、ログインロック機能を実装していること
    - LINEアプリでは、他端末でのログインを禁止する設定が存在しており、ユーザは安心できます。
        - ※WEBブラウザだとIPアドレスなどは毎回変わるため、二度とログインできなくなってしまう可能性があります。あくまでアプリで、再インストールされない場合を想定しています。
- [ ]  初回ログインの端末・あるいは別環境（IP、端末）の場合、追加認証を要求すること
    - ユーザビリティとトレードオフではありますが、国内大手通信キャリアなどではこの実装がスタンダードになっています。

## 最後に
　ここまで主にユーザ目線から記させていただきましたが、**事業者目線**としては、パスワードリスト型攻撃が出来る状態にしてしまうと、大きなリスクを抱え込むことになってしまいます。
　具体的には、仮に他社で流出したID/パスワードリストで自社にログインが成功し、その情報がダークウェブなどで公開され、流出に気づくと、ユーザの安全を守るためにも情報を世間に開示する必要性が出てきます。
　その際、ニュースなどで報道される際は、「A社で情報流出」「顧客情報が何万件流出」のような形で、報道されることになります。
　消費者がサービスを利用する際は信用が大切になり、特にこのご時世では個人情報の取扱がとても大切ですが、築き上げていった信用を一気に地に落としてしまうことになりかねません。
　最終的にはこのようなリスクを保有するか、低減するか、という話にはなってくると思いますが個人的には、ログインフォームは工数を使ってでも、セキュリティを高められるよう考えていきたいです。

## 特にお世話になった参考文献様
- よくわかる認証と認可 / Developers.IO
    - https://dev.classmethod.jp/articles/authentication-and-authorization/
- ログインフォームは変わった方法で実装しないで！ / coliss
    - https://coliss.com/articles/build-websites/operation/work/dont-get-clever-with-login-forms.html
- 会員登録フォームにセキュリティ脆弱性を産む UI デザイン美人局 / feb19.jp
    - http://feb19.jp/blog/archives/000282.php
- 総当たり攻撃 / Wikipedia
    - https://ja.wikipedia.org/wiki/%E7%B7%8F%E5%BD%93%E3%81%9F%E3%82%8A%E6%94%BB%E6%92%83
- 情報セキュリティマネジメントとPDCAサイクル / IPA
    - https://www.ipa.go.jp/security/manager/protect/pdca/risk.html

## 明日
[Ateam Hikkoshi samurai Inc.× Ateam Connect Inc. Advent Calendar 2020](https://qiita.com/advent-calendar/2020/hikkoshizamurai-connect) 16日目の記事は、いかがでしたでしょうか。
明日は心優しい、新卒の @yhorikawa です!! お楽しみに!