Appleが毎年開催している開発者向け会議「WWDC 2020」で発表した「Safariの認証機能とFace IDおよびTouch IDの統合」は、パスワードに代わる新しい認証方式のひとつとしてSafari 14から実装されています。その認証機能の動作イメージと仕組みについて、Appleが開発するSafariのレンダリングエンジン「WebKit」の開発に携わるJiewen Tan氏が解説しています。

Meet Face ID and Touch ID for the Web | WebKit

https://webkit.org/blog/11312/meet-face-id-and-touch-id-for-the-web/

Meet Face ID and Touch ID for the web - WWDC 2020 - Videos - Apple Developer

https://developer.apple.com/videos/play/wwdc2020/10670/

従来、ウェブサイトにログインするための認証方法はパスワードが一般的でしたが、総当たり攻撃などでパスワードが漏えいし、不正ログインされるといったセキュリティ上の懸念が生じ始めました。パスワードに代わる認証方式を生み出すべく、生体認証を基本とした新しいオンライン認証技術の標準化団体「FIDO Alliance」が標準化を進めているのが「WebAuthn」で、YubiKeyなどのセキュリティキーや指紋認証、顔認証などによるウェブサイトのログインを可能にする技術です。

パスワード不要のログイン方法「WebAuthn」がウェブ標準になる - GIGAZINE



Safari 14から実装されたFace IDやTouch IDによるログイン機能も、このWebAuthnに対応したウェブサイトで利用可能。例えば、SafariでWebAuthnに対応したウェブサイトでログインを試みると、以下の画像のようにFace IDやTouch IDを利用してログインを行うかどうかのポップアップが出現します。



このポップアップを出現させているのが以下のJavaScriptコード。必須の記述は「options」内の「authenticatorSelection: { authenticatorAttachment: "platform" }」で、プラットフォームによる認証機能のみを利用するようにWebKitに指示する記述であるとのこと。ユーザー名やIDなどを記述したoptionsを使って、navigator.credentials.create()によって、新しい認証情報をローカルのデバイス上に生成しています。

const options = {
publicKey: {
rp: { name: "example.com" },
user: {
name: "john.appleseed@example.com",
id: userIdBuffer,
displayName: "John Appleseed"
},
pubKeyCredParams: [ { type: "public-key", alg: -7 } ],
challenge: challengeBuffer,
authenticatorSelection: { authenticatorAttachment: "platform" }
}
};

const publicKeyCredential = await navigator.credentials.create(options);


ウェブサイトがデバイス内部の認証情報を利用して認証を行う際のポップアップはこんな感じ。認証情報がひとつしかない場合の画面は以下。



認証情報が複数存在すると、アカウントを選択するポップアップが表示されます。



デバイスによる認証を行う確認ポップアップを出現させるには、以下のようなコードを用いるとのこと。allowCredentials内の「transports: ["internal"]」でデバイス内部の認証情報を利用するように明示しており、navigator.credentials.get()で認証情報を取得しています。

const options = {
publicKey: {
challenge: challengeBuffer,
allowCredentials: [
{ type: "public-key", id: credentialIdBuffer1, transports: ["internal"] },
// ... more Credential IDs can be supplied.
]
}
};

const publicKeyCredential = await navigator.credentials.get(options);


「transports: ["internal"]」が指定されていない認証情報がある場合は、以下のようにセキュリティキーによる認証を選択できるポップアップが表示されるとTan氏は説明しています。



こうした認証を求めるポップアップが勝手に表示されてしまうのを防ぐために、ユーザー側で何らかの操作を行った後にポップアップを表示するサンプルコードも紹介されています。例えば、あるボタンがクリックされたら認証情報を生成するポップアップを表示する場合は、addEventListener()を用いて以下のようにコードを記述します。

button.addEventListener("click", async () => {
const options = {
publicKey: {
...
challenge: challengeBuffer,
...
}
};

const publicKeyCredential = await navigator.credentials.create(options);
});


Tan氏は「マルチファクター認証がパスワードだけの認証を置き換え、ウェブにおける一般的な認証方法になると確信しています」と語っており、開発者に対してFace IDとTouch IDによる認証機能のテストを求めています。