オリジン トライアルでメール確認プロトコルをテストする

公開日: 2026 年 7 月 8 日

登録、ログイン、定期購入、購入手続き、アカウント復元などのプロセスでメールアドレスを収集する場合、入力したメールアドレスが入力したユーザーのものであることを確認するのが一般的です。ワンタイム パスワード(OTP)やメール確認リンク(マジックリンク)などの既存の確認方法では、ユーザーがサイトから離れる必要があります。この中断を伴うプロセスにより、ユーザー(人間またはエージェント)がセッションを完全に放棄し、認証プロセスを完了しないリスクが高まる可能性があります。

Email Verification API は、ブラウザがメール プロバイダと直接通信して、ユーザーがメールアドレスを所有していることを確認できるようにする提案です。 ユーザーは、ブラウザの自動入力またはオートコンプリートの候補からメールアドレスを選択してフォームを送信すると、サイトはメールを送信したりユーザーのフローを中断したりすることなく、プロバイダにメールアドレスを確認します。

Email Verification API のユーザー プロンプトのデモ
Email Verification API のユーザー プロンプトのデモ

メールアドレスの収集は、ユーザー ジャーニーにおける重要なコンバージョン ポイントです。Chrome では、提案に関するフィードバックを、メールアドレスの確認を希望するサイト、確認を実行できるメール プロバイダ、 プロセスを体験しているユーザーから募集しています。オリジン トライアルに 登録 して、こちらの実装手順に沿って実装してください。オリジン トライアルの一般的な構成については、オリジン トライアルのスタートガイドをご覧ください

デモ アカウントでフローを試すことができます。

  • 発行者のデモでは、モックのメール アカウントとセッションが提供されます。
  • 検証者のデモでは、参加している プロバイダが検証されます。

メール確認フロー

以降のセクションでは、メール確認フローを開始するために必要なことと、Email Verification Protocol を使用する場合のワークフロー全体について説明します。

主な用語

Email Verification API の主な用語は次のとおりです。

  • 検証者: メールアドレスを収集して検証するサイト。検証者は、証明書利用者 とも呼ばれます
  • メール プロバイダ: ユーザーのメールアドレスを提供するサービス( 例: gmail.com)。
  • 発行者: ユーザーのメールのアカウントを管理するサービス( accounts.google.comなど)。発行者は、ID プロバイダとも呼ばれます。

メール プロバイダと発行者が同じドメインから運営されている場合もあります。ただし、メールアドレスを持っていることと、関連付けられたアカウントの有効なセッションを持っていることを区別することが重要です。

メール認証フローのアーキテクチャ
メール確認フローのアーキテクチャ

