メアドなどのスクリーニング対策を意識しつつ WebAuthn のログインフローを考える

ritou です。

年末ですが、一年を振り返るエモいポエムを書く気はさらさらないのでいつも通りです。よろしくお願いします。

今年は WebAuthn が話題になりました。 来年はブラウザの対応も進み、本格的に導入してくるサービスも増えてくるかと思います。というか出てこい。というか出そう。

当然、今まで提供してきた認証方式から全てのユーザーを一気に切り替えることは不可能でしょう。 導入にあたってのポリシーはそれぞれだと思いますが、UserVerification を用いてパスワード認証からの完全移行を目指す、もしくはオプションや多要素認証として提供するにしても、既存の認証方式と組み合わせたログインフローを実装する必要があります。

今回は既に複数の認証方式をサポートしているサービスのログインフローをざっと振り返った後に、今年別件で話題になっていたメアドや電話番号などのスクリーニングへの対策という視点を入れてどのようなログインフローを実装すべきかを考えたというお話です。

いきなりまとめ

ダラダラと書いてますが、こんな流れです。

  • GやY!Jはユーザー識別後に設定されている認証方式を提供
  • microsoft はユーザー識別と並列で WebAuthn の認証機能を提供
  • WebAuthn でも Resident Key 使えない環境だと最初にユーザー識別が必要
  • ソーシャルログインも最初に IdP毎の分岐をするのが一般的
  • ユーザー識別後に処理を分岐させるとスクリーニング対策は困難
  • WebAuthn の認証フローでもスクリーニング対策は可能
  • 既存のログイン方法 or WebAuthn のように並列にしておくのが良さそう
  • 利便性低下の防止のために前回と同じ認証方式を使うみたいな仕組みを入れても良いかも

では始めます。

複数の認証方式を提供するサービスを見ていく

まずは Google, Yahoo! JAPAN, microsoftあたりを見てみましょう。

Google

(おそらく普通の) Google ユーザーは2種類の認証方式を利用できます。

ログインフローがどうなっているかを整理します。

まず、ログイン画面で存在しないユーザーのメアドを入れるとエラーになりますね。

f:id:ritou:20181231010133p:plain

Googleの場合、登録されているメアドというよりも 存在するgmailかどうか がここで判断できますね。

次に、「スマートフォンでログイン」を設定していない場合、ログイン画面でメアドを入れるとパスワード入力画面になります。

f:id:ritou:20181231010158p:plain

スマートフォンでログイン」を設定している場合、ログイン画面でメアドを入れるとスマホでタップしろ画面になります。

f:id:ritou:20181231010238p:plain

スマートフォンでログイン」を設定しているユーザーかどうかがここで判断できます。 ちなみに他の方法で...ってやると、こんな画面です。

f:id:ritou:20181231010304p:plain

これはまぁ、いいや。

ここまでで、利便性重視なんでしょうけれども、登録されているかどうか、スマホでログインする設定になってるかどうかがログイン試行している人物に対して丸わかりです。 次は WebAuthn にも対応している Y!J を見ていきましょう。

Yahoo! JAPAN

Yahoo! JAPAN も複数の認証方式に対応しています。

  • 確認コードでログイン(SMS)
  • 確認コードでログイン(メール)
  • 指紋・顔認証など(WebAuthn)

そして、Googleと同様にそれぞれわかりやすいUXとなっています(雑)

まずは存在しないメアドとかの場合。

f:id:ritou:20181231182246p:plain

あ、これ赤枠で囲ったわけじゃなくてログイン画面の背景が赤いんです。念のため。

次、確認コードでログイン(SMS)の場合

f:id:ritou:20181231022859p:plain

確認コードでログイン(メール)の場合

f:id:ritou:20181231022917p:plain

そして、Android Chrome + WebAuthn だとこんな感じです。

f:id:ritou:20181231023101j:plain

確認コードのところはなんかマスクしすぎてわけわかりませんが、Googleと同じような感じですね。 Google と Y!J では、「最初にユーザー識別をしてからそれに紐づく認証方法を提供している」と言えそうです。

次は、同じく WebAuthn のログインを実装している microsoft です。

microsoft

Windows 環境で microsoft + Edge を使うと、ログインに WebAuthn のフローを利用できます。

blog.haniyama.com

ログイン画面はこんな感じです。

f:id:ritou:20181231164906p:plain

"Sign in with Windows Hello or a security key" と言うリンクがここにありますね。 環境判定して Edge だけ出してそうです。 このフローを使うと、メアドなどを入力せずとも Windows Hello や セキュリティキーでログインできます。

f:id:ritou:20181231165437p:plain

navigator.credentials.get() 呼び出してそうです。

f:id:ritou:20181231165600p:plain

スクリーンショットをとった私の環境はPIN入れる画面ですが、とりあえずこれでログインできます。

microsoft の場合、「ユーザー識別をしてからそれに紐づく認証方法を提供 or WebAuthn」のような分岐になっているように見えます。

WebAuthn の Resident Key の現状

上記のように、microsoftWindows + Edge な環境では、「この時点で誰かわからないけどWebAuthnでログインさせる」と言う処理になっていました。 これは username-less とかとも言われますが、ResidentKey を用いた登録/認証機能です。

これは便利なので使いたいところですが、現状、全てのブラウザがこの Resident Key に対応できているわけではありません。 よって、早い段階で WebAuthn をサービスで利用しようと思った場合、Y!J のやっていたような一旦ユーザーを識別した後に紐づく公開鍵を用いて WebAuthn の認証フローに入っていく必要があります。

