Secure Apex Classes
In API version 67.0 and later, Apex runs in user mode by default, meaning that the current user’s permissions and field-level security (FLS) are enforced during code execution. To ignore the FLS and object permissions of the current user, you must explicitly set a database operation or query to run in system mode. Additionally, Apex classes enforce record sharing rules by default. If you don’t want to enforce sharing rules, then you must declare a class with the without sharing keyword.
In API version 66.0 and earlier, Apex runs in system mode by default, which means that it runs with substantially elevated permissions, acting as if the user had most permissions and all field- and object-level access granted. Because these security layers aren’t enforced like they are in the Salesforce UI, you must write code to enforce them. Otherwise, your components may inadvertently expose sensitive data that would normally be hidden from users in the Salesforce UI.
To work with Salesforce records, we recommend using Lightning Data Service, which handles sharing rules, CRUD, and field-level security for you. See Data Guidelines.
An authenticated or guest user can access an @AuraEnabled Apex method only when the user’s profile or an assigned permission set allows access to the Apex class.
For details on configuring user profile or permission set access to an Apex class, see Class Security in the Apex Developer Guide.
An @AuraEnabled Apex class that doesn’t explicitly set with sharing or without sharing, or is defined with inherited sharing, uses a default or implicit value of with sharing. However, Salesforce recommends that you use keyword declarations on all your classes to make your code easier to maintain across API versions.
To bypass sharing rules, you must explicitly declare the class as without sharing.
The with sharing and without sharing keywords set record-level security. They don’t enforce object-level and field-level security.
Apex database operations run in user mode by default. Database operations only ignore FLS and object permissions if you explicitly set them to run in system mode. However, Salesforce recommends setting an access mode on all database operations so that your code is easier to maintain across API versions.
Use the WITH USER_MODE or WITH SYSTEM_MODE clauses for SOQL SELECT queries in Apex code, including subqueries and cross-object relationships.
For example, getExpenses() uses the WITH USER_MODE clause to enforce object-level and field-level permissions.
To bypass the current user’s FLS and object permissions, you must explicitly add the WITH SYSTEM_MODE clause to the SOQL query.
For more details, see Set an Access Mode for Database Operations in the Apex Developer Guide.
For more graceful degradation on permissions errors, use the stripInaccessible() method to enforce field- and object-level data protection. This method strips the fields and relationship fields from query and subquery results that the user can’t access. You can find out if any fields were stripped and throw an AuraHandledException with a custom error message, if desired.
You can also use the method to remove inaccessible sObject fields before DML operations to avoid exceptions and to sanitize sObjects that have been deserialized from an untrusted source.
This example updates ExpenseController to use stripInaccessible() instead of the WITH USER_MODE SOQL clause. The results are the same but stripInaccessible() gives you the opportunity to gracefully degrade instead of failing on an access violation when using WITH USER_MODE.
For more details and examples, see Enforce Security with the stripInaccessible Method in the Apex Developer Guide.
Before the WITH USER_MODE clause and stripInaccessible() method were available, the only way to enforce object and field permissions was to check the current user’s access permission levels by calling the Schema.DescribeSObjectResult and Schema.DescribeFieldResult methods. Then, if a user has the necessary permissions, perform a specific DML operation or a query.
For example, you can call the isAccessible, isCreateable, or isUpdateable methods of Schema.DescribeSObjectResult to verify whether the current user has read, create, or update access to an sObject, respectively. Similarly, Schema.DescribeFieldResult exposes access control methods that you can call to check the current user’s read, create, or update access for a field.
This example uses the describe result methods. This approach requires many more lines of boilerplate code so we recommend using the WITH USER_MODE clause or stripInaccessible() method instead.
For more details and examples, see Enforce Security with Field and SObject Describe Methods in the Apex Developer Guide.
See Also