EC-CUBE / EC-CUBE/ec-cube

Email Verification Protocol (EVP / Chrome Origin Trial) への対応 — 会員登録のメール所有確認を省略

Open
#6,916 0 comments 0 reactions 0 assignees View on GitHub
affected:template affected:外部仕様 enhancement
Dominant language
PHP
Stars
788
Forks
719
Avg merge
3d 20h
Merged PRs (30d)
45

Description

## 概要

Chrome が **Email Verification Protocol (EVP)** の Origin Trial を開始した(2026-07-08 公開)。
EVP は、メールアドレス所有確認を **OTP や magic link のようにユーザーをサイト外へ遷移させることなく**、
ブラウザ経由で完結させる新しい Web プラットフォーム機能。会員登録フローの離脱率低減が主目的。

- API 提案: https://github.com/WICG/email-verification (Browser Email Verification API)
- プロトコル仕様: https://github.com/dickhardt/email-verification / IETF draft `draft-hardt-email-verification-00`
- Origin Trial 解説: https://developer.chrome.com/blog/email-verification-protocol-origin-trial

本 issue は、EC-CUBE を **Verifier(メールアドレスを収集・検証する側)** として EVP に対応させるための調査・実装設計を扱う。

## 用語と役割

| 役割 | 説明 | EVP における該当 |
|---|---|---|
| **Verifier** | メールアドレスを集め検証するサイト | **EC-CUBE(本体)** |
| **Email Provider / Issuer** | メールサービス・アカウント管理側(例: gmail.com / accounts.google.com) | Gmail 等(EC-CUBE 側の実装不要) |

EC-CUBE が実装するのは Verifier 側のみ。Issuer 側(DNS `_email-verification` 委譲レコード・`/.well-known/email-verification` エンドポイント・issuance API 等)は **メールプロバイダーの責務であり EC-CUBE では不要**。

## 解決する課題

現状 EC-CUBE の会員登録は「仮会員 → 確認メール送信 → メール内リンク(`secret_key`)をクリックで本会員化」という**メール往復による所有確認**を行っている。

- `src/Eccube/Controller/EntryController.php`
- `index()` (mode=complete, L113-157): `BaseInfo::isOptionCustomerActivate()` が有効なら `MailService::sendCustomerConfirmMail()` で `entry_activate` リンク付き確認メールを送信
- `activate()` (`/entry/activate/{secret_key}/{qtyInCart}`, L188-) → `entryActivate()` (L227-265): `getProvisionalCustomerBySecretKey()` で仮会員を引き当て、Status を `PROVISIONAL` → `REGULAR` に更新
- `Customer::$secret_key`(ユニーク制約, `StringUtil::random(32)`, `CustomerRepository::getUniqueSecretKey()`)

この「メールを開いてリンクを踏む」往復がユーザー離脱の一因。EVP を併用すると、対応ブラウザ + メールプロバイダーにサインイン済みのユーザーは、**登録フォーム送信と同時にメール所有が確認済みとなり、確認メールの往復を省略できる**。

## Verifier(EC-CUBE)側の実装内容

### 1. 会員登録フォームへの EVP 属性付与

現状、email 入力欄に `autocomplete` 属性が付いていない。EVP は以下を要求する。

- email input: `type="email"` + `autocomplete="email"`
- EVT 受け取り用の hidden field: `autocomplete="email-verification-token"` + `nonce`(リプレイ防止のランダム値)

対象:
- `src/Eccube/Form/Type/RepeatedEmailType.php`(`EntryType` L73 の `email` フィールドが利用。`entry` / `mypage_change` 共有)
- `src/Eccube/Resource/template/default/Entry/index.twig` L111-125(`form.email.first` / `form.email.second`)
- 出力 name は `entry[email][first]` / `entry[email][second]`。**確認用の 2 入力(RepeatedEmailType)と EVP をどう両立させるか**(EVP 前提時は確認欄を省略できるか)は要検討。

```html

```

### 2. EVT(Email Verification Token)の検証

フォーム送信時に付与される EVT を EC-CUBE サーバ側で検証する。EVT は **SD-JWT+KB**(`~` 区切り)形式。検証手順(記事準拠):