前提条件

  • ユーザーは、同じブラウザ プロファイルでメール プロバイダまたは発行者にログインしている必要があります。たとえば、Gmail を使用している場合は、Google アカウントにログインしている必要があります。
  • 参加している検証者サイトとして、オリジン トライアルに登録し、メールフォームと同じページにトークンを指定する必要があります。
  • ユーザーは、自動入力またはオートコンプリートのプルダウンからメールアドレスを選択する必要があります。

    • ユーザーが以前にフィールドにメールアドレスを入力したことがある場合は、オートコンプリートを使用して候補が表示されます。
    • ユーザーが Chrome の設定 [自動入力とパスワード](chrome://settings/autofill)を使用してメールアドレスを追加した場合は、自動入力を使用して候補が表示されます。

  • ユーザーがメールアドレスを検証用に初めて入力すると、権限プロンプトが表示されます。これは、メールアドレスごとに 1 回のみ発生します。

ユーザーがブラウザで有効なセッションを開始したら、次の手順でプロセスを開始できます。

  1. メールフィールドを含むフォームで、ユーザーはオートコンプリートのプルダウンからメールアドレスを選択します。検証者サイトは、このリクエストを検証するために、インスタンスごとのノンスを含む非表示フィールドをフォームに指定します。
  2. ブラウザは、メール ドメインのメール確認 DNS レコードを取得します。これにより、ブラウザは発行者を指します。発行者は、そのメールアドレスの有効なセッションがあることを確認します。

  3. 発行者は、アドレスのメール確認トークン(EVT)を提供します。 ブラウザは、EVT、サイトのオリジン、入力フォームのノンスを組み合わせて、鍵でバインドされた JWT を作成します。

  4. フォームが送信されると、EVT パッケージが非表示フィールドに追加され、サイトに送信されます。

  5. 検証者サイトは、想定されるメールアドレス、ノンス、ブラウザと発行者の署名など、各詳細情報を検証します。

  6. ユーザーには、メール プロバイダがアドレスを確認したことを知らせる小さな通知が表示されます。

このプロセスにより、検証者サイトはメールアドレスが有効で現在のユーザーに属していることを確認できるため、サイトは確認メールの送信をスキップできます。

ユーザーは、[設定] > [自動入力とパスワード] > [連絡先情報] > [確認済みのメールアドレス](または chrome://settings/contactInfo)で、確認済みのメールアドレスを管理できます。

ユースケースに関する考慮事項

メール確認は、既存のフローを段階的に改善するもので、ユーザーがサイトから離れて OTP を取得したり、リンクをクリックしたりする必要がなくなります。サイトは、ログイン、ニュースレターの登録、アカウント作成、パスワードの復元など、関連するすべてのフォームにメール確認フィールドを追加できます。EVP は、ブラウザがサポートしている場合にのみトリガーされます。送信時にコードが受信されない場合や、検証ステップのいずれかが失敗した場合は、デフォルトのメール確認フローに戻ることができます。これは、API の機能検出がないことも意味します。検証者サイトは EVT を省略可能として扱い、リクエストに存在する場合は処理します。

メール確認では、ユーザーがメールアドレスのプロバイダとの有効なセッションを持っていることを確認します。メールがユーザーに届いたことは確認しません。 既存のウェルカム メールやオンボーディング メールを送信する必要がある場合や、ユーザーに迷惑メールの設定を確認するよう促す必要がある場合があります。

検証者サイトを実装する

詳細については、エンドツーエンドのデモ コード を確認し、Email Verification APIEmail Verification Protocol の提案の検証ステップをご覧ください。

フォーム フィールドを構成する

フォーム フィールドに正しい属性があることを確認します。

<input
  name="email-address"
  type="email"
  autocomplete="email">
<input
  type="hidden"
  name="token"
  nonce="rAnD0m-VaLuE"
  autocomplete="email-verification-token">

email 入力の type 属性と autocomplete 属性を email に設定すると、ブラウザでメールアドレスのオートコンプリートを使用できます。

新しい hidden フィールドには、フォームの送信時にメール確認トークンが入力されます。必要な属性は次のとおりです。

  • このフィールドにはユーザー入力が必要ないため、type="hidden" を設定します。
  • nonce="rAnD0m-VaLuE" を設定します。サイトは、フォームの送信を検証するために、セッションにバインドされた一意のノンスを指定する必要があります。
  • autocomplete="email-verification-token" を設定します。ブラウザはこの属性を使用して、入力するフィールドを識別します。

DevTools の [ネットワーク] パネルでフォーム要素を検証します。メールアドレスを選択すると、ブラウザがメール プロバイダと発行者の DNS と後続のアカウント検索クエリをトリガーします。これらは内部ブラウザのリクエストです。フォームが送信されるまで、サイトは何も受信しません。

EVT を検証する

EVT パッケージの各コンポーネントを検証する手順は 5 つあります。

  1. トークンを解析します。
  2. 想定される値を検証します。
  3. 鍵のバインディングを検証します。
  4. DNS レコードを検証します。
  5. 発行者を見つけて EVT 署名を検証します。

1. トークンを解析する

フォームの送信からの生データには、チルダ (~ 文字)で区切られた、 選択的開示 JSON ウェブトークン (SD-JWT+KB)の EVT と署名付きクレームが含まれています。これらを分離し、JavaScript Object Signing and Encryption(JOSE)のヘッダーとペイロードをデコードする必要があります(たとえば、Node.js 用の joseを使用します)。

example.comdemo@gmail.com を検証する場合、デコードされたペイロードは次の例のようになります。

{
  "evtJwtDecodedPayload": {
    "cnf": {
      "jwk": {
        "crv": "Ed25519",
        "kty": "OKP",
        "x": "pUbLiCkEy123pUbLiCkEy123pUbLiCkEy123"
      }
    },
    "email": "demo@gmail.com",
    "email_verified": true,
    "iat": 1782911685,
    "iss": "https://accounts.google.com"
  },
  "kbJwtDecodedPayload": {
    "aud": "https://example.com",
    "iat": 1782911685,
    "nonce": "rAnDoM123rAnDoM123rAnDoM123rAnDoM123",
    "sd_hash": "hAsH456hAsH456hAsH456hAsH456hAsH456"
  }
}

2. 想定される値を検証する

ペイロードの基本値が指定した値と一致していることを確認します。

  • email_verifiedtrue に設定されていることを確認します。
  • email がフォームで指定したメールアドレスと一致していることを確認します。
  • nonce がフォームで指定したノンスと一致していることを確認します。
  • aud がサイトのオリジンと一致していることを確認します。
  • iat のタイムスタンプが比較的最近のものであることを確認します(たとえば、フォームのレンダリング後など)。

3. 鍵のバインディングを検証する

ブラウザは、トークンに署名したことを確認するために、トランザクションの一時的な鍵を作成します。この鍵を EVT の cnf(確認)クレームから抽出し、それを使用して鍵でバインドされた JWT を検証します。

次に、想定されるハッシュを計算し、sd_hash クレームと比較します。次の Node.js の例は、この計算を行う方法を示しています。

const calculatedHash = createHash("sha256")
        .update(evtJwt + "~")
        .digest("base64url");

4. DNS レコードを検証する

メールアドレス ドメインの _email-verification DNS レコードを確認します。たとえば、demo@gmail.com の場合は、_email-verification.gmail.com TXT レコードをクエリします。このプロバイダの場合、クエリはアカウント プロバイダの場所(accounts.google.com)を返します。

$ dig +short TXT _email-verification.gmail.com
"iss=accounts.google.com"

5. 発行者を見つけて EVT 署名を検証する

発行者が /.well-known/email-verification リソースを提供していることを確認します。このリソースは、トークンの発行に使用するエンドポイント、サイトの JSON ウェブ鍵(JWK)、サポートされている署名アルゴリズムを提供します。

$ curl https://accounts.google.com/.well-known/email-verification
{
  "issuance_endpoint": "https://accounts.google.com/gsi/email-verification/issue",
  "jwks_uri": "https://verifiablecredentials-pa.googleapis.com/.well-known/vc-public-jwks",
  "signing_alg_values_supported": ["EdDSA"]
}

JWK を使用して、トークンから抽出した EVT JWT を検証します。ほとんどの JOSE ライブラリには、この検証を処理する関数が用意されています。

5 つのステップがすべて成功したら、プロバイダに対してメールアドレスが検証されます。そうでない場合は、通常のフローに従って確認メールをユーザーに送信します。

メール プロバイダと発行者サービスを実装する

詳細については、モックのメール プロバイダのデモ コード を確認し、Email Verification APIEmail Verification Protocol の提案の発行者ステップをご覧ください。

発行者として、オリジン トライアルに登録したり、トークンを指定したりする必要はありません。ブラウザの動作は証明書利用者サイトによってトリガーされるためです。 これらのリクエストに応答するために、想定されるエンドポイントが用意されていることを確認するだけです。

発行者の検出を構成する

ドメインに属するメールアドレスが選択されたときに、ブラウザが検証エンドポイントを自動的に検出できるようにするには、DNS と .well-known HTTP エンドポイントを使用して構成を公開します。

DNS デリゲート レコードを構成する

発行者 ID に検証権限を委任する DNS TXT レコードをメール ドメインに構成します。インフラストラクチャによっては、これらの ID で同じドメインを使用できます。

レコード形式: _email-verification.<email-domain>

ゾーンファイルの例:

_email-verification.example.com IN TXT "iss=accounts.issuer.example"

.well-known/email-verification エンドポイントをホストする

発行者ドメインの /.well-known/ パスに JSON メタデータ ファイルをホストします。 このファイルには、発行機能と、インフラストラクチャがサポートする暗号署名アルゴリズムの概要が記載されています。

エンドポイント: https://<issuer-domain>/.well-known/email-verification

レスポンスの例:

{
  "issuance_endpoint": "https://accounts.issuer.example/email-verification/issuance",
  "jwks_uri": "https://accounts.issuer.example/.well-known/vc-public-jwks",
  "signing_alg_values_supported": ["EdDSA", "ES256"]
}

.well-known/web-identity エンドポイントをホストする

フェデレーション認証情報(FedCM)API の一部としてすでに実装されている可能性がある、追加の .well-known JSON リソース。これにより、アカウント エンドポイントとログイン URL へのリンクが提供されます。

エンドポイント: https://<domain>/.well-known/web-identity

レスポンスの例:

{
  "accounts_endpoint": "https://accounts.issuer.example/accounts",
  "login_url": "https://accounts.issuer.example/login"
}

アカウント エンドポイントを使用する

FedCM API のアカウント エンドポイントは、現時点でログインしているアカウントのリストを提供します。最小限のレスポンスの例を次に示します。詳細については、ID プロバイダの実装 ガイドをご覧ください。

エンドポイント: .well-known/web-identity で指定されているとおり

レスポンスの例を次に示します。

{
  "accounts": [
    {
      "id": "demo-example",
      "name": "Demo User",
      "email": "demo@example.com",
      "given_name": "Demo"
    }
  ]
}

Login Status API と統合する

ユーザーはプロバイダとの有効なセッションを持っている必要があり、 Login Status API を使用してブラウザにそのことを通知する必要があります。

ユーザーが正常にログインまたはログアウトした場合は、一致する HTTP レスポンス ヘッダーを提供します。

Set-Login: logged-in
Set-Login: logged-out

または、ウェブ アプリケーション コンテキストで JavaScript を使用してステータスを更新します。

navigator.login.setStatus("logged-in");
navigator.login.setStatus("logged-out");

発行リクエストを処理する

issuance_endpoint は、request_token を含む application/x-www-form-urlencoded POST リクエストを受け取ります。

以降のセクションでは、発行リクエストを処理するプロセス全体について説明します。

1. 発行リクエストを検証する

受信したブラウザのペイロードを解析して検証します。

  • メソッド: POST
  • セッションの検証: リクエストとともに送信されたユーザーのファーストパーティ session/authentication Cookie を検証して、有効な認可済み ID コンテキストが存在することを確認します。
  • パラメータの検証: request_token パラメータ(ブラウザによって生成された署名付き JWT)を抽出します。想定される一時的な公開鍵、ターゲット メール、正しいオーディエンス、有効なタイムスタンプが含まれていることを確認します。

デコードされたトークンは次のようになります。

{
  "decodedHeader": {
    "alg": "ES256",
    "typ": "JWT",
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "pUbLiCKeY123pUbLiCKeY123pUbLiCKeY123",
      "y": "pUbLiCKeY456pUbLiCKeY456pUbLiCKeY456"
    }
  },
  "decodedPayload": {
    "iss": "https://accounts.issuer.example",
    "sub": "demo@example.com",
    "email": "demo@example.com",
    "iat": 1780272000,
    "exp": 1780272300
  },
  "signature": "SIGnatURE-123_SIGnatURE-123_SIGnatURE-123"
}

2. トークンで応答する

セッションとリクエスト トークンの検証が成功したら、ペイロードを使用して署名付きの選択的開示 JWT(SD-JWT)を生成します。

{
  "iss": "https://accounts.issuer.example",
  "iat": 1780272000,
  "exp": 1780272300,
  "cnf": {
    "jwk": {
      "kty": "EC",
      "crv": "P-256",
      "x": "pUbLiCKeY123pUbLiCKeY123pUbLiCKeY123",
      "y": "pUbLiCKeY456pUbLiCKeY456pUbLiCKeY456"
    }
  },
  "email": "demo@example.com",
  "email_verified": true
}

秘密鍵とサポートされているアルゴリズムを使用してペイロードに署名します。たとえば、 Node.js で jose を使用する場合:

const evtJwt = await new SignJWT(evtPayload)
   .setProtectedHeader({
     alg: "EdDSA",
     kid: PRIVATE_KEY_JWK.kid, // Key ID corresponding to our JWKS keys
     typ: "evt+jwt", // Standard Token Type for EVTs
   })
   .sign(privateKey);

 // Standard SD-JWT compatibility requires appending a trailing tilde "~"
 // to separate the signed token from the key binding section.
 const issuanceToken = `${evtJwt}~`;

成功レスポンスの例(HTTP 200):

{
  "issuance_token": "tOkEn123tOkEn123tOkEn123...~"
}

オリジン トライアルに関する考慮事項

オリジン トライアルはフィードバックを収集するためのテストです。証明書利用者または ID プロバイダとして参加する場合は、ご意見をお寄せください。問題を報告するには、次の GitHub リポジトリを使用します。

Chrome の実装でバグが発生した場合は、次のコンポーネントに対してバグを報告してください。

オリジン トライアル機能の有効化は、OT トークンを含めることでレスポンスごとに制御されます。つまり、機能を一部のユーザーに制限する場合は、きめ細かい制御が可能です。たとえば、A/B テスト フレームワークがすでに存在する場合は、オリジン トライアルを統合して、管理されたテスト対象ユーザーを設定できます。また、ユーザーのベータ版テスト グループまたは早期プレビュー グループがある場合は、そのグループに対して機能を有効にする必要がある場合があります。この場合は、トークンを発行または検証する前に、指定されたメールアドレスを確認してください。

オリジン トライアルには、リリース前に機能に依存するサイトを最小限に抑えるためのトラフィック制限もあります。発行者 API は開発中であり、Chrome UX の更新とともに下位互換性のない変更が加えられる可能性があります。

開発の進捗状況に応じて、こちらのブログと evp-announce@chromium.org メーリング リストで最新情報をお知らせします。