Salesforce Field Security in SOQL WITH Security Enforced

In Salesforce Apex, we use the WITH SECURITY_ENFORCED keyword to enable field and object-level security in the SOQL queries.

This checks security permissions for the SOQL SELECT queries in the Apex code, including subqueries and cross-object relationships.

In this Salesforce tutorial, I will explain the WITH SECURITY_ENFORCED clause in SOQL and how to use it to enable field or object-level security in SOQL queries.

What is the WITH SECURITY ENFORCED clause in Salesforce?

In Salesforce Apex, by using the WITH SECURITY ENFORCED, we can apply field and object-level security checks to the fields and objects referenced in the SELECT or FROM SOQL clauses. Still, we cannot use security checks on clauses like WHERE or ORDER BY.

This means that security can be enabled only on what the SOQL SELECT query returns, not on all the elements that go into running the query.

Where should the WITH SECURITY_ENFORCED clause be inserted in the SOQL query?

In Salesforce SOQL queries, the WITH SECURITY_ENFORCED clause should be inserted after the WHERE clause if it exists; otherwise, it should be inserted after the FROM clause. Also, it can be inserted before any ORDER BY, LIMIT, OFFSET, or aggregate function clauses.

The WITH SECURITY_ENFORCED clause is only available in Apex. It is not recommended to use WITH SECURITY_ENFORCED in Apex classes or triggers with an API version earlier than 45.0.

Syntax for WITH SECURITY _ENFORCED clause

The WITH SECURITY_ENFORCED clause is executed in the SOQL using the following syntax.

ELECT Id, Name, Email 
FROM Contact 
WITH SECURITY_ENFORCED

In this query, if the user doesn’t have access to the email, the query will throw an exception. This way, the WITH SECURITY_ENFORCED clause ensures that no unauthorized access is granted to restricted fields.

Use case example of WITH SECURITY_ENFORCED clause in SOQL

For example, if the user has field access for email, this query returns the ID and email for the Contacts, then the WITH SECURITY_ENFORCED will be inserted in the Apex code in the following way.

SELECT Id, Name, Email 
FROM Contact 
WHERE Email LIKE '%.com'
WITH SECURITY_ENFORCED
what is With security enforced in Salesforce soql

Apex SOQL query without WITH SECURITY_ENFORCED clause:

Let’s see what an Apex SOQL query looks like when executed without a WITH SECURITY _ENFORCED clause.

try {
    List<Contact> contacts = [SELECT Id, Name, Email FROM Contact];
    System.debug(contacts);
} catch (Exception e) {
    System.debug('Exception occurred: ' + e.getMessage());
}

The above query fetches all requested fields regardless of the user’s permissions, which might give access to that data to the user he is not supposed to view.

Apex code using WITH SECURITY _ENFORCED clause:

try {
    List<Contact> contacts = [SELECT Id, Name, Email FROM Contact WITH SECURITY_ENFORCED];
    System.debug(contacts);
} catch (Exception e) {
    System.debug('Exception occurred: ' + e.getMessage());
}

For execution purposes, I have written the Apex class in the following way.

public class ContactService {
    public void mymethod() {
        List <Contact> myContact = new List <Contact>();
        myContact = [SELECT Id, Name, Email FROM Contact WITH SECURITY_ENFORCED];
    for (Contact c : myContact) {
        system.debug('ID :' + c.Id + ' Name :  '  + c.Name + ' Email: ' + c.Email);
    }
        }
}

In the execution log window, the following output will be there if the user has access to records.

With security enforced in Salesforce SOQL

In the above query, if the user lacks access to the Email field, the query throws an error of System.QueryException with a message: INSUFFICIENT_ACCESS_ON_CROSS_REFERENCE_ENTITY

WITH SECURITY_ENFORCED limitations

In the following points, we will examine the limitations of the WITH SECURITY_ENFORCED clause that should be considered when executing it.

  • For static validation, this clause operates only at run time and does not validate queries at compile time.
  • If the user cannot access fields or objects, a System.A QueryException error is thrown, which must be handled programmatically; this means we need to modify the code with try-catch exception handling.
  • For cross-object queries, ensure all queried fields across objects have the required permissions.

What is the difference between WITH SECURITY_ENFORCED and WITH SHARING?

In Salesforce SOQL, WITH SECURITY_ENFORCED and WITH SHARING are used to ensure data access is aligned with defined security and sharing rules, but they operate at different levels and contexts.

WITH SECURITY _ENFORCED in SOQL:

  • The scope of WITH SECURITY _ENFORCED applies to object- and field-level security in SOQL queries.
  • If the running user cannot access a queried field or object, an exception (System.QueryException) is thrown.
  • It checks CRUD (Create, Read, Update, Delete) access and FLS (Field-Level Security) for the objects.
  • It ensures security compliance directly in SOQL queries.

WITH SHARING in SOQL:

  • The scope of WITH SHARING applies to record-level sharing rules in Apex classes.
  • The purpose of this clause is to enforce record-level sharing rules when the Apex code runs.
  • Without this, code can bypass sharing rules (if the class is defined as WITHOUT SHARING or a system-level class like a trigger handler).
  • It ensures record-level sharing rules for users’ data visibility.

You may also like to read

Agentforce in Salesforce

DOWNLOAD FREE AGENTFORCE EBOOK

Start with AgentForce in Salesforce. Create your first agent and deploy to your Salesforce Org.

Salesforce flows complete guide

FREE SALESFORCE FLOW EBOOK

Learn how to work with flows in Salesforce with 5 different real time examples.