WebAuthn など新しい認証方式を受け入れる際の「アカウントリカバリー」の考え方

ritou です。

この前、こんなイベントを覗いてました。

* [[自由編集可] 次世代 Web カンファレンス 2019 AuthN/Z セッション (#nwc_auth)](https://togetter.com/li/1267064)

この中で WebAuthn が流行るためにアカウントリカバリーのあたりが難しいと言う話題が出ていました。

もしかしたら話している人の「難しい」と聞いている人の「難しい」が違う可能性もありそうですが、聞いている人の方が漠然と「難しそう」って感じなのが気になりました。

記憶認証に比べると所持認証や生体認証の方は「●●したら終わり」と言う印象が強く、それをメインの認証方式に利用しようと思うとリカバリーどうしたら良いのか？と不安になるのかもしれません。

今回は新しい認証方式を採用したい、あわよくばパスワード認証を捨てたいと考える際の一つの考え方をご紹介します。

## 詰んだ状態

一般的なアカウントリカバリーについて、

* パスワードを忘れたのでメールやSMSなどで本人確認をして再設定
* カスタマーサポートに問い合わせて何らかの方法でログインできるようにする

などが思いつきます。多分。
今回は主に前者、ユーザーが単体で頑張る方の話を前提としていますが、後者もどこかの処理が代理で行われているみたいな感じで矛盾はしないと思います。

例えば WebAuthn "のみ" でサービスを実装しようとすると、

* YubiKey どっかいった
* 飲み過ぎてしまい、渋谷のど真ん中でスマホを無くしてしまった
* 何本か指を切り落とされてしまい、指紋認証ができない

といった「詰んだ」状態が考えられます。
この「詰んだ」状態には段階がいくつかあると思っていて

* ユーザーを識別するのが困難
* 識別できても認証するのが困難
* 普通に認証できる状態に戻すのが困難

といったあたりではないかと思います。

## ソーシャルログインの時はどうだったのか？

この話は、何も今に始まったことではありません。

数年前、いわゆるソーシャルログインが流行り始めた時、同じことを考えるきっかけはあったのではないでしょうか。

Google, Twitter, Facebook でログインできるサービスを使っているときに、IdP側でアカウントがBANされたらどうなるでしょうか？サービス側ではどうにもできません。

ではどんな対策があったかと言うと、複数のIdPのアカウントと紐づける、以外にはやはり

「パスワード"も"設定させて、パスワード認証もできるようにする」

ではなかったでしょうか？
そして、パスワードもわからない、設定していない場合は

「確認済みのメアドなどで色々して再設定」

と言うおなじみのアカウントリカバリーフローを用意することになっていたはずです。

私もソーシャルログインの紹介などをする時に何となくそんな感じで「リカバリーフローを用意することが大事ですよ」ぐらいは言っていたと思います。

この時は問題にならなそうだったのに、今になってパスワード認証を"完全"に捨てようとなった途端に不安に襲われてしまうのは何でしょうか？

## 「アカウントリカバリー」を「認証」と「設定変更」機能に分解する

前置きが長くなってしまいましたが、考え方として「アカウントリカバリー」を「認証」と「設定変更」機能に分解することをお勧めします。

### よくあるパスワードリセットフロー

前提として

* ユーザーに対して一意に確認済みのメールアドレスやSMS番号を保持している
* パスワードを設定していたが忘れた

と言う状態において、

1. パスワードを忘れたリンクをクリックする
2. メールアドレス(or SMS番号)を入力する
3. パスワード再設定リンクもしくは確認コードを送信
4. URLをふむ or 確認コードを入力してパスワード再設定フローに入る
5. パスワードを再設定する

みたいなフローがあるでしょう。
これを

* 認証 : 2,3,4
* 設定変更 : 5

のように分けて考えられそうではないでしょうか？

このパスワード認証の定石のようなフローは、パスワードによる認証とURLや確認コードを送ることによる認証の2種類が用意されており、世の中に一定数いると言われている「パスワードなんて覚えないで毎回リセットするユーザー」は、もうだいぶ前からパスワードレス(再設定はするけど使わない)な世界を生きているのです。

なぜパスワード認証をやめようと思うとリカバリーが不安になるのかに話を戻すと、このように１つの認証方式だけだと思っていた「パスワード認証」は既に複数の認証方式を並列にしている状態であり、一方で WebAuthn は単一の認証方式しか存在しないことが不安を感じる理由なのではないかと思うのです。

## ソーシャルログインやWebAuthnを単体で利用する場合のリカバリーフロー

まずはパスワード再設定に当たる部分が何なのかを整理する必要があります。

* ソーシャルログイン : 既存のID連携を解除&新たにID連携を行う
* WebAuthn : 対象の Authenticator を削除&別の Authenticator を追加

と言うぐらいのものでしょう。

WebAuthn のひも付け解除の時の Authenticator 側に残るデータの話とか、細かい部分は仕様を考えるレベルで引き続き検討されていくところでしょうけれども、利用者が最低限気にしなければならないのはサーバサイドで公開鍵の管理ぐらいだと思います。

と言うことで、上記のパスワードリセットフローのパスワード再設定部分を置き換えると問題があるかを考えましょう。

1. ログインできないリンクをクリックする
2. メールアドレス(or SMS番号)を入力する
3. Authenticator設定リンクもしくは確認コードを送信
4. URLをふむ or 確認コードを入力してAuthenticator設定フローに入る
5. Authenticatorを再設定する(使えなくなったAuthenticator削除&新しく登録)

そこそこのサービスであれば、これで十分そうです。

ソーシャルログインだけを認証に利用している場合でも、同じような実装にすることで(自分たちで提供している)パスワード認証をやめることができそうじゃないでしょうか？

## 認証強度の話

今回、認証方式を並列に考えることを提案しました。
これは多要素/多段階認証を導入する際にも重要だと思っています。

例えば、パスワード認証にオプションで WebAuthn を導入しようと考えたとします。
一見認証強度が上がったように見えますが、リカバリーフローがそのままの場合、認証強度が低いところが狙われるでしょう。

リカバリーフローで使われる認証機能を並列の認証方式と捉えることで、全体の認証強度の比較ができるようになるかもしれません。

## 今回のまとめ

* 定石のパスワード認証機能には複数の認証方式が含まれていると考えてみてはいかがだろうか
* アカウントリカバリーを「認証」と「設定変更」に分けて考えることが大事
* 「詰んだ」状態を防ぐためには「単一の認証方式」のみの状態を避けることが大事

実際はこれを頭の片隅のおいておきつつ、アプリケーションに最適な実装をしていくしかないのですが、アカウントリカバリーは難しく考える必要はないんだと言うことをお伝えしたかった次第であります。

## おまけ: WebAuthn 周りの UX について

Qiitaの記事はサクッと書いたのを載せてますが、ブログではわりとじっくり記事を書いています。
興味があったらどうぞ。

[私のブログの WebAuthn カテゴリ](https://ritou.hatenablog.com/archive/category/WebAuthn)

ではまた。