2

I have a Visualforce page that uses apex:canvasApp. The canvas app itself uses a signedrequest for authentication via SAML SSO. Everything loads fine when logged in as a real user, however when an admin impersonates the same user, the whole lightning record page that the Visualforce page is embedded in gets redirected to an "insufficient privileges" error page.

I have read previous discussions around this that mention Salesforce stopped supporting the Login As feature for impersonating users across trust domains around 2015, which is understandable. What I want to do is to make the failure only happen within the iframe in which the Canvas app lives, rather than the heavy-handed redirection of the whole page layout. This makes the Login As feature completely unusable for admins when the canvas app is embedded.

Is there a way to "catch" the exception/redirect or avoid it in this situation such that, when impersonating, just the iframe containing the canvas app fails, but the rest of the page layout successfully loads? This must be a common issue among canvas app developers but I find it strange that there is no documented info or workarounds for it.

I have tried wrapping the apex:canvasApp within another apex:iframe with sandbox attributes, but that doesn't seem to be enough to stop the redirect to the error page.

0

Answering my own question here in case others come here looking for a solution.

This answer to a previous question gave me the hint on using the presence of the RSID cookie to detect impersonation and render a message instead of showing the canvas app.

Here's how it is implemented:

Visualforce page:

<apex:page standardController="Opportunity" extensions="myControllerExt" showHeader="false" sidebar="false" standardStylesheets="false">
  <apex:form >
    <apex:actionFunction name="setImpersonate" action="{!reload}" rerender="myCanvas">
      <apex:param name="param1" assignTo="{!impersonate}" value="" />
    </apex:actionFunction>
  </apex:form>
  <script type="text/javascript">
    setImpersonate(document.cookie.match(/(;|^)\s*RSID=/i) ? 1 : 2);
  </script>
  <apex:pageBlock id="myCanvas">
      <apex:pageBlock rendered="{!impersonate == 0}">
        <p>Loading...</p>
      </apex:pageBlock>
      <apex:pageBlock rendered="{!impersonate == 1}">
        <p><b>MyCanvas not available due to security restrictions when impersonating.</b></p>
      </apex:pageBlock>
      <apex:pageBlock rendered="{!impersonate == 2}">
        <apex:canvasApp applicationName="MyCanvas" namespacePrefix="example" height="60px"/>
      </apex:pageBlock>
  </apex:pageBlock>
</apex:page>

Controller:

public class myControllerExt {
    private Integer impersonate = 0;

    public myControllerExt(ApexPages.StandardController stdController) {
        impersonate = 0;
    }

    public Integer getImpersonate() {
        return impersonate;
    }
    public void setImpersonate(Integer n) {
        impersonate = n;
    }
    public PageReference reload() {
        return null;
    }
}

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.