Sharing

Abstract

Force.com allows developers and administrators to control access to data at many different levels. You can control access at the object-level, the record-level, and at the field-level. This article will focus on security guidelines for controlling access to data at the record-level.

The default behavior for apex classes is to run without sharing. Use with sharing keyword to enforce sharing.

Public with sharing class MyController {
// Code enforces current user's sharing rules


Understanding Sharing

Sharing policy: Sharing policy is a record level access control for all custom objects, as well as many standard objects (such as Account, Contact, Opportunity and Case). More details on sharing policies can be found here:

Understanding Sharing

To learn more about Sharing architecture within Salesforce please refer to the following documentation: Sharing Architecture

Implementing Sharing Rules

The platform supports many ways of setting sharing permissions. The owner of a record can explicitly grant access to that record to another user. There are group based policies, hierarchies and many other ways of managing sharing. See Types of Sharing

Enforcing Sharing in Apex Classes

  • Sharing rules can never be stricter than your organization-wide default settings. They simply implement access controls on the record level among users/groups.
  • Sharing rules can be enforced in your apex class by including the with sharing keyword in your class declaration.
  • The “with sharing” keyword on a class affects all Database operations/queries in the class.
Public with sharing class MyController {
// Code enforces current user's sharing rules

Function calls inherit the enforcement of the sharing policy from the caller class. If no keyword is present then it defaults to the sharing settings of the caller.

//Function is declared in a class with sharing but sharing policies depends on the calling class.
public class with sharing Def {
	myfunc(x,y){
…..   }
// Function is called from this class which is declared without sharing 
public class without sharing abc {
	// This function will be called without sharing although it is declared in a class with sharing.
Def.myfunc();
…….

Virtual/Abstract classes should also be defined with the with sharing keyword. If the concrete class overrides the sharing policies for virtual/abstract classes, then sharing policies are inherited from the concrete class.

	// Abstract/Virtual classes also need to be defined “with sharing”
	public abstract class with sharing abc {

In apex code no sharing policies are inherited from the outer classes. For example:

Public class with sharing MyController {
    // Code enforces current user's sharing rules 
    Public without sharing Class MyInnerClass {
        // Code does not enforce current user's sharing rules
    }
}


Secure Coding Guidelines

  • Every class should have either with sharing or without sharing keyword. For example:
Public class MyController {
    // Bad practise to declare a class. Please always use either with or without sharing keyword in  the class declaration.
}
  • Declaring a class and leaving the with/without sharing keyword means the sharing security now relies on the caller class. This means we are setting a critical security feature as an effect of code written somewhere else, possibly by another developer.
  • If a class needs multiple sharing policies, refactor the code and declare separate classes with their sharing keywords.
    • Use of without sharing in a class is legitimate ONLY if custom fields are being accessed and no standard fields are being accessed. In that case, the developer may want to roll their own security policy (just as with CRUD/FLS) and they need not respect the platform policy for fields that they own. However, they ‘’’must’’’ respect the platform policy for fields that they don’t own (standard fields).
  • All entry points to an application should have the with sharing keyword in your class declarations. Unless and until there is a specific reason to declare classes using the without sharing keyword.
  • If you need your code to operate ‘’’without sharing’’’, extract the minimum amount of code that needs to use this keyword and put it in a helper class.
  • Developers often need to refactor their code, particularly when they write helper classes that handle both standard and custom fields. If they want the helper class to not have a sharing declaration or be without sharing, then they need to split the class up into one that handles custom fields and one that is explicitly with sharing for the standard fields.
  • Sharing also needs to be enforced on asynchronous apex classes. Sharing does not depend on whether the class executes asynchronously as a scheduled job or batch job, what matters is whether standard fields are being accessed by the class.
  • It is a common misconception that Asynchronous classes must be declared as Global. However, asynchronous classes should always be declared as public.
  • Another common misconception is that Asynchronous classes have no user context, however the user context is whomever launched the job
  • Invoking a trigger from a global class without sharing is considered insecure because there is no way to ensure that only the right sObject types are being changed.

For example:

// Trigger a function which takes parameterized object:  
AnotherClass.my_update(foo, bar)
// AnotherClass declaration with global and missing sharing keyword: 
	Global class AnotherClass {

// Function declaration
my_update(SObject foo, String bar) {
		foo.Name = bar;
		update foo;
}

In cases when a specific action needs to be performed without sharing, it should be done via a without sharing utility class called from the controller. Make sure to document these use cases as a part of your AppExchange review submission.