フロントエンド(SPA)からHeadless Identity APIを呼び出す際、ブラウザ特有のセキュリティ制約(CORSやOpaque Redirect)が技術的な障壁となります。
第四弾である本記事では、React環境での制約突破手法と、開発効率を維持するための対策を解説します。
前回の記事はこちら
【ペットクリニックサイト 制作日誌 Vol.3】外部クライアントアプリケーション(ECA)を用いたHeadless Identity認証設定
今回の連載記事で作成したReactサイトとSalesforceコンポーネントをGitHubで公開しています。 ぜひ Clone して、あなたの組織で動かしてみてください。

事実(仕様に基づく通信制約)
- Salesforceの
/services/oauth2/authorizeエンドポイントは、処理成功時に302 Redirectを返却します。 - ブラウザの
fetchAPIは、セキュリティ仕様によりクロスオリジンでの不透明な302リダイレクトのLocationヘッダーを直接読み取ることができません。
実装コード(ローカルプロキシとモック関数)
ローカル開発環境におけるVite Proxyのハックと、APIレートリミットを回避するためのモック関数の実装です。
// vite.config.ts
export default defineConfig({
server: {
proxy: {
'/TatehamaPetClinic': {
target: 'https://orgfarm-...',
changeOrigin: true,
secure: false,
configure: (proxy) => {
proxy.on('proxyRes', (proxyRes, req, res) => {
// /authorize が返す 302 リダイレクトを強引に 200 に変換し、フロントエンドでLocationを抽出可能にする
if (req.url?.includes('/services/oauth2/authorize') && proxyRes.statusCode === 302) {
const location = proxyRes.headers['location'];
proxyRes.statusCode = 200;
proxyRes.headers['x-intercepted-location'] = location;
}
});
}
}
}
}
});
// API呼び出しモジュール (salesforceAuth.ts) の抜粋
export async function sendOtpRequest(email: string) {
// 開発環境かつモックフラグが有効な場合は、Salesforce APIを叩かずダミーレスポンスを返却する
if (import.meta.env.DEV && import.meta.env.VITE_USE_MOCK_OTP === 'true') {
return new Promise(resolve => setTimeout(() => resolve({ success: true, mockIdentifier: 'mock-id-1234' }), 500));
}
// 実API通信処理の実装...
}
推測・見解(本番環境でのリダイレクト戦略)
SPA単体でのOAuthの限界
SPA単体で完全なHeadless体験(リロードなし)を本番環境で実現するには、BFF(Node.jsやEdge Function等)の導入を強く推奨します。
302 Redirect を、Reactなどのブラウザの fetch APIで受け止めようとすると、CORS制約とOpaque(不透明な)リダイレクトの仕様により中身が読み取れず、Vite Proxyのハックは静的ホスティングでは機能しません。BFFの追加が困難な場合は、fetch による非同期通信を諦め、window.location.href = authorizeUrl でブラウザごとSalesforceへ遷移させる「フルリダイレクト方式」を許容するトレードオフの判断が必要です。
開発時の知見(ハマりどころ)
- OTP要求の1時間レートリミット
/services/auth/headless/init/registrationに対して、同一IPまたはメールアドレスから約5〜10分間に5回連続でリクエストを送ると、1時間のロックアウト(429 Too Many Requests)が発生します。開発中は上記のようなモック関数を組み込み、API呼び出しをバイパスする仕組みを用意することが開発効率維持の鍵となります。 - reCAPTCHAとViteキャッシュトラップ
Headless Identityの要件でreCAPTCHAのシークレットを更新した際、フロントエンドのビルドキャッシュ(.env等の古いサイトキー)が残り、400 Bad Requestが発生し続けるケースがあります。環境変数変更時は完全な再ビルドを実施してください。
まとめ
SPA(React)からのHeadless API連携は、ブラウザ特有のCORSや不透明なリダイレクト(Opaque Redirect)の制約をどう突破するかが実装の鍵となります。
ローカル開発環境でのVite Proxyを利用したリダイレクトハックは有効ですが、本番環境ではBFF(Backend For Frontend)の導入やフルリダイレクトの許容といったインフラ構成の決断が必要です。また、Salesforceの厳格なOTPレートリミット(1時間ブロック)による開発の停滞を防ぐため、環境変数を用いたAPI通信のモック化を初期段階で組み込むことを強く推奨します。
続いて第五弾の記事もご覧ください。
参考URL
Configure a Connected App for the Authorization Code and Credentials Flow
Headless Identity APIs: Headless Registration Flow for Private Clients




読者の声