Run Apex in the context of a different user

apexcontext

Is it possible to run Apex in the context of a different user?

Specifically, we are building a custom Partner Community. We want to share some information about some custom objects but we want to prohibit the users in this community to be able to use API or other APEX to access the data.

E.g. is it possible that we treat Salesforce like a database – where the user is talking to the Apex code and only that Apex code can see the fields, whereas if the user went to, say, standard record page, or made an API call, or used other Apex (not developed by us, for example), they could NOT see any data about the records. 

So ideally we would not give 'Read' access to an object to these users instead having our code only be authorised to access this data.

Kind of like in a traditional web app, where your FE authorises you to the backend but the user that accesses the DB has nothing to do with the user that accesses your Front End?

Best Answer

In answer to your question title, you cannot run Apex as another user directly**, but you don't need to in order to achieve your goals.

Except for anonymous apex, apex runs in system mode so can access and manage data on behalf of the user that the user cannot access otherwise (including UI and REST API etc.). If you apply sharing you can also decide whether or not this affects the queries and DML in your code base using a class declaration "with sharing" or "without sharing" (plus inherited sharing).

If you use managed code from your own managed package you can have a protected custom object. Being protected it is only visible to your managed package.

Using these points together it is possible to ensure that the custom object records can only be accessed and manipulated via your own packaged APIs and Apex.

Note that new features are coming to support user mode in apex and the declared intent from Salesforce is to eventually flip the default execution mode for Apex to be user mode rather than system mode.

You should also note that managed packages can only be put on the app exchange after passing a security review from Salesforce. To do what is listed here (explicitly ignore the user's permissions in your apex code) is something you would have to explicitly explain and list as false positive CRUD/FLS violations. Of course, you can create a managed package without listing it (and thus having it reviewed) if you are doing so just for yourself.

NB: To handle false positives, we tend to ensure that this is documented in the code itself. For example, if we do a query without permission checks we would have something like:

for (Account account : [SELECT Scope__c FROM Account // CRUD/FLS False Positive: permissions are not checked because ...
        WHERE ...]) {
    ...
}

It's on the end of the first line that forms a statement and simply goes as long as required. This way, when Checkmarx flags the false positive, our whole comment explaining why it is a false positive is included in the generated report.

The same applies to DMLs and the field assignments and object instantiations that precede them.

**: Platform event apex trigger based subscribers run as a different user but that isn't necessary to use here.

Related Topic