Thursday 11 February 2021

Spring 21 - AuraEnabled Apex and Sharing


(Updated 11/02 to fix typo on inherited sharing when Apex is invoked by starting a transaction. Mea culpa)

Introduction

The Spring 21 release of Salesforce includes an update that may change the behaviour of your Apex classes that are used as controllers for Aura or Lighting Web Components. If your org was created after the Spring 18 Salesforce release, or you activated the (now retired) update

   Use without sharing for @AuraEnabled Apex Controllers with Implicit Sharing 

then by default your controllers run as without sharing, which means that they don't take into account sharing settings for the user making the request and allow access to all records. 

Once Spring 21 goes live, the

   Use with sharing for @AuraEnabled Apex Controllers with Implicit Sharing (Update, Enforced)

will be applied and this behaviour will be reversed - the default will be with sharing and access will only be allowed for records owned by, or shared with, the user making the request. 

Why the Change

In a word, security. This update makes your components secure by default - if you forget to specify with sharing or without sharing, the principle of least privilege is applied and the most restrictive option is chosen. 

The absence of a sharing keyword can also be considered a sharing keyword

I'm really not a fan of acts of omission driving behaviour, especially when that behaviour isn't guaranteed. Prior to the Spring 21 release, if you don't specify the type of sharing, there's no way to tell by inspecting the code itself what will happen. Anyone debugging an issue around sharing would have to know when the org was provisioned, or find out whether the earlier update had been applied, always assuming they could get access to production to find out!

Historically, one reason to omit the sharing was to allow the code to inherit the sharing from it's calling Apex. This allowed a class to execute as though :

  • with sharing is defined, if called from a class defined as with sharing
  • without sharing is defined, if called from a class defined as without sharing
which gives a great degree of flexibility, with the trade-off that the exact same behaviour applies if you forgot the sharing declaration rather than intentionally excluded it. A comment to clarify the intent could help here, but that's something else to remember.

Inherited Sharing


Winter 19 made a great step forward for forgetful programmers with the introduction of the inherited sharing keyword. This explicitly states that the the class will inherit the sharing from the calling code, so no need for anyone to try to infer what the missing sharing keywords might mean.  

A slight wrinkle to this is what does inherited sharing mean when the calling code is not Apex - i.e. when it is the entry point for a transaction and thus executed by the Salesforce platform? A great example of this is an @AuraEnabled class used as a controller for an Aura or Lightning Web Component, aka where we came in to this post! 

The good news is that the Apex docs explicitly call this out - inherited sharing means with sharing when it is the entry point for a transaction - the principle of least privilege again, but clearly documented so that everyone knows what behaviour to expect.

Call to action

So do yourself and your team a favour, and when you are checking your @AuraEnabled classes to see if they will be affected by the Spring 21 update, if you find any without a sharing keyword, add one to make it clear what sharing is being applied. Your future self will thank you, and it also means that Salesforce can flip flop around what the absence of a sharing keyword should be and your code remains unaffected.

Related Posts


No comments:

Post a Comment