SandilyaSridhar
ServiceNow Employee
ServiceNow Employee

The Virtual agent can be embedded in the third-party website. You can define an inline frame with HTML tag <iframe>.  The <iframe> tag defines a rectangular region within the document in which the browser can display a separate document, including scrollbars and borders.

But to embed the Service-Now Virtual Agent to any external web page, Below are the prerequisites to be followed. 

1.Activate Virtual Agent:

You can activate the Glide Virtual Agent plugin (com.glide.cs.chatbot) if you have the admin role. Please refer to the Product Document.

2.Make sure the website that you are hosting has a valid domain name and is secure.

3.The embedding of virtual agent might not work if you are using online code editors so please make sure the code is embedded in a hosted website. 

4.Using a dev instance might not work in the long term so only use a paid customer instance.

 

Procedure:

  • Use the com.glide.cs.embed.xframe_options property to enable the configuration of the X-Frame header for only the https://<your-instance>.service-now.com/sn_va_web_client_app_embed.do page.
  • Set ‘com.glide.cs.embed.xframe_options’ to: sameorigin .

Note: Avoid using allow-from * as the X-Frame-Options header value because it would enable all domains and leave the application potentially vulnerable to clickjacking.

find_real_file.png

  • Use the com.glide.cs.embed.csp_frame_ancestors property to enable the configuration of the frame-ancestors policy for only the https://<your-instance>.service-now.com/sn_va_web_client_app_embed.do page.
  • Set ‘com.glide.cs.embed.csp_frame_ancestors’ to: 'self' http://*.your-domain.com 

Note: Avoid using only '*' as the Content Security Policy because it would enable all domains and leave the application potentially vulnerable to clickjacking.

 

find_real_file.png

  • Based on the UI technology that is been used in developing the 3rd party website, Need to follow a similar architectural pattern in embedding the Virtual agent WebClient in the website. 
  • After associating your ServiceNow instance to a custom URL, create the iframe element and specify the custom URL in the inline element (iframe) used to embed the Virtual Agent client in an external web page: "https://<your-domain>.com/sn_va_web_client_app_embed.do"
Note: Your instance may have multiple custom URLs, but only one instance URL. You must use your custom instance URL only.
 

Challenges in Cross-domain communication:

  • Think of a website ParentPage.com consisting of an iframe through which you can access another website IframePage.com.
  • When you need to operate an embedded iframe and if you try to call a JavaScript function and if both applications are on a different domain, you often encounter this error:
  1. "Unsafe JavaScript attempt to access frame with URL 'http://parent.com' from the frame with URL 'http:// Iframe.com'. Domains, protocols, and ports must match."
  2. “Permission denied accessing property”
  3. “Child document does not have the right to access parent document.”
  • For any action for IframePage.com from ParentPage.com, the postMessage method allow cross-origin communication which is supported by all modern browsers allowing communication between different domains.

Syntax:

 window.postMessage(data, targetOrigin)
  • The postMessage interface allows two different windows to talk to each other doesn't matter the origin from which they are from. So, it’s a way around the “Same Origin” policy. It allows a window fromParentPage.com to talk to IframePage.com and exchange information.

data:

  • The data to send. Can be any object, the data is cloned using the “structured serialization algorithm”. IE supports only strings, so we should JSON.stringify complex objects to support that browser.


targetOrigin:

  • Specifies the origin for the target window, so that only a window from the given origin will get the message.
  • Specifying the target origin ensures that the window only receives the data if it’s still at the right site. Important when the data is sensitive.
  • For instance, here win will only receive the message if it has a document from the origin http://thirdPartyDoamin.com:
<iframe src="http://thirdPartyDoamin.com" name="thirdPartyDoamin">

<script>
  let win = window.frames.example;

  win.postMessage("message", "http://thirdPartyDoamin.com");
</script>

 

 For demonstration, we will take one parent.html and i-frame.html file and try to access the iframe.html from parent.html.

 

  1. Here is our parent.html page where we can Receive, Validate and Process Messages from the Iframe.html page.
<html>
<head>
    <script>
        window.addEventListener('message', receiveMessage, false);
