【必読】なぜ今、Aura ではなく LWR を選ぶべきなのか?

外部サイトに配置したMIAW(拡張チャット)のJWTベースユーザー検証と安全な顧客紐付けアーキテクチャ

A sophisticated, professional-style digital art piece depicting secure data synchronization between a user interface and a cloud system. The central focus is a stylized, glowing chat interface icon surrounded by abstract cryptographic symbols, such as translucent geometric keys and shimmering light matrices representing JSON Web Tokens. Thin, luminous data lines connect a sleek, minimalist web dashboard in the foreground to a powerful, glowing digital core in the background. The scene is rendered in a deep indigo and electric blue color scheme, with high-quality soft-focus lighting and a clean, high-tech aesthetic. The overall mood conveys trust, seamless connectivity, and advanced architectural security. 基礎・アーキテクチャ

この記事はバージョン Summer ’26 において執筆しています。
現在の動作と異なる場合がありますので、ご認識おきください。

外部WebサイトにMIAW(拡張チャット)を配置する際、ログインユーザーの認証状態を連携して過去の会話履歴を安全に引き継ぐためには、User Verification APIを使用したJWT(JSON Web Token)方式の検証が必要です。

本記事では、PHPベースのバックエンドからSalesforceへセッションを連携する構築ステップに加え、フロントエンドの改ざんリスクを排除し、オムニチャネルフロー内部で安全に取引先責任者(Contact)を紐付けるアーキテクチャの仕様を解説します。

LWRって何?どんなメリットがあるの?
そんな疑問を解決するにはまずは以下の記事をご覧ください。
Salesforce LWRとは? Experience Cloudの次世代ランタイムを徹底解説

ステップ1: 暗号鍵ペアの生成

【ドキュメントに基づく仕様】
Salesforceのユーザー検証APIは、RS256(RSA Signature with SHA-256)アルゴリズムによる署名を要求します。

【構成したサンプル手順】
OpenSSLを使用して、署名用の秘密鍵と検証用の公開鍵(自己署名証明書)を生成します。ターミナルで以下のコマンドを実行します。

openssl req -new -x509 -nodes -sha256 -days 365 -keyout private.key -out certificate.crt

生成された private.key はバックエンドサーバーに配置し、certificate.crt は次のステップで使用します。

ステップ2: 公開鍵のJWK(JSON Web Key)変換

【ドキュメントに基づく仕様】
Salesforceに公開鍵を登録するためには、証明書ファイル(.crt)をJWK(.json)形式に変換する必要があります。

【構成したサンプルコード】
PHPスクリプトを使用して .crt から JWK 形式の .json ファイルを生成します。

<?php
// generate_jwk.php
$certContent = file_get_contents('certificate.crt');
$pubkey = openssl_pkey_get_public($certContent);
$details = openssl_pkey_get_details($pubkey);

function base64url_encode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

$jwk = [
    "kty" => "RSA",
    "use" => "sig",
    "alg" => "RS256",
    "kid" => "custom-miaw-key-001", // 任意のキーID
    "n"   => base64url_encode($details['rsa']['n']),
    "e"   => base64url_encode($details['rsa']['e'])
];

file_put_contents('public_key.json', json_encode($jwk, JSON_PRETTY_PRINT));
?>

ステップ3: Salesforceへのキーセット登録とチャネルへの紐付け

キュメントに基づく仕様】
Salesforce上でJWKを登録し、対象のメッセージングチャネルに関連付けます。

  1. JSON Web キーの作成:
    [設定] > [拡張チャットユーザー検証] を開き、[JSON Web キー] セクションで新規作成します。ステップ2で生成した public_key.json をアップロードします。
  2. JSON Web キーセットの作成:
    同画面の [JSON Web キーセット] セクションで新規作成します。[JSON Web キー発行者 (Issuer)] に任意の識別子(例: custom-miaw-issuer)を入力し、先ほどアップロードしたキーを追加します。
  3. チャネルへの紐付け:
    [設定] > [メッセージング設定] から対象チャネルの「詳細画面」を開きます。関連リスト [ユーザー検証設定] で新規作成し、作成したキーセットを選択します。指定する「設定名」は、複数チャネル間で履歴を共有する際のセッション識別子となります。
  • 拡張チャットユーザー検証
  • メッセージング設定

ステップ4: バックエンド(JWT生成API)の実装

【ドキュメントに基づく仕様】
JWTのヘッダーには alg (RS256) と kid (登録したキーID) が、ペイロードには sub (ユーザーの一意の識別子)、iss (キーセットで指定した発行者)、exp (有効期限)、iat (発行日時) が含まれている必要があります。

【構成したサンプルコード】
バックエンド(PHP)でJWTを動的に生成するAPIを実装します。

<?php
header('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');

$privateKey = file_get_contents('private.key');
$now = time();

$header = [
    'alg' => 'RS256',
    'typ' => 'JWT',
    'kid' => 'custom-miaw-key-001'
];

$payload = [
    'sub' => 'user123@example.com', // ユーザーの一意の識別子(例: メールアドレスや外部ID)
    'iss' => 'custom-miaw-issuer', 
    'iat' => $now,
    'exp' => $now + 3600
];

$base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(json_encode($header)));
$base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(json_encode($payload)));

$signatureInput = $base64UrlHeader . "." . $base64UrlPayload;
openssl_sign($signatureInput, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));

$jwt = $signatureInput . "." . $base64UrlSignature;
echo json_encode(['token' => $jwt]);
?>

ステップ5: フロントエンドの実装(セキュアな設計)

【ドキュメントに基づく仕様とセキュリティ制約】
フロントエンドの prechatAPI(Custom Context)を使用して識別子(メールアドレス等)をSalesforceへ送信することも技術的には可能ですが、クライアントサイドのJavaScriptは開発者ツール等で容易に改ざんできます。

【アーキテクチャ設計のベストプラクティス】
本人確認のための識別子は prechatAPI に含めず、暗号学的に担保されたJWTのペイロード(sub)のみを信頼元とするべきです。フロントエンドは setIdentityToken によるJWTの引き渡しのみを担当させます。

<script>
    window.addEventListener("onEmbeddedMessagingReady", () => {
        fetch('[https://your-backend.com/generate_jwt.php](https://your-backend.com/generate_jwt.php)')
            .then(response => response.json())
            .then(data => {
                if (data.token) {
                    embeddedservice_bootstrap.userVerificationAPI.setIdentityToken({
                        "identityTokenType": "JWT",
                        "identityToken": data.token
                    });
                }
            });
    });
</script>

※注意: Salesforceの要件として、[設定] > [CORS] に、Webサイトのドメインが登録されている必要があります。

ステップ6: オムニチャネルフローでの安全な顧客紐付け

【ドキュメントに基づく仕様】
JWTの sub クレームで渡された値は、Salesforce上で自動生成される MessagingEndUser(メッセージングユーザー)レコードの MessagingPlatformKey 項目に直接保存されます。オムニチャネルフローでは、チャット開始時に渡される recordId(MessagingSessionのID)からこのレコードを辿ることが可能です。

【構成したフロー設計】
フロントエンドの改ざんリスクを排除し、Contact(取引先責任者)を自動紐付けするためのオムニチャネルフロー(インバウンド)の要素構成は以下の通りです。

この設計により、クライアント側の入力に依存しない、堅牢なセッション管理とレコード連携が実現します。

ロジック

  1. レコードの取得(Session): MessagingSession オブジェクトから、Id が入力変数 recordId と一致するレコードを取得し、MessagingEndUserId を確保します。
  2. レコードの取得(End User): MessagingEndUser オブジェクトから、手順1の MessagingEndUserId と一致するレコードを取得します。この際に MessagingPlatformKey(JWTで渡した識別子を含む文字列)を確保します。
  3. レコードの取得(Contact): Contact オブジェクトから、Email(または外部ID)が以下に示すフロー数式の抽出値と一致するレコードを検索し、Idを確保します。
  4. レコードの更新(紐付け): MessagingSessionContactId を手順3のContactのIdで更新します。

フロー数式

MessagingEndUser.MessagingPlatformKey には、JWTで渡した識別子を含む文字列が格納されています(v2/iamessage/AUTH/SFDC/uid:xxx の形式)。フロー数式を使用して、uid: 以降の文字列を抽出します。

MID(
    {!get_MessagingEndUser.MessagingPlatformKey}, 
    FIND("uid:", {!get_MessagingEndUser.MessagingPlatformKey}) + 4, 
    LEN({!get_MessagingEndUser.MessagingPlatformKey}) - FIND("uid:", {!get_MessagingEndUser.MessagingPlatformKey}) - 3
)
DXforce Point

💡顧客体験の向上のために

