この翻訳は不完全です。英語から この記事を翻訳 してください。

これは実験的な機能です。本番で使用する前にブラウザー実装状況をチェックしてください。

Secure context
This feature is available only in secure contexts (HTTPS), in some or all supporting browsers.

Web Authentication API は公開鍵暗号を用いて強力な認証を行う Credential Management API の拡張機能で、パスワードを用いない認証に加え、SMS を用いない二要素認証を実現します。

Web authentication の概念と使い方

Web Authentication API (別名 WebAuthn) はウェブサイトの登録・認証・二要素認証公開鍵暗号 をパスワードや SMS の代わりに利用します。これは フィッシング情報漏洩・ SMS や他の二要素認証に対する攻撃といった厄介なセキュリティ問題を解決し、同時にユーザーの利便性を向上させます。(ユーザーが多くのパスワードを管理する必要がなくなるため)

多くのウェブサイトが既にアカウントの登録や作成したアカウントにログインするウェブページを提供しています。 WebAuthn は既存のウェブページの代替または補足として機能します。 Credential Management API の他の形式と同様に、 Web Authentication API は登録とログインの2つの基本的な機能を持っています。

  • navigator.credentials.create() - publicKey オプションと併用すると、新しいアカウントの登録または既存のアカウントへの新しい非対称鍵ペアの関連付けを行うために新しい認証情報を作成します。
  • navigator.credentials.get() - publicKey optionと併用すると、ログインまたは二要素認証の形式でサービスを認証する既存の認証情報セットを使用します。

註: create() と get() は両方ともセキュアコンテキスト (サーバと暗号化通信をしているか、localhost と通信している場合)であることを必要とし、ブラウザーがセキュアコンテキストで動作していない場合は利用できません。

もっとも基本的な形式では、 create() と get() はサーバーからチャレンジと呼ばれる大きな数値を受け取り、チャレンジを秘密鍵で署名してサーバーへ送り返します。この方法でユーザがネットワーク上に秘密にすべき情報を流すことなくサーバーにユーザが必要な秘密鍵を所持していることを証明します。

create() と get() 関数が大きな画像にどのように適合しているか理解するためには、それらがブラウザー外の2つのコンポーネント間にあることを理解することが重要です。

  1. サーバー - WebAuthn API はサーバー (サービスや relying party) に認証情報を登録し、以後ユーザー認証には同じサーバーに同じ認証情報を使うことを意図しています。
  2. オーセンティケーター - 作成された認証情報はオーセンティケーターと呼ばれるデバイス内に格納されます。パスワード認証では、パスワードはユーザーの頭の中に格納され、他のデバイスは必要ありません。 WebAuthn認証なら、パスワードは鍵ペアに置き換えられ、オーセンティケーターに格納されます。オーセンティケーターは Windows Hello などの OS に組み込まれていても良く、 USB や Bluetooth セキュリティキーなどの物理トークンであっても良いのです。これは新しい認証コンセプトです。

登録

典型的な登録過程は図1に示す6つの手順を踏みます。これは概要説明のみを目的とした登録過程に必要なデータを単純化したものです。必須フィールドと任意フィールド、登録リクエスト作成の意味は PublicKeyCredentialCreationOptions に記述されています。同様に、応答フィールドは PublicKeyCredential インタフェース (ただし PublicKeyCredential.responseAuthenticatorAttestationResponse インタフェース)に記載されています。アプリケーションを作っているほとんどの JavaScript プログラマーはcreate() が呼び出され、返り値が手に入る手順1と5のみを気にする必要があります。しかしブラウザとオーセンティケーター間で行われる処理とその結果のデータの意味を理解するためには手順2,3,4を理解することが不可欠です。

WebAuthn registration component and dataflow diagram

図1 - WebAuthn による登録手順と各アクションに関連する必須データ

