By default Salesforce allows the guest user to be granted 'Create' and 'Read' sharing access to standard object records (for the purpose of this question, let's consider Account). It makes sense that in the standard sharing model you cannot enable 'Edit' access because this would remove all security from your data and any user could change your Salesforce data.
However, with a little bit of custom work some security could be added to allow guest users to securely change some data. Let's say I have a field on Account called
My_Field__c that I would like my customers to be able to update under some scenarios. Does anyone see any inherent security risks in the following setup and/or have any insight on how Salesforce might view this custom override to the default sharing model?
- Add a new custom field
Accountthat indicates this record is available for customer editing.
- Create a sharing rule to allow site guest user
- Create a custom
External_Id__cfield containing a secure, non-sequential Id value. We don't want to use the standard Salesforce Id because these are sequential and easy to guess. This will be given to the customer so they can update their
My_Field__cvalue in our system using a URL like https://my-force-com-site.com/updatedetails?a=SFGH40MTdoyTINd0eqb99rENNdcylJQZ07B2vJj5easOxMEtin0e3NVa4oyj
- Create a Visualforce page for the editing that loads records
with sharingusing the
This is now the part that seems the least straight-forward to me. We can give the Site Guest user 'read-only' access to a number of fields with Field Level Security but because they do not have top-level Edit access to the object, Visualforce
apex:inputField tags will render as read-only and we cannot check
isUpdateable() from Apex because it will always say false. However, we can do the following:
- Store the Salesforce Account Id in a temporary variable in Apex in the constructor.
- Clear the Id from the Account in the constructor. (The page now views the Account as a new record and FLS behaves as expected with respect to read/edit access to specific fields).
- On save, place the Account Id back onto the record, ensure that the user has
isCreateable()access to all the fields on the Account record, then perform an update call.
This accomplishes what I am looking for from a technical standpoint but does anyone see any big issues here or egregious sharing model violations?
I just want to add a note that I am aware I could use an authenticated community user to achieve full security. However this update that is being made is incredibly infrequent per customer and requiring people to set up a user before performing it will be a big road-block. Also, there is a non-insignificant increased cost to acquiring blocks of licenses from Salesforce (especially if we want access to sharing).
To narrow the scope of this question a little, let me add some additional detail. I understand that in passwordless security there is a non-zero chance that a guess could be made for an access token. This can be mitigated by using long access tokens generated with randomness from the Apex
Crypto class. I am more interested in any non-brute force risks here that are unique to the Salesforce platform. For example, if Salesforce allowed guest access to the REST API, then someone could simply execute a SOQL query via REST API to list all Accounts that they could edit, then proceed to make edits to them with other REST API calls. However, Salesforce does not allow unauthenticated access to the REST API (nor do they allow loading other standard pages to list records on a Force.com site).