WITH SECURITY_ENFORCED in Salesforce Apex
In this article I will be talking about the WITH SECURITY_ENFORCED clause and why as Developers we use it in our SOQL queries.
Why do we use WITH SECURITY_ENFORCED in SOQL queries?
Apex generally runs in system context, which means that it does not take into consideration the the current user’s permissions and field-level security. This causes a problem because if you include a field in a SQOL query that a user doesn’t have access to, the field is returned and can be used by the code, thus exposing the data to someone that should not have access to it.
So we use WITH SECURITY_ENFORCED to throw an exception if there are any Fields or Objects in the query that the context user doesn’t have access to. In that way we ensure that the code doesn’t provided access to Fields or Objects that an admin may have specifically restricted access to via the profile.
What is the difference between WITH SECURITY_ENFORCED and WITH SHARING?
An important thing to note here is that WITH SECURITY_ENFORCED clause is different from the with sharing or without sharing keywords. When using with sharing keyword you are enforcing record access, unlike the WITH SECURITY_ENFORCED clause which is used to enforce Field and Object level security.
The with sharing or without sharing keywords on a class decide whether Sharing Rules are enforced or not. So when you use the with sharing keyword in you class and for example you display a list of contacts, then only the records that the user has access to are displayed.
Enforcing Field Level Security in Visualforce Pages
Visualforce Standard Controller runs in User Context, which means that Object and Field level security is automatically enforced when using Standard Controller.
Visualforce Custom Controller runs in System Context, which as we mentioned, does not Object and Field level security.
So, In order for a visualforce custom controller to respect Field and Object level security we use the WITH SECURITY_ENFORCED clause. I’m going to illustrate this with an example.
In this example I’m using a custom controller in visualforce. It’s a simple page that displays a table of 5 accounts. The table has 3 columns: Account Name, Account Number and Website. Then we have a button that will update the website of the first account record displayed in our list: sForce.
Visualforce:
Apex Controller:
Now, to see what happens when we don’t have access to a certain field, I created a Dummy User. Then I will update this user’s profile to NOT have Read or Edit access to the Website field by going to his profile and unchecking the Read and Edit permissions
Now when I log in as the Dummy User and open the visualforce page, I cannot see the Website column. But here’s the question:
What happens when I click the button? Will the website field be updated?
The answer is yes, because the visualforce page is running in System Context which doesn’t enforce the field level security.
As you can see, A user who doesn’t have access to a field could update it, and this is an unwanted behavior. So to prevent this we will use the WITH SECURITY_ENFORCED clause.
Now, when I open the visualforce page as the Dummy User, an exception will be thrown indicating that there is an inaccessible field queried.
This way we were able to achieve Object and Field level security in our Visualforce pages.
Please note that WITH SECURITY_ENFORCED is inserted after the WHERE clause if one exists, if not then after the FROM clause and Before any ORDER BY, LIMIT, OFFSET, or aggregate function clauses.
For more information check the Salesforce Documentation.