How to get Canvas working, need pointer to simple instruction

For a simple use-case like that, I would just use a Web Tab. Canvas is more than you need, for sure.

When it comes time to pass parameters out to the 3rd-party site, you'll need to change it up a bit. I'd use a Visualforce Tab at that point. Set it to load a Visualforce page that's only job is to dynamically create the parameters for the 3rd-party URL, and then redirect. Something like this:

Page:

<apex:page controller="MyController" action="{!redirect}"/>

Controller:

public with sharing class MyController{
    public PageReference redirect(){
        PageReference pageRef = new PageReference('https://third-party-site.com');

        String currentUsersPhone = [SELECT phone FROM User WHERE Id = :UserInfo.getUserId() LIMIT 1].phone;
        pageRef.getParameters().put('phone', currentUsersPhone);
        pageRef.setRedirect(true);

        return pageRef;            
    }
}

Make sure all users have access to the Visualforce page, and you should be good to go.

UPDATE: Based on your comments (below) about 3rd party site content not being displayed within another web page, that's definitely a concern. Websites can set the X-Frame-Options HTTP header to tell browsers not to render their content inside another page.

All modern browsers respect the X-Frame-Options setting, so if it's an issue for the 3rd party site you're working with, it won't matter whether you're using web tabs, embedded Visualforce, or Canvas -- you'll have the same problem with all of them.

The only way I can think of to get around this would be to load the page server-side (in Apex) and then display its content in a Visualforce page. You won't be able to navigate within the 3rd party site -- just display a single page -- but it is possible.

Note that you'll have to create a remote site record for the 3rd party site to access it from Apex.

Page:

<apex:page controller="MyController">
    {!pageContent}

</apex:page>

Controller:

public with sharing class MyController{
    String pageContent {get; set;}

    public void myController(){
        HttpRequest req = new HttpRequest();
        req.setEndpoint('http://third-party-site.com');
        req.setMethod('GET');

        Http http = new Http();
        HTTPResponse res = http.send(req);
        pageContent = res.getBody();
    }

}

That said, I don't think I would try to work-around an X-Frame Options setting forbidding display within another page. The site owner's request should be respected.


These are the steps I used to create a Canvas App as part of the Can I embed a Salesforce app, via Canvas, in another org? question. This was pre-Lightning UI, but it hopefully gives you more direct steps to follow.

I'll modify them slightly to make more sense for your scenario.

  1. Create a Canvas App
    1. Username > App Setup > Develop > Create > Apps [New: Connected Apps]
    2. Under API (Enable OAuth Settings)
    3. Enabled OAuth Settings
    4. Callback URL: https version of the target site URL. E.g. https://www.fishofprey.com
    5. Selected OAuth Scopes: Full access (full). You might wish to use a more stricted OAuth scope here if there is no need for the external site to call back into Salesforce APIs.
    6. Under the Canvas App Settings
    7. Check Force.com Canvas
    8. Enter the Site URL from the other Org using https
    9. Set the Access Method to Signed Request (POST)
    10. Locations: Visualforce Page
  2. Create a Visualforce page to host the Canvas App.
    Visualforce page content: (The developerName is the API Name of your Canvas App)

    <apex:page>
        <apex:CanvasApp developerName="SitesApp"/>
    </apex:page>
    
  3. Manage the Connected App

    1. Set OAuth policies to Permitted Users: Admin approved users are pre-authorized
    2. Under Managed Profiles, add System Administrators (or whichever profiles suit)
  4. Preview the Visualforce Page. You should be able to see the Sites page from the first Org receiving the Signed Request Post data.

Now the big catch here is that Salesforce will POST a signed request to the target iframed site. If the target URL won't accept a POST you will likely get an error back. Instead, you could change it from Access Method of "Signed Request (POST)" to "OAuth Webflow (GET)".

enter image description here

Of course, we haven't actually done anything in the target nested site to verify the request is valid. To do so you will either need to accept and process the signed request or complete the OAuth flow.

The Visualforce page will give you some flexibility in how the canvas app is used. It would also be worth exploring adding "Lightning Component" as a supported Canvas App location.


Passing additional parameters to the external site via the signed request is more complicated. I've done so in the past by implementing Canvas.CanvasLifecycleHandler and then configuring that class as the "Lifecycle Class" under the Canvas App Settings.

Tags:

Canvas