Writing secure Apex with the latest security best practices
Over the last few years, there have been a lot of changes around enforcing the CRUD (create, read, update, and delete) and FLS (field-level security) securities in Apex.
Harald is the Co-Founder of Hutte, bringing his vision of no-code DevOps to life. His passion enables teams and individuals to focus on what matters most – bringing value to the users they build for.
Samantha Spiro
Senior Content Manager & Editor-In-Chief
Samantha is Hutte's Content Manager and Chief Editor. She has over six years of experience as both a content writer and a copywriter. Bringing the written word to life is the name of her game.
Article highlights
The use of WITH USER_MODE and WITH SYSTEM_MODE in SOQL and SOSL queries allows developers to precisely enforce CRUD, FLS, and record-level sharing security constraints.
Salesforce's introduction of user mode database operations represents a significant shift, enabling Apex to run in the user's context, thereby ensuring that security settings like CRUD and FLS are adhered to by default.
The new AccessLevel parameter in the database and search class methods enhances security customization, supporting more granular control over data access and manipulation in Apex.
The diagram above depicts the evolution of Apex security best practices. It dates back to 2006 when Salesforce developers used to do manual checks on objects to check for CRUD/FLS permission.
🔏
In 2019, Salesforce released some significant updates (“WITH SECURITY_ENFORCED” and “Security.StripInaccessible()”) to improve on some of the shortcomings of the earlier approaches.
To address most (if not all) of the issues encountered in the past, Salesforce announced user mode database operations.
Let’s see what it is all about.
Apex, by default, runs in a system mode with elevated permissions, meaning that developers can bypass security controls, such as CRUD, FLS, or record sharing, when writing code.
With user mode database operations, developers can run Apex in the user’s context and enforce the user’s CRUD/FLS and sharing rules access.
Enforce CRUD/FLS and sharing rules in SOQL
🔑
You can set the mode of the operation by using the keyword “WITH USER_MODE” for the user mode and “WITH SYSTEM_MODE” for the system mode in your SOQL (Salesforce object query language) inquiry.
Static SOQL example
Account[] accList = [
SELECT
Id, Name
FROM Account
WITH USER_MODE
]; // User Mode SOQL
Account[] accList = [
SELECT
Id, Name
FROM Account
WITH SYSTEM_MODE
]; // System Mode SOQL
Using the keyword “WITH USER_MODE,” the query respects the CRUD, FLS, and record-level sharing security constraints.
Dynamic SOQL example
String query = 'SELECT Id, Name FROM Account';
Account[] accList = Database.query(query, AccessLevel.USER_MODE);
A database class has new overloaded methods, which now support an “AccessLevel” parameter.
Enforce CRUD/FLS and sharing rules for SOSL
🗣️
“WITH USER_MODE” or “WITH SYSTEM_MODE” are also supported for SOSL (Salesforce object search language) statements.
Static SOSL example
String keyword = 'Test';
List<List<SObject>> searchResults = [
FIND :keyword
IN Name FIELDS
RETURNING
Account(Name),
Contact(LastName, Account.Name)
WITH USER_MODE
];
Dynamic SOSL example
String query = 'FIND \'Test*\' IN ALL FIELDS RETURNING Account(Name), Contact, Lead';
List<List<SObject>> searchResults = Search.query(query, AccessLevel.USER_MODE);
Like the database class, a search class also has new overloaded methods, which now support an “AccessLevel” parameter.
Enforce CRUD/FLS and sharing rules for DML
🖥️
Database operations can specify user or system modes using the keywords as a user or system.
//Creating an account in user mode.
insert as user new Account(
Name = 'Test Account'
);
//Creating an account in System mode.
insert as system new Account(
Name = 'Test Account'
);
For Dynamic DML, developers can use the “AccessLevel” parameter to run database operations in the user or system mode.
Database.insert(
new Account(
Name = 'Test Account'
),
true, /*All or Nothing*/
AccessLevel.USER_MODE
);
Important considerations
User mode DML operations now generate the correct DML exception. Previously, they generated a security exception. This behavior is versioned, and the valid exception is generated in API version 58.0 and later.
A SOQL query using the “WITH USER_MODE” keyword supports restriction and scoping rules instead of the “WITH SECURITY_ENFORCED” keyword.
A user mode overrides the class-level setting for the SOQL query or DML written in the mode.
public without sharing Example {
public Account[] getAccounts() {
String query = 'SELECT Id FROM Account';
return Database.query(query, AccessLevel.USER_MODE);
}
}
In the example above, even though the Apex class is set to run in the system context (without sharing the keyword), the SOQL query runs in the user mode, enforcing security.
Salesforce has recommended using the new user mode database ops instead of “WITH SECURITY_ENFORCED” going forward. "WITH SECURITY_ENFORCED" may likely be versioned out at some point.
The Spring Release has introduced significant enhancements to Apex, providing developers with new tools and functionalities that support more secure and efficient coding practices.
Updated Migrate to Flow Tool
This tool has been updated to support the partial migration of most actions, excluding invocable actions. This enhancement aids developers in transitioning legacy Apex code to the more modern and robust Flow Builder, which can lead to more secure and maintainable codebases.
New and Changed Aura Components
There have been adjustments to the lightning:navigation component in Aura that affect how navigation works post-record creation, which can be crucial for maintaining secure user experiences in Salesforce applications.
Harald is the Co-Founder of Hutte, bringing his vision of no-code DevOps to life. His passion enables teams and individuals to focus on what matters most – bringing value to the users they build for.
Samantha is Hutte's Content Manager and Chief Editor. She has over six years of experience as both a content writer and a copywriter. Bringing the written word to life is the name of her game.