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

公開日: 2026 年 7 月 8 日、最終更新日: 2026 年 10 月 5 日

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

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

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

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

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

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

メール確認フロー

以降のセクションでは、メールアドレス確認フローを開始するために必要なものと、メールアドレス確認プロトコルを使用する場合のワークフロー全体について説明します。

主な用語

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

  • 検証サイト: メールアドレスを収集し、そのメールアドレスを検証したいサイト。検証ツールは、Relying Party とも呼ばれます。
  • メール プロバイダ: ユーザーのメールアドレスを提供するサービス(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 API と Email 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. トークンを解析する

フォーム送信からの未加工データには、チルダ(~ 文字)で区切られた Selective Disclosure JSON Web Token(SD-JWT+KB)の EVT と署名付きクレームが含まれています。これらを分離し、Javascript Object Signing and Encryption(JOSE)ヘッダーとペイロードをデコードする必要があります(たとえば、Node.js で jose を使用します)。

example.com が demo@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_verified が true に設定されていることを確認します。
  • 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 Web Key(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 つのステップがすべて成功すると、プロバイダに対してメールアドレスが確認されます。そうでない場合は、通常のフローに沿って確認メールをお客様に送信します。

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

詳細については、メール プロバイダのモックのデモコードを確認し、メール検証 API と メール検証プロトコルの提案で発行者の手順を参照してください。

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

発行者の検出を構成する

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

DNS 委任レコードを構成する

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

レコード形式: _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 エンドポイントをホストする

Federated Credentials(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"
    }
  ]
}

ログイン ステータス API と統合する

ユーザーはプロバイダとのアクティブなセッションを必要としており、ログイン ステータス 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 メーリング リストで随時お知らせします。