I'm trying to determine if this is an unsupported Canvas scenario or if there's something misconfigured in the org or the browser that would otherwise allow it to succeed.
For the purpose of simplicity of this question: This canvas app is showing the user a "document viewer" widget which will be rendered in a lightning component placed on a flexipage. This widget will ultimately be raising events that can be acted upon within Salesforce.
I have a canvas app endpoint configured at https://sfdc-canvas.example.com
and this endpoint authenticates the request and parses a few parameters out of the SignedRequest payload and uses the values to redirect the iframe to https://docviewer.example.com
.
Problem
When this canvas app is rendered, the browser console displays the message below, indicating that something prevented a message from being posted to the canvas frame because the frame's URL doesn't match what is configured on the Connected App's Canvas URL.
CanvasProxy.js:29 (this is the location of
window.postMessage(a, b)
)Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://sfdc-canvas.example.com') does not match the recipient window's origin ('https://docviewer.example.com').
It appears that when messages are posted to/from the canvas app to Salesforce via postMessage, the only supported origin is the one explicitly defined on the Connected Application.
- Is it forbidden to communicate with hosts, all on the same domain, through canvas eventing, other than the one explicitly set in the connected app?
- Can I use a canvas app embedded in a VF page, which is then embedded in a lightning component to work around this restriction? (rather than using the
force:canvasApp
tag directly in the LC)
I came across this related question, noting that this security restriction was put in place with the Winter '16 release, however this doesn't address the use case of the canvas app being rendered from a different origin than the value explicitly stated in the Connected App.
Diagram
A sequence diagram, if the above could be clarified with a picture.
3rd Party App Configuration
The remote "document viewer" canvas app has markup similar to this, to publish an event back to Salesforce to trigger the opening of the targeted document using the Canvas SDK library:
Sfdc.canvas(function() {
sr = JSON.parse('<%=signedRequestJson%>');
Sfdc.canvas.client.publish(sr.client,
{
name : "myNS.openDocument",
payload : {
documentId : 'someID',
documentType: 'T1'
}
});
});
Update:
I now suspect that the problem is originating within the SDK's publishing of the event from the 3rd party and the sr.client
value containing the original Canvas endpoint as the origin and not the URL of the "document viewer" host which it is actually being rendered from.
Sfdc.canvas.client.publish(sr.client
Update 2:
Looks like it is not the publishing of an event (Sfdc.canvas.client.publish(
) where the error is logged out to the console, it is when the Sfdc.canvas(function() {
is being called.
The org-side of this onready
-like behavior is where the postMessage
is being called within CanvasProxy.js
and rejected because of the origin mismatch.
Removing the Sfdc.canvas(callbackFn);
might be a temporary workaround but definitely not a solid solution.
Update 3:
The removal of the Sfdc.canvas()
function did nothing to better the situation. Looks like it is the call to Sfdc.canvas.client.refreshSignedRequest()
which we are executing on init from the script at docviewer.example.com
that triggers this error message.
I may end up using a new service hosted at sfdc-canvas.example.com
as a relay/proxy to refresh the signed request payload on my behalf from the other host.
I would love some advice if anyone has implemented a canvas app where the domain of the rendered app is different than the domain of the canvas URL.
This use case is similar to the shared usage of login.salesforce.com by all users of the platform and then the My Domain vanity URLs representing a custom instance for one specific client.
I do not want to completely abandon Canvas and use raw iframes and I also prefer to leverage the Canvas SDK where I can - maybe this cross frame messaging is not one of those places.