function receiveMessage(event) {
if (event.origin != 'http://parentPage.info') {
    // something from an unknown domain, let's ignore it
    return;
  }
    // Write your logic to check the event conditions to trigger the SSO
            alert("got message: " + event.data);

// redirect to SSO login if the web client logs in but is logged in as a guest user(unauthenticated)
      if(event.data==="message"){
        window.location.href = "https://<your-instance>.service-now.com/sn_va_web_client_login.do?sysparm_redirect_uri=<your-page>";

        }
    </script>
</head>
<title> Parent Page </title>
<body>
<iframe 
   id="sn_va_web_client"
    title="ServiceNow Virtual Agent Client"
    width="600"
    height="900"
    src="https://<your-domain>.com/sn_va_web_client_app_embed.do">
    "https://<your-domain>.com/"https://<your-domain>.com/
</iframe>
</body>
</html>
  • In order to receive messages, the message event of the window should be listened.
  • When a message is received there are a couple of steps that should be followed to assure security as much as possible.
  • Validate the sender (From where we are listening the event) and Check event.origin to see if it is a trusted sender.
  • Validate the message(The message that we received from child Ex:'message') and We want to make sure it's a valid json object and it does not contain anything malicious
  • Process the message.Do whatever you want with the received message for example: append the message into your #console div
  • The sender should always be validated to make sure the message is received from a trusted sender.
  • After that, the message itself should be validated to make sure nothing malicious is received.
  • After these two validations, the message can be processed.

2.Now below is our Iframe.html page where we can start sending messages to the parent.html page

<html>
<head>
    <script>
        function send() {
            window.parent.postMessage('message', 'http://receiver.com');
        }
    </script>
</head>
<title> IFrame Test </title>
<body>
    <h1> Welcome </h1>
    <p> Hello There </body>
<button onclick="send()">Send</button>
</body>
</html>
  • This will call the window.parent.postMessage() function after the instantiation of click event by the user and send the message 'message' to the parent window.
  • Run the parent.html and click on the send button the parent page will receive the message ‘message’ in alert box.
  • In order send and receive JSON objects instead of a simple string, JSON.stringify() and JSON.parse() methods can be used.For example:
function sendMessage(message) {
    if (!message || !message.length) return;
    Window.postMessage(JSON.stringify({
        message: message,
        time: new Date()
    }), 'http://receiver.com');
}

 

In the above example, The event that I am sending to the receiver is 'message', so on the parent window, I am checking for the event condition 

 if(event.data === 'message')

But as described in the product document, you can send custom data objects to the 'window.addEventListener' from the 'window.postMessage(dataObject, target origin)' that can satisfy the below mentioned.

if(event.data.type==="SESSION_CREATED" && event.data.authenticated === false)
if(event.data.type==="SESSION_LOGGED_OUT")

I have implemented a simple approach to just check if the  if(event.data === 'message')
and if so, I am triggering the SSO as showcased above in parent.html page .​

Note: Before you run the script, use the com.glide.cs.web_client_login_redirect_urls system property to specify the URLs that can be passed in the script.

The redirection works only when you specify one or more allowed URLs in the property value. Specify the full redirect URLs or the host part of the URL, such as https://example.com.

 

I am sharing the video of my project that I have attempted to integrate the virtual agent into my third-party application along with the SSO integration.

 Do share your thoughts on the same.

Happy Learning!!!

Comments
akarshagnihotri
Tera Contributor

event.data.type==="SESSION_CREATED" && event.data.authenticated === false

 

In my implementation, Why everytime this condition is getting true.  Every time it's getting true thats why every time it's redirecting to login page and then again open external website and still treating me as guest user.

 

 

mohammadabd
Tera Contributor

Great article.

 

This workaround worked for me:

https://<instance>.service-now.com/sn_va_web_client_login.do?sysparm_redirect_uri=<mypage>
tye456
Tera Contributor

Embedding the ServiceNow Virtual Agent into a third-party site demands careful alignment of domain security, header configuration, and iframe setup. Just like a well-blended taper fade, it’s all about smooth transitions—ensuring seamless communication between domains using post message without exposing vulnerabilities. Your website architecture must be clean, secure, and structured to make the integration as sharp and precise as a good fade.

Version history
Last update:
‎08-01-2021 08:06 AM
Updated by: