サイキックな認証

遅ればせながら、アドベントカレンダー15日目のやつです。

12/23のアイマスハッカソン2018にてアドベントカレンダーネタにしようとしたものをちょうど作れたのでそちらについて書きたいと思います。

GitHub - kahun-mask/psychic-authn: web authentication flow code is based on https://github.com/fido-alliance/webauthn-demo

サイキック認証の裏側

今回サイキックという言葉で隠したのですが、お気づきかもしれないですが技術としてはWebAuthenticationAPIを使いました。 WebAuthenticationAPIに関しては何番煎じなんだってくらい記事は溢れているのでここではあまり説明しませんがざっくりとこんな感じです。

Web Authentication API公開鍵暗号を用いて強力な認証を可能にする Credential Management API拡張機能で、パスワードを用いない認証や、 SMS テキストを用いない二要素認証を実現します。

https://developer.mozilla.org/ja/docs/Web/API/Web_Authentication_API

インターフェース的にはシンプルで以下2つを抑えておけば、API部分については十分です。

  • navigator.credentials.create([options])
    • 新しい認証情報を作成します。
  • navigator.credentials.get([options])
    • 既存の認証情報と照合します。

Web Authentication APIについてはこのくらいの理解で十分です。

Web Authnの辛いところ

前述の通りWeb Authnに関しては2つのAPIの理解をしていれば十分なのですが、それだけでは認証解決するまでには遠くWeb Authnによって得られるPublicKeyCredentialを紐解く作業、つまりRelying Party Serverの実装がほぼ全てと言ってもいいでしょう。

このRelying Partyでは何をしているのか、ちょっとだけ説明すると以下のようなことをやっています。

(登録フロー)

  1. challengeを発行
  2. PublicKeyCredentialを取得 (Web Authn)
  3. challengeの照合
  4. originの照合
  5. CBOR(Concise Binary Object Representation)という形式でAuthenticatorAttestationResponseがシリアライズされているのでdecode
  6. 上記から認証器の情報を取得
  7. clientDataJSONのhashを作成
  8. AttestationStatementFormatを決定
  9. AttestationStatementFormatの検証手順を使用してattStmtが正しいかどうかを検証 ...

すべて説明するのも大変なのでこのフローもまた一部抜粋したものです。

仕様書のほうには詳細が記載されているのでそちらを見てみてください。

Web Authentication: An API for accessing Public Key Credentials - Level 1

ここで改めてよく目にする登録フローの図を見てみます。

Registration Flow
Registration Flow
画像引用元: https://w3c.github.io/webauthn/#api

お気づきだろうか、これだけ複雑な検証手順が上の図だと⑥にまとめられているのです。ちなみに実装の9割は⑥に含まれると言っても過言ではないです。

一見華やかに見えるWeb Authentication API、実のところRelying Partyというハードな見えないところの実装の努力があって初めてパスワード不要な認証が実現できていることがおわかりいただけただろうか。

見えないところでの努力。これってすごいアイドルを感じますよね。

そして謎に包まれた認証、すごくエスパーです。

Web Authentication APIに堀裕子みを感じてしまったのでこれは実装せざるを得ないと思い、先日のim@s_hack 2018にてサイキックな認証を作ってみた成果がこちらです。

https://psychic-authn.herokuapp.com

もちろんサイキックに対応したブラウザじゃないと見れないのでご注意を。

実装内容的には公式のそのままじゃ動かないデモを参考にしつつ、w3cの仕様を見ながら整合性を取るのに手間取りましたがなんとか認証解決できるところまでできました。

(認証情報に関しては個人情報の取り扱いが面倒なのである程度キャッシュさせたら削除させるようにします)

よかったら試してみてください。PC ChromeでYubikeyを使ってのみ動作検証をしていないので他環境での動作の保証はしませんのであしからず。

以上遅ればせながらアドベントカレンダー15日目の記事でした。来年は風邪を引かないようにがんばります。