3

I'm working on a project that will have us create a managed package which can be used for integration between Salesforce and our client's platform (let's just call it Cloud Product). Our client will then make this available to their customers who have both Cloud Product and Salesforce.

The requirements include making it possible to put a Visualforce page in customers' Classic or Lightning page layouts. In the case of Classic layouts, the platform requires the VF page to use the object's Standard Controller. Obviously we cannot package VF pages for the Standard Controllers of unknown objects. We can create a VF component capable of working for an ID of any SObject type, but the customer would still have to create the necessary VF pages.

I tested out the Tooling API and found that I was able to use it to publish VF successfully even in a live production org. So I was thinking we'd have a Setup Visualforce page in which, when the customer's admins set up integrations between Cloud Product and objects in their org, we offer them the option of clicking a button to create the appropriate VF page. This button would call the Tooling API from JavaScript to create a very small VF page, e.g. something like this:

<apex:page standardController="Customer_Object__c">
    <cloudProductNamespace:cloudProductPanel id="{!Customer_Object__c.id}" />
</apex:page>

The user who does this would have to have admin-level privileges, but I think this is fine as non-admins shouldn't be seeing this Setup page anyway. It would probably fail in Professional Edition and we can include backup instructions for that scenario. And I believe doing it from JS would remove the need for a Remote Site Setting compared to from Apex.

But are there any other caveats to this approach? Would it potentially cause a problem in Security Review?

5

The rule of thumb for the security review is no self-modifying code. That is, suppose you want to publish an app that is an IDE and creates other packages. That's going to be OK as long as the namespace of the packages you are creating is different from the namespace of your app. If it's the same namespace, you will most likely run into problems. There are very minor exceptions to this -- for example, populating pick list labels. But there are no exceptions for things like brand new VF pages or classes being inserted into a managed package at runtime. So please have the code that does the insertion be in a separate namespace that is going through the review, since there needs to be a well-defined (not self-modifying) code base to review.

There are other issues related to transparency -- e.g. you need to disclose what you are doing to admins triggering the event. That can usually be taken care of without any architectural changes, as it's just a matter of proper disclosure.

Also, when using the APIs, be sure to use OAuth to authorize your app, rather than grabbing the current user's session id.

  • Thanks for your response. To be clear, the VF page our package would be creating is in the end user's own org, in their own namespace. I would be providing them a shortcut that is easier for admins to use than the instructions "Please copy the following 3 lines and paste them into a new VisualForce page". This would be similar to how Andrew Fawcett's DLRS has a "Create Remote Site Setting" button that calls out to the Metadata API via JavaScript. That one does use {!$Api.Session_ID} incidentally and seems to have passed security review. – Charles T Dec 10 '17 at 5:44
  • Basically the admin user would be going into a setup interface to pick one or more of their org's objects and define how they want them mapped to "Cloud Product". As a courtesy final step we'd display something like: To use this on the object's page layout, we need to create a VisualForce page. Click here to do this automatically. – Charles T Dec 10 '17 at 5:59
  • I don't know whether that specific code you referenced has gone through the review or when -- you may want to reach out in an office hour about the API.SessionID. We really don't like apps using that session id for a lot of reasons -- none of them the fault of developers -- but the API session Ids blow up the security of using namespaced origins in the first place. Think of what happens if there's an XSS and the attacker grabs it. So one option is to do this in Apex code, so that an XSS in your page doesn't give the attacker a cross-namespace token that is equivalent to a full app compromise. – Robert Sussland Dec 10 '17 at 10:56
  • 1
    Thanks Robert I might do that. Would it be any more secure if we make a Javascript Remoting call to Apex for the Session ID, rather than binding it directly into Visualforce? That way it would not be present in the returned markup on a GET request, and browsers do not allow cross-site attackers to execute those remoting calls. – Charles T Dec 10 '17 at 14:58
  • @CharlesT That wouldn't make it more secure from this attack (XSS), as an attacker could also make the remoting call. The most secure (and recommended) option is to use the API.Session ID in Apex and not on the client. You can trigger the call from the client, but the token itself should not be exposed to the client side DOM. But again, I'm not saying you must do this -- you can book an office hour to discuss. – Robert Sussland Dec 10 '17 at 23:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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