
みなさんこんにちは。エンジニアの佐藤です。今回は前回に引き続き、Experience Cloudの「チャット窓」こと、組み込みメッセージングコンポーネントのお話です。
AIチャットボットにユーザーが期待する機能の一つに、パーソナライズがあります。AIチャットボットが自分のことを覚えていてくれて、気を利かせた応答をしてくれたら、きっと便利なことでしょう。Experience Cloudでページの内容にログインユーザーの情報を織り込むことは容易にできます。ぜひAIチャットボットにも同様にユーザー情報を注入したいものです。
とは言え、ここで問題になるのは、ユーザーをどうやって「安全に」特定するかです。会話の中で「私は佐藤です。」と言われたからといって、AIチャットボットは「佐藤さんですね。」と返すわけにはいきません。別人がなりすましているかもしれないからです。
Experience Cloudサイトへのログインユーザーを、安全に(なりすましができない形で)Agentforceエージェントに知らせる手段はないものでしょうか。Salesforceメッセージングにはこのための機能が用意されており、「ユーザー検証」と呼ばれています。以下にこの設定方法について解説したいと思います。
「簡単、安全、確実」な方法が、実はある
そうなのです。端的に言えば、以下のこれだけです。
- 拡張チャットメッセージングで「メッセージングのユーザー検証」を有効にする。
- Experience Cloudサイト(ユーザー認証を要するもの)に組み込みメッセージングコンポーネントを配置する。
- 組み込みメッセージングコンポーネントの「ログイン情報ベースのユーザー検証の追加」を有効にする。
順番に見ていきましょう。まず、一昨年の弊社ブログ「Service Agent を Web ページから利用する」の手順に従って以下を準備します。
- 拡張チャットメッセージング
- 組み込みサービスリリース
- キュー
なお、オムニチャネルメッセージングフローについては、最近のアップデートで不要になり、拡張チャットメッセージングを直接Agentforceエージェントに接続できるようになりました。以下は拡張チャットメッセージングの該当部分です。

ここで一つ、重大な制約があります。本校執筆時点では、このユーザー検証機能は組み込みサービスリリースV1のみ対応しており、前回ブログでUI拡張をご説明したV2は対応していません。(ぜひ早期に対応してもらいたいものです。)
拡張チャットメッセージングの設定(下図参照、開き方注意)では、「ユーザー検証を追加」をチェックしましょう。


次にExperience Cloudサイトに組み込みメッセージングコンポーネントを配置したら、「ログイン情報ベースのユーザー検証の追加」をチェックします。

以上で設定は終了です。
Agentforceアクションはどうやってサイトのログインユーザーを知るのか
さて、この設定を行うと、Agentforceアクションに、Experience Cloudサイトにログインしたユーザーが通知されます。通知は以下の2方面から行われ、指しているユーザーは同一です。
- UserInfo.getUserId()
- MessagingSession.MessagingEndUser.MessagingPlatformKey
1. UserInfo.getUserId()
先ほどの設定(拡張チャットメッセージング「ユーザー検証を追加」と組み込みメッセージングコンポーネント「ログイン情報ベースのユーザー検証の追加」)を行うと、Agentforceアクションの実行ユーザーがExperience Cloudサイトのログインユーザーに変更されます。(通常はAgentforceの既定のユーザー)
このことは、AgentforceのアクションにApexアクションを設定して、その内部でUserInfo.getUserId()を実行すると観察できます。
つまり、Agentforceアクションの実行は全て、Experience Cloudのログインユーザーの範囲に制限されるのです。これは以下のようなパーソナライズを適用できる、強力な機能です。
- 実行ユーザーの情報の取得
- オブジェクトアクセスや項目アクセスの制限
- 実行可能なApexクラスなどの制限
そして、この実行ユーザーの設定をごまかすことは、できません。ユーザー情報は安全に連携されてくるのです。
(短くて恐縮ですが、本ブログの要点は以上です。ただし、ユーザー検証の仕組みについてより深く理解されたい方は、この先もお読みください。)
2. MessagingSession.MessagingEndUser.MessagingPlatformKey
こちらも探ってみましょう。
Apexアクションの入力項目に「Routable Id」変数を設定すると、SalesforceのId文字列が連携されてきます。

(実のところ入力項目名がmessagingSessionIdStringだと、変数設定しなくてもAtlas推論エンジンが推測して値が連携されてきますが、確実な動作のために変数設定します。)
このId文字列を足場にSOQLでクエリすると、以下のような情報が引き出せます。(抽出コードはこちら)
{ "messagingSessionIdString": "0Mwgxxxxxxxxxxxxxx", "messagingSession": { "messagingEndUserId": "0PAgxxxxxxxxxxxxxx", "messagingEndUser": { "messagingPlatformKey": "v2/iamessage/AUTH/SFDC/uid:005gxxxxxxxxxxxxxx", "name": "X Sato" } }, "userInfo": { "userId": "005gxxxxxxxxxxxxxx", "userName": "x.sato.xxxxxxxx@agentforce.com" } }
messagingPlatformKeyの末尾のID文字列と、userIdは常に一致しています。本質的には、UserInfo.getUserId()によって得られるものと同じです。
全てのパーソナライズはユーザーIDから行うべき
このユーザーID(userId値)を足場にAgentforceのアクションの動作を調整することで、Experience Cloudのログインユーザーに合わせたパーソナライズが可能になります。これはプレチャット(英語名: pre-chat)と異なり、たとえWebデバッグツールでスクリプトを改変しても変更できない確実な足場です。
実はこれだけではない「ユーザー検証」機能
拡張メッセージングのユーザー検証機能には、すでに紹介した「ログイン情報ベース」の方法の他に、「トークンベース」の方法があります。
トークンベースのユーザー検証機能は昨年の弊社ブログ「Service Agent に認証済みユーザの情報を提供する」に書かれているMessaging for In-App and Web (MIAW、現在はEnhanced Chatに改名)のユーザ認証の仕組みそのもので、本質的には以下のようなものです。(用語については前回ブログ「AgentforceとExperience Cloud組み込みメッセージングコンポーネントの関係」を参照してください。)
- Salesforce組織に公開鍵を設定する。これはJWKSと呼ばれる仕様で、IDプロバイダーが公開しているJWKSを活用する方法と、JWKを手作業で設定する方法がある。
- Web画面(昨年の弊社ブログではMIAW REST APIを使う任意のクライアント。または組み込みサービスリリースのスニペットを展開したWebページ)で(サイト独自の)ユーザー認証を行った後にJWTを取得し、拡張チャットメッセージングを初期化する時に設定する。
- Salesforceは設定済みJWKSでこのJWTを検証し、検証できた場合のみ拡張チャットメッセージングを有効にする。
IDプロバイダがJWKSを公開しているケースについて図にすると、以下のようになります。

Salesforce自身もIDプロバイダとして動作しますので、以下のようにSalesforce認証を行う外部Webサイトを作成して動作を確認してみましょう。

外部サイト側
- 外部サイトは、ログイン認証をSalesforce環境に設定した外部クライアントアプリケーションで行う。この外部クライアントアプリケーションでは、Web画面の認証フローとJWTベースのアクセストークン発行を有効にする。(詳細についてはこちらをご覧ください。)
- 外部サイトに組み込みサービスリリースのスニペットを貼り付ける。
- 取得したアクセストークン(JWT)を組み込みサービスリリースに設定する。
Salesforce側(JWKSのみ掲載)
- Setup: 機能設定 -> サービス -> 組み込みサービス -> 拡張チャットユーザー検証
- 画面一番下のJSON Webキーセットで、以下の画面の通りにSalesforceのJWKSを設定

- 拡張メッセージングチャネルのユーザー検証でこのJWKSを指定

サイト全体のソースコードはこちらに掲載しましたので、適宜ご参照ください。(なお、環境固有の文字列については匿名化しています。)
「ログイン情報ベースのユーザー検証」の場合と同様にAgentforceのApexアクションを観察すると、以下のような出力になりました。
{ "messagingSessionIdString": "0Mwgxxxxxxxxxxxxxx", "messagingSession": { "messagingEndUserId": "0PAgxxxxxxxxxxxxxx", "messagingEndUser": { "messagingPlatformKey": "v2/iamessage/AUTH/t219tecptl484/uid:uid:005gxxxxxxxxxxxxxx", "name": "Guest" }, }, "userInfo": { "userId": "005gxxxxxxxxxxxxxx", "userName": "t219tecptl479_01@....ext" } }
messagingPlatformKeyに注目してください。「t219tecptl484」は、先ほど登録したJWKSの名称です。また、「uid:005gxxxxxxxxxxxxxx」は、ログイン認証されたユーザーの、Salesforce組織におけるユーザーIDです。こちらは昨年の弊社ブログで確かめられた通り、ユーザー検証に使われたJWTのsubクレームが「uid:」プレフィクスの後に設定されます。
アクセストークンのクレームを見てみると、以下のようになっており、このことが確認できます。
{ ... "sub": "uid:005gxxxxxxxxxxxxxx", ... }
また、アクセストークンのヘッダ部のkidクレームを、JWKSで設定したURLでダウンロードされるJWKSデータと比較してみると、列挙されたJWKの一つにこのkidクレームに一致するものが含まれており、署名検証が可能であることがわかります。
アクセストークンのヘッダ部
{ ... "kid": "CORE_ATJWT.00Dg5000003Gi2J.1767952265729", ... }
JWKSの対応キー
[ ... (他のキー) { ... (キーのデータ) "kid": "CORE_ATJWT.00Dg5000003Gi2J.1767952265729" ... } ... ]
署名が効いていることを確認してみましょう。外部サイトでアクセストークンを組み込みサービスリリースに設定する際に、トークンの内容に"A"を付け足すなどして改変すると、スクリプトエラーとなり、チャット窓が開かなくなります。期待通りにJWTの検証が行われているようです。
await embeddedservice_bootstrap.userVerificationAPI.setIdentityToken({ identityTokenType: "JWT", identityToken: accessToken + "A" // <= トークンを改ざんするとチャット窓が開かなくなる。 });
なお、userInfoに報告されたユーザー(Name=t219tecptl479_01@....ext)は、Agentforceに設定されたエージェントユーザーです。このため「トークンベースのユーザー検証」を利用する場合には、実行コンテキストはパーソナライズされていないことに留意する必要があります。
振り返って、どうか
実案件では、ログイン情報ベースのユーザー検証の追加が選ばれることがほとんどでしょう。設定も簡単で、安全で、効果は確実です。トークンベースのユーザー検証も柔軟性が高い仕組みですので、既存サイトにAgentforceを出張させ、パーソナライズの効いたチャットを実装する際に便利に使えそうです。
ユーザー検証、拡張チャットV2での早期の対応を期待したいと思います。
最後までお読みいただきありがとうございました。
謝辞
外部サイトに組み込みサービスリリースのスニペットを展開する際には、以下のサイトを参考にしました。
なお、「2.2 Trusted Domains for Inline Frames の設定」を行うには、(Experience Cloudサイトではなく)Salesforce組織のサイト機能を有効にする必要がありますので、注意してください。