登録手順

  1. アプリケーションが登録要求を行う - アプリケーションは最初の登録リクエストを作成します。このリクエストのプロトコルとフォーマットは WebAuthn の範囲外で定められます。
  2. サーバーがチャレンジ・ユーザー情報・Relying Party 情報を送信 - サーバーはチャレンジ・ユーザ情報・ Relying party 情報を JavaScript プログラムに送信します。このときのプロトコルも特に指定はなく、 WebAuthn の範囲外で定められます。通常、サーバ通信は XMLHttpRequestFetch を用いた HTTPS を介して REST 通信で行いますが、安全な通信であれば SOAPRFC 2549 、その他ほとんどのプロトコルを使用しても構いません。サーバーから受け取ったパラメーターは create() 関数に渡され、通常少し改変するか全く改変せずに AuthenticatorAttestationResponse を含む PublicKeyCredential に解決する Promise を返します。 チャレンジはランダムな情報の大きなバッファー(例えば100バイト以上)が絶対に重要であり、登録過程のセキュリティを確保するために必ずサーバー上で生成しなくてはなりません。
  3. ブラウザーがオーセンティケーターの authenticatorMakeCredential() を呼び出す - 内部的にブラウザーはパラメーターを検証し、デフォルト値を入れて AuthenticatorResponse.clientDataJSON 形式にします。最も重要なパラメーターは origin であり、後でサーバーがオリジンを検証できるように clientData に保存されています。client() 関数のパラメーターは clientDataJSON の SHA-256 ハッシュ値と共にオーセンティケーターに渡されます。(オーセンティケーターへの接続が低帯域幅の NFC または Bluetooth である可能性があり、オーセンティケーターがハッシュに署名して改ざんされていないことを保証するためにハッシュのみを送信します)
  4. オーセンティケーターが新しい鍵ペアと証明書を作成 - これを行う前に、通常オーセンティケーターは何らかの形でユーザーが存在し、登録に同意していることを確認します。方法は PIN の入力や指紋・虹彩認証などがあります。ユーザ確認後、オーセンティケーターは非対称鍵ペアを作成し、後に使用する秘密鍵を安全に保存します。公開鍵は証明書の一部になり、オーセンティケーターはこのプロセス中にオーセンティケーター中に焼かれた秘密鍵で署名します。そうすることでルート認証局にさかのぼって検証可能な証明書チェインを持ちます。
  5. オーセンティケーターがブラウザーにデータを返す - グローバルユニークなクレデンシャルIDの新しい公開鍵と他の認証データをブラウザーに返され、そこで attestationObject になります。
  6. ブラウザーが最後のデータを作成し、アプリケーションがサーバにレスポンスを送信 - The create() Promise resolves to an PublicKeyCredential, which has a PublicKeyCredential.rawId that is the globally unique credential id along with a response that is the AuthenticatorAttestationResponse containing the AuthenticatorResponse.clientDataJSON and AuthenticatorAttestationResponse.attestationObject. The PublicKeyCredential is sent back to the server using any desired formatting and protocol (note that the ArrayBuffer properties need to be be base64 encoded or similar).
  7. サーバーが登録を検証・完了させる - Finally, the server is required to perform a series of checks to ensure that the registration was complete and not tampered with. These include:
    1. Verifying that the challenge is the same as the challenge that was sent
    2. Ensuring that the origin was the origin expected
    3. Validating that the signature over the clientDataHash and the attestation using the certificate chain for that specific model of the authenticator
    A complete list of validation steps can be found in the WebAuthn specification. Assuming that the checks pan out, the server will store the new public key associated with the user's account for future use -- that is, whenever the user desires to use the public key for authentication.

認証

After a user has registered with WebAuthn, they can subsequently authenticate (a.k.a. - login or sign-in) with the service. The authentication flow looks similar to the registration flow, and the illustration of actions in Figure 2 may be recognizable as being similar to the illustration of registration actions in Figure 1. The primary differences between registration and authentication are that: 1) authentication doesn't require user or relying party information; and 2) authentication creates an assertion using the previously generated key pair for the service rather than creating an attestation with the key pair that was burned into the authenticator during manufacturing. Again, the description of authentication below is a broad overview rather than getting into all the options and features of WebAuthn. The specific options for authenticating can be found in the PublicKeyCredentialRequestOptions dictionary, and the resulting data can be found in the PublicKeyCredential interface (where PublicKeyCredential.response is the AuthenticatorAssertionResponse interface) .

WebAuthn authentication component and dataflow diagram

Figure 2 - similar to Figure 1, a diagram showing the sequence of actions for a WebAuthn authentication and the essential data associated with each action.

  1. Application Requests Authentication - The application makes the initial authentication request. The protocol and format of this request is outside of the scope of WebAuthn.
  2. Server Sends Challenge - The server sends a challenge JavaScript program. The protocol for communicating with the server is not specified and is outside of the scope of WebAuthn. Typically, server communications would be REST over https (probably using XMLHttpRequest or Fetch), but they could also be SOAP, RFC 2549 or nearly any other protocol provided that the protocol is secure. The parameters received from the server will be passed to the get() call, typically with little or no modification. Note that it is absolutely critical that the challenge be a large buffer of random information (e.g. - more than 100 bytes) and it MUST be generated on the server in order to ensure the security of the authentication process.
  3. Browser Call authenticatorGetCredential()  on Authenticator - Internally, the browser will validate the parameters and fill in any defaults, which become the AuthenticatorResponse.clientDataJSON. One of the most important parameters is the origin, which recorded as part of the clientData so that the origin can be verified by the server later. The parameters to the create() call are passed to the authenticator, along with a SHA-256 hash of the clientDataJSON (only a hash is sent because the link to the authenticator may be a low-bandwidth NFC or Bluetooth link and the authenticator is just going to sign over the hash to ensure that it isn't tampered with).
  4. Authenticator Creates an Assertion - The authenticator finds a credential for this service that matches the Relying Party ID and prompts a user to consent to the authentication. Assuming both of those steps are successful, the authenticator will create a new assertion by signing over the clientDataHash and authenticatorData with the private key generated for this account during the registration call.
  5. Authenticator Returns Data to Browser -  The authenticator returns the authenticatorData and assertion signature back to the browser.
  6. Browser Creates Final Data, Application sends response to Server - The browser resolves the Promise to a PublicKeyCredential with a PublicKeyCredential.response that contains the AuthenticatorAssertionResponse. It is up to the JavaScript application to transmit this data back to the server using any protocol and format of its choice.
  7. Server Validates and Finalizes Authentication - Upon receiving the result of the authentication request, the server performs validation of the response such as:
    1. Using the public key that was stored during the registration request to validate the signature by the authenticator.
    2. Ensuring that the challenge that was signed by the authenticator matches the challenge that was generated by the server.
    3. Checking that the Relying Party ID is the one expected for this service.
    A full list of the steps for validating an assertion can be found in the WebAuthn specification. Assuming the validation is successful, the server will note that the user is now authenticated. This is outside the scope of the WebAuthn specification, but one option would be to drop a new cookie for the user session.

Interfaces

CredentialsContainer
WebAuthn extends the Credential Management API's create() and get() methods to take a new option: publicKey. When the publicKey option is passed to create() and / or get(), the Credential Management API will create a new public key pair or get an authentication for a key pair, respectively.
PublicKeyCredential
A credential for logging in to a service using an un-phishable and data-breach resistant asymmetric key pair instead of a password.
AuthenticatorResponse
Part of the PublicKeyCredential, the AuthenticatorResponse includes information from the browser (such as the challenge and origin); as well as information from the authenticator such as an AuthenticatorAttestationResponse (for new credentials) or an AuthenticatorAssertionResponse (when authenticating with existing credentials).
AuthenticatorAttestationResponse
When a PublicKeyCredential has been created with the create() call, it will include an AuthenticatorAttestationResponse. This is the authenticator's way of providing a cryptographic root of trust for the new key pair that has been generated.
AuthenticatorAssertionResponse
When a PublicKeyCredential is the result of a get() call, it will include an AuthenticatorAssertionResponse. This is the authenticator's way of proving to a service that it has the key pair and that the authentication request is valid and approved.

Options

PublicKeyCredentialCreationOptions
The options for creating a credential via navigator.credentials.create()
PublicKeyCredentialRequestOptions
The options for using a credential via navigator.credentials.get()

註: セキュリティ機能として、 create() や get() のような WebAuthn 関数の実行中にブラウザーウィンドウがフォーカスを失うとキャンセルされます。

// 登録のサンプル引数
var createCredentialDefaultArgs = {
    publicKey: {
        // Relying Party (a.k.a. - Service):
        rp: {
            name: "Acme"
        },

        // User:
        user: {
            id: new Uint8Array(16),
            name: "john.p.smith@example.com",
            displayName: "John P. Smith"
        },

        pubKeyCredParams: [{
            type: "public-key",
            alg: -7
        }],

        attestation: "direct",

        timeout: 60000,

        challenge: new Uint8Array([ // サーバーから暗号学的にランダムな値が送られていなければならない
            0x8C, 0x0A, 0x26, 0xFF, 0x22, 0x91, 0xC1, 0xE9, 0xB9, 0x4E, 0x2E, 0x17, 0x1A, 0x98, 0x6A, 0x73,
            0x71, 0x9D, 0x43, 0x48, 0xD5, 0xA7, 0x6A, 0x15, 0x7E, 0x38, 0x94, 0x52, 0x77, 0x97, 0x0F, 0xEF
        ]).buffer
    }
};

// ログインのサンプル引数
var getCredentialDefaultArgs = {
    publicKey: {
        timeout: 60000,
        // allowCredentials: [newCredential] // 下記参照
        challenge: new Uint8Array([ // サーバーから暗号学的にランダムな値が送られていなければならない
            0x79, 0x50, 0x68, 0x71, 0xDA, 0xEE, 0xEE, 0xB9, 0x94, 0xC3, 0xC2, 0x15, 0x67, 0x65, 0x26, 0x22,
            0xE3, 0xF3, 0xAB, 0x3B, 0x78, 0x2E, 0xD5, 0x6F, 0x81, 0x26, 0xE2, 0xA6, 0x01, 0x7D, 0x74, 0x50
        ]).buffer
    },
};

// 新しい認証情報の作成/登録
navigator.credentials.create(createCredentialDefaultArgs)
    .then((cred) => {
        console.log("NEW CREDENTIAL", cred);

        // 通常はサーバーから利用可能なアカウントの認証情報が送られてきますが
        // この例では上からコピーしただけです。
        var idList = [{
            id: cred.rawId,
            transports: ["usb", "nfc", "ble"],
            type: "public-key"
        }];
        getCredentialDefaultArgs.publicKey.allowCredentials = idList;
        return navigator.credentials.get(getCredentialDefaultArgs);
    })
    .then((assertion) => {
        console.log("ASSERTION", assertion);
    })
    .catch((err) => {
        console.log("ERROR", err);
    });

Specifications

Specification Status Comment
Web Authentication: An API for accessing Public Key Credentials Level 1 勧告候補 Initial definition.

ブラウザ実装状況

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Basic support Nightly build 60 (60)[1] 未サポート 未サポート 未サポート
Feature Android Webview Chrome for Android Firefox Mobile (Gecko) IE Phone Opera Mobile Safari Mobile
Basic support 未サポート 未サポート 未サポート[1] 未サポート 未サポート 未サポート

[1] Web authentication has been restricted to active documents (バグ 1409202).

See also

ドキュメントのタグと貢献者

このページの貢献者: takubokudori
最終更新者: takubokudori,