Newer Version Available
Securing Data in Apex Controllers
Sharing Rules
You can choose whether an Apex class enforces sharing rules by using the with sharing or without sharing keywords.
An @AuraEnabled Apex class that doesn’t explicitly set with sharing or without sharing uses a default or implicit value of with sharing.
However, Apex classes that don’t explicitly set with sharing or without sharing inherit the value from the context in which they are run. 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. It’s a best practice to always use with sharing in Apex controllers used by Aura components.
Enforcing sharing rules by using the with sharing keyword doesn’t enforce the user’s permissions and field-level security. You must manually enforce CRUD permissions and field-level security separately in your Apex classes.
Object and Field Permissions (CRUD and FLS)
Enforce object-level and field-level permissions in your code by explicitly calling the sObject describe result methods (of Schema.DescribeSObjectResult) and the field describe result methods (of Schema.DescribeFieldResult) that check the current user’s access permission levels. In this way, you can verify if the current user has the necessary permissions, and only if he or she has sufficient permissions, you can then 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.
Example
This example shows the recommended way to query fields on a custom expense object.
1public with sharing class ExpenseController {
2
3 // ns refers to namespace; leave out ns__ if not needed
4 // This method is vulnerable.
5 @AuraEnabled
6 public static List<ns__Expense__c> get_UNSAFE_Expenses() {
7 return [SELECT Id, Name, ns__Amount__c, ns__Client__c, ns__Date__c,
8 ns__Reimbursed__c, CreatedDate FROM ns__Expense__c];
9 }
10
11 // This method is recommended.
12 @AuraEnabled
13 public static List<ns__Expense__c> getExpenses() {
14 String [] expenseAccessFields = new String [] {'Id',
15 'Name',
16 'ns__Amount__c',
17 'ns__Client__c',
18 'ns__Date__c',
19 'ns__Reimbursed__c',
20 'CreatedDate'
21 };
22
23
24 // Obtain the field name/token map for the Expense object
25 Map<String,Schema.SObjectField> m = Schema.SObjectType.ns__Expense__c.fields.getMap();
26
27 for (String fieldToCheck : expenseAccessFields) {
28
29 // Check if the user has access to view field
30 if (!m.get(fieldToCheck).getDescribe().isAccessible()) {
31
32 // Pass error to client
33 throw new System.NoAccessException();
34 }
35 }
36
37 // Query the object safely
38 return [SELECT Id, Name, ns__Amount__c, ns__Client__c, ns__Date__c,
39 ns__Reimbursed__c, CreatedDate FROM ns__Expense__c];
40 }
41}