9

The Salesforce Canvas Developer Guide states: "Canvas enables you to easily integrate a third-party application in Salesforce". And then it needs more than 100 pages to explain how to do this.

OK, maybe less pages, but still, the process is not particularly easy or intuitive. What's worse, the instructions in the Guide do not work. Problems with Jetty, or something like that. So I cannot even get the "simple" scenario to work.

Also, this scenario is way too complicated for me. All I want is a window/pane in Salesforce that shows a third-party website. At some point I would like to pass some parameters, so that the contents of that window are dynamic.

To be very specific: I want the third-party website to be visible inside a Salesforce window, so some part of the window must show Salesforce data and some part of the window must show the other website.

Where can I find the instructions on how to do such a simple thing?

4
  • Upvote from Me, Wish there was a trailhead which would allow us to demo a connected app on our playground orgs. I would try tweeting @trailhead , for this. Oct 29, 2018 at 9:58
  • For simple use cases an iframe may do?
    – Kasper
    Oct 29, 2018 at 10:30
  • @Kasper Canvas is the successor of iframe. iframe is no longer permitted (not secure). Oct 29, 2018 at 11:45
  • I still use iframes in places where I don't require authentication. If you require the extra level of security I guess you have no choice but to use the canvas app. I tried reading once and agree with you that it's rather tough material for simple solutions.
    – Kasper
    Oct 29, 2018 at 12:52

2 Answers 2

5
+100

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.

6

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.

5
  • I edited my question, to make it more specific: I want the third-party website to be visible in a part of the Salesforce page. So I think that a Visualforce Tab will be the best solution. I just hope that it will work, because I read that web browsers will sometimes prevent web sites to be embedded in a web page. I will just have to experiment with it. I will not yet award you the bounty, as my question was about Canvas. But if no other answers are given, you will get the bounty. Oct 30, 2018 at 8:06
  • What page do you want to see the 3rd party site on? Is it a record detail page, by chance? If so, you can embed the visualforce page in the standard page layout. (See help.salesforce.com/…) You'll need to use the object's standard controller for your visualforce page, and write an extention to handle the redirect, but the idea is pretty much the same. Let me know if this is what you're looking for and I'll update my example. Oct 30, 2018 at 14:09
  • 1
    I've updated my answer to address the, "browsers preventing embedded sites," concern. Oct 30, 2018 at 14:31
  • It's not determined yet which site(s) would need to be displayed, but navigation is definitely a must. It will probably be a challenge to influence the X-Frame-Options settings of the included site(s)... Oct 31, 2018 at 7:36
  • Do you have access to the 3rd party site now? You can check the X-Frame-Options in the HTTP header. In Chrome, open the developer tools (ctrl-shift-I) and click on "Network." Go to the site, and once all the madness stops scrolling past in the Network window, click on the top row. A separate frame will open to the right. Look under the Headers tab in that frame, and find x-frame-options. If it's set to SAMEORIGIN (as StackExchange is), then you won't be able to use the site in Canvas directly. You'll have to load it server-side and render it "manually". Nov 5, 2018 at 2:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .