Secure Apex Classes
By default, Apex runs in system mode, 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.
When you declare a class, it’s a best practice to specify with sharing
to enforce sharing rules when a component uses the Apex controller.
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, an Apex class that doesn’t explicitly set with sharing
or without sharing
inherits the value from the context in which it runs. So when a class without explicit sharing behavior is called by a class that sets one of the keywords, it operates with the sharing behavior of the calling class. To ensure that your class enforces sharing rules, set with sharing
.
The with sharing
keyword enforces record-level security. It doesn’t enforce object-level and field-level security. You must manually enforce object-level and field-level security separately in your Apex classes.
There are a few alternatives to enforce object-level and field-level permissions in your Apex code.
- Easiest enforcement using
WITH SECURITY_ENFORCED
To enforce object-level and field-level permissions, use the
WITH SECURITY_ENFORCED
clause forSOQL SELECT
queries in Apex code, including subqueries and cross-object relationships.The
WITH SECURITY_ENFORCED
clause is ideal if you have minimal experience developing secure code and for applications that don’t require graceful degradation on permissions errors.This example queries fields on a custom expense object with an insecure method,
get_UNSAFE_Expenses()
. Don't use this class!This next example uses a secure method,
getExpenses()
, which uses theWITH SECURITY_ENFORCED
clause to enforce object-level and field-level permissions. Use this class instead ofUnsafeExpenseController
.For more details, see the Apex Developer Guide.
- Graceful degradation with
stripInaccessible()
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 anAuraHandledException
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 usestripInaccessible()
instead of theWITH SECURITY_ENFORCED
SOQL clause. The results are the same butstripInaccessible()
gives you the opportunity to gracefully degrade instead of failing on an access violation when usingWITH SECURITY_ENFORCED
.For more details and examples, see the Apex Developer Guide.
- Legacy code using
DescribeSObjectResult
andDescribeFieldResult
methods Before the
WITH SECURITY_ENFORCED
clause andstripInaccessible()
method were available, the only way to enforce object and field permissions was to check the current user’s access permission levels by calling theSchema.DescribeSObjectResult
andSchema.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
, orisUpdateable
methods ofSchema.DescribeSObjectResult
to verify whether the current user has read, create, or update access to ansObject
, 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 SECURITY_ENFORCED
clause orstripInaccessible()
method instead.
See Also
- Apex Developer Guide: Enforcing Sharing Rules
- Apex Developer Guide: Enforcing Object and Field Permissions
- Apex Developer Guide: Using the with sharing, without sharing, and inherited sharing Keywords
- Secure Coding Guide: Lightning Security