In Salesforce, while we do development, ensuring data security is important, and we can do that using the CRUD feature. CRUD permissions allow us to define what a user can do with different data types. Validating these permissions before performing SOQL or DML operations helps maintain the security of the org application and protects sensitive data.
In this Salesforce tutorial, I will explain how to validate the CRUD permission before SOQL/DML operations in Salesforce.
CRUD permission validation in Salesforce Apex
Salesforce enforces CRUD and FLS (Field Level Security) at the platform level for declarative tools like standard UI and reports. Not validating the CRUD permissions can lead to unauthorized access to data and create data security issues.
Methods for CRUD Validation in Salesforce Apex
Salesforce provides methods in the Schema.DescribeSObjectResult and Schema.DescribeFieldResult classes to check CRUD and FLS permissions. Below are the methods to validate the CRUD permission in Salesforce.
- isCreateable(): This method checks permission to create records.
- isAccessible(): It checks if the user can read records.
- isUpdateable(): Checks if the user has permission to update records.
- isDeletable(): Checks if the user has permission to delete records.
Validate Read Permission Before SOQL Query
Validate the user’s read permission before the SOQL query.
Apex Class:
public class getAccounts {
public void fetchAccounts() {
if (!Schema.SObjectType.Account.isAccessible()) {
System.debug('Access to Account records is denied.');
throw new SecurityException('You do not have permission to access Account records.');
}
System.debug('Access to Account records is granted.');
List<Account> accounts = [SELECT Id, Name FROM Account];
System.debug('Fetched Accounts: ' + accounts);
}
}Calling the class method fetchAccounts to show the output :
getAccounts ga = new getAccounts();
ga.fetchAccounts();Output:

As we can see, the debug statements returned that access is granted, and this way, we can validate the read access for a user in Salesforce SOQL and DML operations using the .isAccessible() method.
Validate Create Permission Before Inserting Records
In this example, we will validate the user’s creation permission before inserting the records through the DML operation. For this, we will use the method .isCreateable() to check the permission to create records.
Apex Class:
public class AccountInsertPermission {
public void createAccount(Account acc) {
if (!Schema.SObjectType.Account.isCreateable()) {
System.debug('Create permission for Account records is denied.');
throw new SecurityException('You do not have permission to create Account records.');
}
System.debug('Create permission for Account records is granted.');
insert acc;
System.debug('Inserted Account: ' + acc);
}
}Calling the defined validation method createAccount :
Account newAccount = new Account(Name = 'Test Account');
AccountInsertPermission manager = new AccountInsertPermission();
manager.createAccount(newAccount);Output:

As we can see in the debug, the create permission is validated, and an account is created or inserted. This way, we can validate the create permissions in Salesforce using the .isCreateable() method.
Validate the Update Permissions before updating records.
In this example, I have created a public class, ContactsController, that will retrieve a list of Contact records from the database while ensuring that the fields and objects we’re trying to access can be updated.
In this example, we will check the update records validation for the contact fields Name and Phone, and the method getDecribe will validate that the Contact object itself is updatable.
Apex class code:
public with sharing class ContactsController {
public static List<Contact> getContacts(Integer queryLimit, Integer queryOffset) {
List<Contact> contacts = new List<Contact>();
try {
if(
Contact.SObjectType.getDescribe().isUpdateable() &&
Schema.SObjectType.Contact.fields.Name.isUpdateable() &&
Schema.SObjectType.Contact.fields.Phone.isUpdateable()
) {
System.debug('Query Limit: ' + queryLimit);
System.debug('Query Offset: ' + queryOffset);
contacts = [SELECT Id, Name, Phone, Email FROM Contact LIMIT :queryLimit OFFSET :queryOffset];
System.debug('Number of Contacts Retrieved: ' + contacts.size());
} else {
System.debug('One or more required fields are not updatable');
}
} catch(Exception e) {
System.debug('Error: ' + e.getMessage());
}
return contacts;
}
}Calling the validation method:
Integer queryLimit = 5;
Integer queryOffset = 0;
List<Contact> contacts = ContactsController.getContacts(queryLimit, queryOffset);
System.debug('Retrieved Contacts: ' + contacts);Output:

This way, we can validate whether the user can update the specific record or not using the “.isUpdatable()” method.
Validate CRUD permission before SOQL operation using WITH SECURITY_ENFORCED
In Salesforce, the WITH SECURITY_ENFORCED keyword is used to enforce field-level security checks within SOQL queries, which means it only verifies if a user can access specific fields in a SELECT statement.
This clause is only applicable to SELECT queries, not DML operations like INSERT, UPDATE, or DELETE. It verifies if the user can access the fields in the SELECT clause based on their object and field-level permissions.
In this example, we will see the user access to read the contact records using the WITH SECURITY_ENFORCED method.
Apex class code:
public with sharing class ContactsController {
public static List<Contact> getContacts(Integer queryLimit, Integer queryOffset) {
List<Contact> contacts;
try {
contacts = [
SELECT Name, Phone
FROM Contact
WITH SECURITY_ENFORCED
LIMIT :queryLimit OFFSET :queryOffset
];
System.debug('Queried Contacts: ' + contacts);
} catch(System.QueryException qe) {
System.debug('Query Exception: ' + qe.getMessage());
contacts = new List<Contact>();
}
return contacts;
}
}Call the validation in the anonymous window.
Integer queryLimit = 10;
Integer queryOffset = 0;
List<Contact> contacts = ContactsController.getContacts(queryLimit, queryOffset);Output :

In the above apex class, I have applied only the keyword WITH SECURITY_ENFORCED after Contact in the query to check validation.
This query will return a QueryException if we’re querying a field the current user cannot access. To check that, I called the getContacts method from the anonymous apex window. Then, in the debug window, we got the list of contacts validating the read access of records.
This method of validating record access is useful when validating multiple fields in an object. Then, instead of using the isAccessible() method for all fields, we can use SECURITY_ENFORCED to validate them.
Use the stripInaccessible() method to validate CRUD permission before SOQL
The stripInaccessible() method is used to strip or remove the results of a query that users don’t have access to. The stripInaccessible method is part of the Security class and has two variations, as explained below:
1. stripInaccessible(accessCheckType, sourceRecords, enforceRootObjectCRUD):
- accessCheckType: This parameter defines the type of access check using the AccessType enum, which includes four possible values: CREATABLE, READABLE, UPDATABLE, and UPSERTABLE.
- sourceRecords: This is a list of SObjects, where fields that the user cannot access will be removed.
- enforceRootObjectCRUD: An optional boolean parameter that specifies whether to check for object-level access. By default, this parameter is set to true.
2. stripInaccessible(accessCheckType, sourceRecords):
This version of the method includes only the first two parameters, which work the same as described above. The key difference is that this version does not check for object-level access.
Use the stripInaccessible() method in Apex code:
public with sharing class ContactsController {
public static List<Contact> getContacts(Integer queryLimit, Integer queryOffset) {
List<Contact> contacts = [SELECT Name, Phone FROM Contact LIMIT :queryLimit OFFSET :queryOffset];
System.debug(contacts);
SObjectAccessDecision decision = Security.stripInaccessible(AccessType.READABLE, contacts, true);
System.debug(decision.getModifiedIndexes());
System.debug(decision.getRecords());
System.debug(decision.getRemovedFields());
return contacts;
}
}Calling the validate method in the apex anonymous window.
Integer queryLimit = 20;
Integer queryOffset = 1;
List<Contact> contacts = ContactsController.getContacts(queryLimit, queryOffset);Output:

When attempting to create or update a record, a NoAcessException may occur if you lack access to that record. To handle this situation, you can enclose the operation within a try block and include a catch(NoAccessException e) block to catch and process the exception.
Additionally, the stripInaccessible() method can be utilized with two parameters to filter out inaccessible fields from a list of records. This approach lets you focus your exception handling on the insert, update, or upsert statements within a try-catch block.
This way, by using the above methods for different scenarios, we can validate the user access before retrieving them in the SOQL query or the DML operations.
Conclusion
In this Salesforce tutorial, we learned how to validate the CRUD and Field-Level Security (FLS) permissions in Apex before a SOQL query or DML operation. In the above examples, we have used access validation methods such as .isCreateable(), .isAccessible(), .isUpdateable(), and .isDeletable() to ensure users perform only authorized actions.
The WITH SECURITY_ENFORCED simplifies field-level validation for a user in SOQL. The stripInaccessible() method effectively filters inaccessible fields or records, which is helpful in bulk operations.
You may also like to read:
- SOQL Query on Group and GroupMember in Salesforce
- Create a For Loop to Iterate Through a SOQL Query in Salesforce
- OFFSET Clause in SOQL
- Salesforce SOQL Query RecordType
I am Bijay Kumar, the founder of SalesforceFAQs.com. Having over 10 years of experience working in salesforce technologies for clients across the world (Canada, Australia, United States, United Kingdom, New Zealand, etc.). I am a certified salesforce administrator and expert with experience in developing salesforce applications and projects. My goal is to make it easy for people to learn and use salesforce technologies by providing simple and easy-to-understand solutions. Check out the complete profile on About us.