Salesforceテスト自動化で二段階認証を突破する現実解|TOTP自動生成とJWT注入

- SalesforceのMFA(多要素認証)が強制され、CI/CDでの夜間テスト自動化が止まってしまった
- メールに届く認証コードをAPIで取得しようとしたが、遅延やタイムアウトでテストが激しくフレイキー化している
- ヘッドレスブラウザ環境で二段階認証を安全・高速に自動突破する決定的な実装パターンを知りたい
MFA強制化で崩壊する自動テスト:メールOTP連携は今すぐやめろ
Salesforceで多要素認証(MFA)が契約上必須となり、多くのQAチームが悲鳴を上げました。
従来の「IDとパスワードを入れてログイン」という素朴なテストシナリオは、すべて認証コード画面で撃沈します。
ここで最もやってはいけない悪手があります。メールの受信トレイをAPIで監視し、届いた認証コードをパースして入力するアプローチです。
- メールの着信に10〜30秒のラグが発生し、テスト実行時間が数倍に膨れ上がる
- スパム判定やネットワーク遅延でコードが届かず、CIがランダムに赤(失敗)になる
- メールプロバイダの認証仕様変更やAPI制限で、テスト基盤ごと共倒れする
貴重なQAリソースをメール連携のバグ調査で溶かしてはいけません。
現場で採用すべき現実解は2つしかありません。**「TOTPシードキーによる動的コード生成」か、「JWTベアラフローによるログイン画面バイパス」**です。
現実解①:TOTPシードキーから動的にワンタイムパスワードを算出する
最も汎用的な手法がTOTP(Time-based One-Time Password)方式です。
既存の画面テストの流れを壊さずに二段階認証を突破できます。
認証アプリと同じ計算ロジックを使います。これをテストコードの内部で直接実行する仕組みです。
1. Salesforce側で秘密鍵(シードキー)を手動取得する
Salesforceで認証アプリを接続する際、QRコードを読んではいけません。
画面下の**「キーを手動で入力」**をクリックし、英数字の秘密鍵(Base32文字列)を控えます。
この秘密鍵を、CI/CDのシークレット環境変数(例: SF_TOTP_SECRET)として厳重に保管します。
2. Playwrightでの実装コード(TypeScript / otplib)
Node.js環境であれば、軽量なTOTP計算ライブラリ otplib を活用します。
import { test, expect } from '@playwright/test';
import { authenticator } from 'otplib';
test('Salesforceに二段階認証(TOTP)を突破してログインする', async ({ page }) => {
const username = process.env.SF_USERNAME!;
const password = process.env.SF_PASSWORD!;
const totpSecret = process.env.SF_TOTP_SECRET!;
// 1. 通常のID/パスワード入力
await page.goto('https://test.salesforce.com');
await page.getByLabel('ユーザー名').fill(username);
await page.getByLabel('パスワード').fill(password);
await page.getByRole('button', { name: 'ログイン' }).click();
// 2. 二段階認証画面の表示を待機
const otpInput = page.getByLabel('確認コード');
await expect(otpInput).toBeVisible({ timeout: 10000 });
// 3. 現在時刻から6桁のワンタイムコードを即座に生成
const token = authenticator.generate(totpSecret);
// 4. コードを入力して確認
await otpInput.fill(token);
await page.getByRole('button', { name: '確認' }).click();
// 5. ホーム画面の表示確認
await expect(page).toHaveURL(/lightning\/page\/home/);
});
メール受信を待つ必要は一切ありません。ミリ秒単位で最新の6桁コードが計算されるため、待機時間は実質ゼロです。
現実解②:JWTベアラフローでセッションを直接ブラウザに注入する
さらに実行速度と安定性を極限まで高めたいなら、**「UIログインそのものをスキップする」**のがシニアQAの常套手段です。
Salesforceの「OAuth 2.0 JWTベアラフロー」を活用します。API経由で事前にセッションID(アクセストークン)を取得する手法です。
仕組みと処理フロー
[テストランナー] --- (1) 秘密鍵で署名したJWTを送信 ---> [Salesforce OAuth]
[テストランナー] <--- (2) Access Token (Session ID) 返却 - [Salesforce OAuth]
│
▼ (3) ブラウザのCookie(sid)にトークンをセット
[Playwright Browser] ---> (4) ホーム画面URLへ直接アクセス (ログイン画面スキップ)
- 事前にSalesforceに「接続アプリケーション」を作成し、デジタル証明書を登録
- テスト実行開始時、裏側でNode.jsからOAuthエンドポイントへトークンリクエストを発行(約0.3秒)
- 取得したトークンを使い、PlaywrightのBrowserContextにセッションクッキー(
sid)を直接セット - ログイン後のトップページURLへ直接
page.goto()する
ログイン画面の描画待ち、ID/パスワードの入力、MFA判定の処理が丸ごと消え去ります。ログイン処理に要する時間は15秒から1秒未満へ短縮されます。
2つのアプローチの使い分け比較
| 項目 | ① TOTP動的生成 | ② JWTセッション注入 |
|---|---|---|
| 突破方式 | 画面上で6桁コード入力 | ログイン画面を完全バイパス |
| 所要時間 | 約3〜5秒 | 約0.5〜1秒(爆速) |
| Salesforce設定 | ユーザごとのMFA秘密鍵登録のみ | 接続アプリ・デジタル証明書の設定が必要 |
| 向いているテスト | ログイン画面自体の挙動も担保したい場合 | 業務シナリオ(商談作成・承認フロー等)の大量実行 |
ログイン画面自体の挙動も担保したいなら ① TOTP動的生成 です。その後の膨大な業務フローを高速に回したいなら ② JWT注入 を選ぶのが現場の鉄則です。
まとめ:CI/CDを止めないテストアーキテクチャを組む
- メールOTP監視は即刻廃止: 遅延とフレイキーの温床であり、保守コストに見合わない
- 画面テストはTOTP動的計算: `otplib` でシードキーからミリ秒で6桁コードを生成する
- 業務シナリオはJWTバイパス: ログイン画面をスキップしてセッション注入し、実行時間を最短化する
「二段階認証があるから自動テストは無理だ」と諦める必要はありません。
認証の仕組みを正しくハックし、壊れにくく高速なテストパイプラインを構築しましょう。