User Verification APIを使用したJWT(JSON Web Token)方式の検証を実装すると、MIAWは「非同期・永続的メッセージング」として動作し、過去の会話履歴が維持されます。この環境下において、ユーザーとの初回の会話や2回目以降のセッションの顧客体験を向上させることができます。
詳しくは以下の記事の「【実装】会話体験の最適化(ダミーチャットの回避)」をご覧ください。Experience Cloudサイトでも外部サイトでも同じように適用できます。

MIAWユーザー検証と自動紐付けの処理フロー

フロントエンド、自社バックエンド、メッセージングゲートウェイ、オムニチャネルフロー、およびSalesforce DBの間で発生する処理のシーケンス図です。

フローにおける重要なポイント

認証処理のバックエンド集約(Phase 1)

本人確認のキーとなる識別子(sub)を含んだ JWT の生成と暗号署名は、すべて自社バックエンド(サーバーサイド)で完結させています。フロントエンドの JavaScript は生成されたトークンを Salesforce へ受け渡す役割のみを担うため、クライアント側における識別子の漏洩リスクを抑えています。

改ざん不可能な識別子を用いた安全な紐付け(Phase 3)

フロー内で取引先責任者(Contact)を検索する際、フロントエンドから送信可能な事前チャット(Custom Context)の値を信用して使用することはありません。Salesforce プラットフォームが JWT の署名検証に成功した証として MessagingEndUser レコードに格納する MessagingPlatformKey を直接抽出して検索キーとしています。これにより、ブラウザコンソール等からのパラメータ改ざんによる「他者へのなりすまし」を完全に防御します。

フロー実行とセッション復元の分岐仕様(Phase 3 および 参考)

オムニチャネルフローを利用した Contact の自動紐付け(Phase 3)が実行されるのは、新規のチャットセッション(MessagingSession)が生成された初回ルーティング時のみです。セッション維持期間中にユーザーがページをリロードしたり再アクセスしたりした場合(参考ルート)、システムは既存の会話の続きであると判定し、フローの実行をスキップしてウィジェット上に過去の会話履歴を自動復元します。

まとめ

本記事では、外部サイトに配置したMIAW(拡張チャット)におけるJWT方式のユーザー検証実装について、セキュアな設計を主軸に解説しました。

MIAWにおけるJWTユーザー検証の核心は、セッション管理とビジネスロジックの責任分担にあります。

  • セッションの担保: サーバーサイドで生成・署名されたJWTの sub クレームを信頼の起点とし、Salesforce側で MessagingPlatformKey として自動的に管理・永続化します。
  • 安全な顧客連携: 取引先責任者(Contact)との自動紐付けは、フロントエンドからのパラメータ送信(事前チャット)に依存せず、フロー内部で暗号学的に保証された MessagingPlatformKey を起点に行います。

今回の実装により、フロントエンドの改ざんリスクを排除しつつ、シームレスなチャット体験と堅牢なセキュリティを両立するアーキテクチャが構築可能です。特に、オムニチャネルフロー内で MessagingSession を起点にデータを参照する設計は、運用保守性の観点からも推奨されます。

今後、Messaging for In-App and Web の実装を進める際は、単なる「チャットの表示」に留まらず、今回構築した「信頼された識別子(MessagingPlatformKey)」を基点としたデータ連携を意識してみてください。これにより、将来的なエージェントの負荷軽減や、他システムとの連携拡張時にも破綻のないセキュアな設計を維持できるはずです。

本記事が、セキュアでスケーラブルな顧客対応基盤構築の一助となれば幸いです。

参考URL

User Verification in Enhanced Web Chat

トークンベースのユーザー検証の設定

MessagingEndUser | Object Reference for the Salesforce Platform

DXforceの管理人

福島 瑛二

2013年にJavaエンジニアとしてのキャリアをスタート。2019年にSalesforceと出会い、Salesforceエンジニアの道へ。

デザインや UI/UX の観点からもシステムを捉え、ユーザーにとって心地よい体験を実装することにやりがいを感じています。

CRM(顧客データ)や Data Cloud と連携した高度なサイトを目に見える形で表現できる Experience Cloud に大きな可能性を見出しており、バックエンドのデータ構造とフロントエンドの表現力を極めることがこれからの Salesforce エンジニアに求められるスキルだと確信しています。

Trailblazer: efukushima

福島 瑛二をフォローする

読者の声

タイトルとURLをコピーしました
DXforce 案内エージェント