1. **トークン解析**: SD-JWT+KB を分解(JOSE ライブラリ利用。PHP なら `web-token/jwt-*` 等)
2. **基本クレーム検証**: `email_verified === true` / `email` がフォーム入力と一致 / `nonce` が hidden field と一致 / `aud` が自サイトの origin と一致 / `iat` が直近のタイムスタンプ
3. **Key Binding 検証**: `cnf` クレームのブラウザ一時鍵と `sd_hash`(`sha256(evtJwt + "~")` の base64url)を照合
4. **DNS 検証**: email ドメインの `_email-verification.` TXT レコードから `iss=` を取得し Issuer を確定
5. **署名検証**: Issuer の `/.well-known/email-verification` から `jwks_uri` を引き、JWK で EVT の署名を検証(`signing_alg_values_supported` は `EdDSA` / `ES256` 等)

検証成功時は、その email を**所有確認済み**として扱い、会員登録で仮会員(`PROVISIONAL`)を経ずに直接本会員(`REGULAR`)化する分岐を追加する。

### 3. フォールバックと段階的導入

- **非対応ブラウザ / EVT 未付与 / 検証失敗 時は、既存の `secret_key` 確認メールフローに必ずフォールバック**する(EVP を必須にしない)。Origin Trial 段階かつトラフィック制限がある機能のため。
- 有効/無効を店舗設定(`BaseInfo` 相当のフラグ)で切り替え可能にする(`isOptionCustomerActivate()` と同様のパターン)。
- Origin Trial 参加には Verifier サイトごとの **OT トークン登録**が必要(`` またはレスポンスヘッダ)。本番投入前提でない旨を明記。

## 影響範囲(email を入力/検証する箇所)

EVP 適用を検討しうる箇所を洗い出し(会員登録が第一対象、他は将来検討):

- **会員登録**(第一対象): `EntryController` / `EntryType` / `RepeatedEmailType` / `Entry/index.twig`
- マイページ会員情報変更(メール変更): `Mypage/ChangeController.php`(`EntryType` 再利用、`isOptionMailNotifier()` で変更通知メール)
- お問い合わせ: `ContactController` / `Front/ContactType.php`(`EmailType` 単一入力)
- パスワード再発行: `ForgotController`(`reset_key` 別系統。所有確認の側面あり)
- ログイン: `CustomerLoginType`(`login_email`)

## 対応方針(提案)

- **フェーズ 1(本 issue の主眼)**: 会員登録フォームへの `autocomplete` 属性付与 + EVT 検証サービスの新設(`Eccube\Service` 配下、HTTP 非依存の検証ロジック)+ 既存メール確認フローへのフォールバック。設定フラグで opt-in。
- **フェーズ 2**: マイページのメール変更・お問い合わせ等への横展開。
- 実装は **`app/Customize` で完結しない**(コアの `EntryController` / フォーム / テンプレート改変を伴う)ため、コア機能として設計する。EVT 検証は独立した Service に切り出し、決済プラグイン等と同様に拡張・差し替え可能な seam を用意する。

## 注意事項・リスク

- **仕様が不安定**: EVP は Origin Trial 段階。`request_token` の署名方式が **HTTP Message Signatures**(`draft-hardt-email-verification`)へ移行予定など、後方互換のない変更が予告されている。Chrome の UX も更新予定。**GA 前に本機能へ依存しないこと**(トラフィック制限あり)。
- **標準化は 2 系統並行**: WICG の Browser Email Verification API と IETF draft。動向を追跡する。
- Verifier 側は Issuer の well-known / DNS を**参照する**のみ(自前で公開する必要はない)。

## 参考

- https://developer.chrome.com/blog/email-verification-protocol-origin-trial
- https://github.com/WICG/email-verification
- https://github.com/dickhardt/email-verification
- Origin Trial 登録: https://developer.chrome.com/origintrials
- デモ(Verifier): https://rowan.fyi/made/email-verification

Contributor guide

Open the contributing guide

Research direction

Start by reading EntryController.php, EntryType, RepeatedEmailType.php, and Resource/template/default/Entry/index.twig to trace the current provisional-account and confirmation-mail flow. Review the referenced EVP, WICG, and IETF materials before deciding the verification boundary. Done means a documented phase-one design covering the opt-in flow, EVT validation seam, and reliable fallback without depending on the unstable protocol.

Written by the indexing model from the issue text.

Assessment

Tech stack
php, symfony
Domain
authentication, backend, security
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.