と言うことは、やはりG や Y!J のようなやり方がベストなのでしょうか?

ソーシャルログイン対応サービス

Google も Y!J も基本的に自分たちで認証機能を提供しています。 それに対し、世の中には既に「ソーシャルログインを利用」する形で複数の認証方式に対応しているサービスがたくさんあります。

例えば、エンジニア向けのイベントで有名な connpass とか

f:id:ritou:20181231170657p:plain

エンジニアの転職で有名なメルカリとか

f:id:ritou:20181231170643p:plain

ソーシャルログインを利用するログインフローでは、「パスワード認証 or ソーシャルログイン」もっと言うと「パスワード認証 or IdPその1でログイン or IdPその2でログイン or ...」と言う感じで、これまでの例でいうと microsoft のやり方に近いです。

ということで、ここまでで複数の認証方式をサポートしたログインフローを考える時の最初のキメは「ユーザーの識別前に認証方式を分岐させるか、識別して設定に合わせた認証方式を提供するか(さらにいうと、識別後に分岐させるか)」あたりかなと思ってきました。

少し落ち着いて、一旦スクリーニング対策について考えましょう。

スクリーニング対策の必要性

今年、メールアドレスなどのスクリーニングについての話題も目につきました。

qiita.com

よくある「メアド or パスワードが間違っています」でやってたところが、新規登録のところでちゃんとエラー返してたのでスクリーニングに利用されたのではというお話ですね。

今回はログインの話ですが、スクリーニングに使われることの何が嫌かというと

  • 悪意のある行為の手助けをしてしまう
  • 例えばSMSをじゃんじゃん送られたらそれなりにお金もかかる
  • 対象となり通知を受けたユーザーが困惑、心配からの炎上
  • 負荷も上がるかも

といったあたりでしょう。 やはり良いことなさそうです。

まぁ、GoogleGmailが生きてるかどうかを聞いてもそんなに得しない気もしますが、オンラインショッピングや決済関係のサービスでスクリーニングされたらそのリストの価値は上がるでしょう。

しかし、上記のGやY!Jのようにユーザー識別後に処理が分岐するようでは、簡単にスクリーニングされてしまうので、microsoft やソーシャルログインを利用するサービスのように、並列に WebAuthn の認証フローに入る、かつスクリーニング対策をする方向で考えていきたいところです。

WebAuthn におけるスクリーニング対策

こんな感じではどうでしょうか。

  1. 存在しないメアドや電話番号でも、認証画面に入る
  2. 公開鍵はメアドや電話番号に一意に紐づけられるダミーの物を用意しておく。毎回同じものを使う。
  3. 万が一認証通ってきたとしても、しれっとエラーにする

この辺りはもう少し考えたいですが、できないことはなさそうです。

既存の認証方式とWebAuthn の組み合わせ方案

ここまでの話を整理して、ログインフローを検討しました。

Step 1 : ログインフローの最初に分岐

例え現状の WebAuthn の認証フローがユーザー識別を必要としても、最初に分岐させるのが良さそう。 Y!J の認証方式の用語を用いるとこんな感じでしょう。

f:id:ritou:20181231030450p:plain

Step 2 : ユーザーに紐づくメアド or 電話番号などを入力

ここで登録されていないエラーは出しません。

Step 3 : 存在しないメアド or 電話番号の場合でもダミーの公開鍵で WebAuthn の認証フローに入る

仮にダミーの公開鍵だったとしても、WebAuthn の Authenticator から見たら「別の Authenticator 向けの公開鍵なんだな」として処理してくれれば問題なさそう。

スクリーニング対策による利便性低下への対策

上に書いたログインフローですが、ユーザー視点で毎回分岐しまくるのは正直辛いですし、エラーも出てこない分、永遠に「ログインできねーや」と詰む人が出てきそうです。 また、どんな認証方式を利用しているか忘れてしまうこともあるでしょう。

実は、ソーシャルログインの普及時期においても同様の議論はありました。 例えばソーシャルログインでサービスアイコンが並んでる時の問題は Nascar Problem と呼ばれていました。

idmlab.eidentity.jp

上記の記事にもありますが、この問題の対策として、前回利用した認証方式を覚えておくみたいな話があります。 WebAuthnが利用できる環境なら使うけど、そうじゃなかったらSMSとかで確認コードを送りたいみたいなユーザーにも、ブラウザごとに前回の認証方式が利用できる仕組みになっていると良さそうです。

まとめ

最初に書きました。

  • GやY!Jはユーザー識別後に設定されている認証方式を提供
  • microsoft はユーザー識別と並列で WebAuthn の認証機能を提供
  • WebAuthn でも Resident Key 使えない環境だと最初にユーザー識別が必要
  • ソーシャルログインも最初に IdP毎の分岐をするのが一般的
  • ユーザー識別後に処理を分岐させるとスクリーニング対策は困難
  • WebAuthn の認証フローでもスクリーニング対策は可能
  • 既存のログイン方法 or WebAuthn のように並列にしておくのが良さそう
  • 利便性低下の防止のために前回と同じ認証方式を使うみたいな仕組みを入れても良いかも

今回のお話ですが、現状の他のサービスを見つつ、優秀な若者氏に相談して見た結果、良さそうってなった提案です。 これでうまくいくかどうかはわかりませんので、実際に自分たちのサービスに導入して検証できると面白そうですね。

長文読んでいただきありがとうございました。来年も頑張りましょう。

ではまた!