さて, 私の運用してるサービスのいくつかの認証にFIDO2を組み込んでやろうと開発していたのですが, 開発途中でいまいちwebauthn APIの挙動が意味不明だったので寄り道にwebauthn APIと戯れてみることにしてみました.
まあ結論から言うと結局OSやブラウザ, またその組み合わせによって挙動が違ってやっぱりなかなか細かいところの詰めが難しいという感じです..
とりあえず仕様や挙動が安定するまでは検証条件を甘めにして様子見で進めていこうと思ってますよ.
はじめに
一応簡単にwebauthn apiがどんなものかというと, アプリケーション(ブラウザ)が認証器とコミュニケーションをとるためのものです.webauthnサポートブラウザであれば「navigator.credentials.{create,get}(options)」とJSコードを実行すれば, ブラウザ側でoptionsに応じて良しなに認証器から情報を引き出すことができます.
んでその引き出した情報をRP(サービスのサーバ)に送ってRPで要求する条件を満たすか検証, という流れ.細かい説明はすでに結構いろいろ出てるので割愛. 個人的には公式の仕様と Yuriyさんの記事を読むのが正しい理解の近道な気はしますがね(人任せ).
検証してみる
基本的に認証器から取り出した情報の検証は決まった処理なのでここではスコープ外とします.要はWebauthn APIにどんなオプションを渡すと認証器からどんなレスが得られるのかにだけここでは興味がありますよ.
既存のいい感じのdemoサイトを探したところ, Azureのdemoサイトがよさげ.
がここではもうちょっとシンプルでサーバサイドでの検証(AuthN)は不要で 認証器からのレスポンスが見たいので 簡単なぺらいちのdemoサイトを作ってそれで確認してみます.
基本ブラウザ-認証器間でのやり取りのみなのでofflineでも動作します.
手持ち環境ありったけのWindows{8.1,10},MacBookAir,Android7で それぞれポチポチparamを変えて挙動をひたすら確認. 以下ちょっと気になった箇所だけ適当に備忘録として書き出しておくのです.
FIDO2対応セキュリティキーもOSによってはU2F扱いされる
基本ブラウザ - 認証器間のやり取りなのでOSのversionは依存しないと思っていたのですがそんなことなさそうです.
FIDO2対応のセキュリティキーで試してみましたが認証器からのレスポンスで
「fmt: packed」
(Webauthn仕様に最適化したformat)と返ってきたのはWindows10のInsiderPreview版のみでした.
それ以外のPC環境だといずれも「fmt: fido-u2f」
という旧来のU2F互換フォーマットでの扱いとなってしまいます.
どうやらWindowsだとbuild17723以上
からのサポートなようで.
Beginning with build 17723, Microsoft Edge supports the CR version of Web Authentication.
参考:Introducing Web Authentication in Microsoft Edge
ということでブラウザだけでなくOSのバージョンにも依存するということ.
ブラウザサポート状況についてはcaniuseで確認できますが徐々にサポートが増えてきているのが見て取れます.
UV非対応の認証器利用でUVを求められた場合, PINとの合わせ技が可能
Webauthnではユーザ認証としてUP(User Present)とUV(User verified)があります.
UPはユーザの存在を証明した際に認証器からのレスポンスで立つフラグで, 認証器へのタップなど単純な存在検証のみでユーザが本人かどうかの検証は含まれません.
一方, UVはユーザ自身かどうかの検証フラグであり, 指紋認証やPINなどを満たした場合に立ちます.
そして, Yubicoが提供しているFIDO2セキュリティキーのような認証器だとUPしか満たせません.
以下の図のように, 登録時のオプションでauthenticatorAttachment:cross-platform
, userVerification: required
, つまり, 外部認証器でUV必須とした場合で試してみます.
この場合, Yubikeyへのタップのほかに, Windowsに設定しているPIN
が要求されました.
このWindowsに設定したPINとの合わせ技で, UV非対応の認証器しかなくてもUVを満たすことが可能
なようです.
"flag": {
"UP": 1,
"UV": 1,
"AT": 0,
"ED": 0
}
extra. counter機能って必要?
ちょっと本題からずれますが, counterの必要性がU2Fの時からよくわかっていません.
認証器側で認証操作をする都度+1インクリメントされ, サービス(RP)側では認証器から渡ってきたcounter値をストアしておくことで, 前回の値から増加しているかを検証する奴ですね.
つまりcounter検証では常に大きいcounter値を持った認証器が正とみなされるわけです.
device cloning検知のためのようですが, 通常悪意のある人がデバイスをコピーしたら真っ先に試すと思うんですよね, 本来の所有者より先に..
つまりコピーされたデバイスのほうがoriginalより先にcounterがインクリメントされ正とみなされるわけで, むしろこれ逆効果じゃね?となってしまうのです.
まあ検知した際にアラート上げる程度ならありかと思いますがね.どうなんでしょう.
おわりに
まだ怪しいところはあった気がしますがいったんこんなところです.このほかにもアカウントリカバリどうすんの?とか考えないといけないところはありますがまあ順々に潰していければいいかなと思います.
現状まだサービスでの認証だと二要素目の認証(U2F,UAF)としてしかほぼ使われてないかと思いますが, FIDO2で登録・認証が完結すれば, 利用者はサービスにpassword級のクリティカルな情報を渡す必要がなくなります.
利用者側もサービス側もお互い心持ち楽になりそうですね.(依然として個人情報なのでRP側は気を付けないとですが.)
参考リンク
- www.w3.org/TR/webauthn
- medium.com/@herrjemand
- webauthntest.azurewebsites.net
- niconico-pun.gitlab.io/fido-sample/fido-simple.html
- github.com/gebogebogebo/fido2YubikeyTest