Is your Lightning Component secure ?

Jonathan Maes
All Things PaaS
Published in
8 min readMay 1, 2020

In short…

As Salesforce developers, we are often led to build custom Lightning Components. When implementing a component, one aspect which is often skipped is the Security. A component unsafe can have disastrous consequences. The damages can easily be imaginable if by example, the unsafe component is included in a public community page.

This article dives deep and explains one of the main security breaches which can be created on a lightning component and the solutions to prevent it.

By Jonathan Maes

The basics: CRUD, FLS and Sharing

It could be surprising to see this subject here, but it is from far something usually not enforced or not correctly enforced on a custom Lightning Component. Indeed, the lightning component does not always ensure:

  • The object level permissions (called CRUD in this article for Create Read Update Delete). The CRUD permissions “determine which objects a user can create, read, update, and delete”*.
    There are configured in the profile of the user or in the permission set(s) assigned to him.
  • The field level permissions (called FLS in this article for Field Level Security). The FLS permissions “determine which fields a user can read and edit”*.
    There are configured in the profile of the user or in the permission set(s) assigned to him.
  • The Sharing. The Sharing determines “the access settings on the records themselves”**. The Sharing is defined by the Organization-Wide Defaults, the role hierarchy, the sharing rules,… Described simply, the Sharing can give different type of access to the records : no access, read-only, read/write, read/write/transfer and full access (read/write/transfert/delete).

Depending of the HTML tag used to display or enter information, it is important to know if CRUD permissions, FLS permissions and the Sharing are enforced or not. There are 2 types of tags:

1. The tags leveraging on the Lightning Data Service:

From a high level perspective, the Lightning Data Service (LDS) can be compared to the Visual Force standard controller. The LDS enforces the Sharing, CRUD permissions and FLS permissions automatically.

As mentioned, the first category of tags is the tags built on top of the LDS. There is no need of extra code when these tags are used. Whenever possible, favor tags built on top of the Lightning Data Service to read and modify Salesforce data in your components. A non-exhaustive list of such tags (Aura and LWC) can be found below.

  • lightning:recordForm
  • lightning:recordViewForm
  • lightning:recordEditForm
  • force:recordData
  • lightning-record-form

2. The other tags:

The second category of tags is… the others. Thus, the tags which do not use the LDS to display or modify information. If a tag not leveraging on the Lightning Data Service is used, the back-end apex code (the controller) will have to ensure CRUD permissions, FLS permissions and the Sharing by itself. If it is not done, the component could show (and even give write access to) information which should not be accessible. This is obviously a data breach.
A non-exhaustive list of such tags (Aura and LWC) can be found below.

  • lightning:input
  • lightning:inputAddress
  • lightning:inputName
  • lightning-input

Then, how to enforce CRUD, FLS and Sharing ?

There are several ways to solve this data breach. In this section, we will first discuss the ‘With Sharing’ keyword to solve the Sharing security issue. And then, we propose two solutions to solve the CRUD and FLS security issue.

But, before going into the details, it is important to add that the security enforcement presented here are always added on the server-side. The reason is that the client-side code can be modified by the end-user and then, is fully controlled by him. Thus, the security put in the client side would be easily bypassed.

With Sharing’: required but not enough !

The ‘With Sharing’ keyword allows the developer to specify that the class has to run in the user context. It means that the class enforces the Sharing for the current user.
If ‘With Sharing’ is not added to the controller class, the apex code runs by default in system context. It means that the code has access to all objects records.
However, the keyword ‘With Sharing’ does not enforce the CRUD and FLS permissions. Indeed, ‘With Sharing’ only enforces the sharing of records and does not enforce CRUD and FLS permissions. Thus, even with ‘With Sharing’, the end user could potentially see fields that he should not be able to see or modify a record he should normally not be able to modify.

Let’s recap.

  • The CRUD permissions “determine which objects a user can create, read, update, and delete”*.
    There are configured in the profile of the user or in the permission set(s) assigned to him.
  • The FLS permissions “determine which fields a user can read and edit”*.
    There are configured in the profile of the user or in the permission set(s) assigned to him.
  • The Sharing determine “the access settings on the records themselves”**. The Sharing is defined by the Organization-Wide Defaults, the role hierarchy, the sharing rules,… Put simply, the Sharing can give different type of access to the records : no access, read-only, read/write, read/write/transfer and full access (read/write/transfert/delete).

It is important to note that the CRUD and the Sharing could conflict each other. The rule is: it is the most restrictive who overwrite the other. There are just 2 exceptions: the permissions view all and modify all which overwrite the Sharing without restricting them.

Now, let’s take some examples.

Example 1: In an org, a simple component was developed and published on the account record page in order to let the users change the account name. This component is using tags not leveraging on the LDS. The Organization-Wide Defaults (OWD) of the org is put to Public Read/Write for the object Account.

The code below shows the APEX controller of the component. As you can see this controller has the ‘With Sharing’ keyword.

If a user with a profile giving only read access on the account object uses the component to change the account name, he would be able to update the name without any warning or error showing up.
Explanation: As the Sharing is put to Read/Write for the user (via the OWD), the ‘With Sharing’ keyword validates the update of the account name. The ‘With Sharing’ keyword does not check the CRUD and FLS permissions of the user.

Example 2: In an org, a simple component was developed and published on the account record page in order to let the users change the account name. This component is using tags not leveraging on the LDS. The Organization-Wide Defaults (OWD) of the org is put to Public Read Only for the object Account.

The code below shows the APEX controller of the component. As you can see this controller has the ‘With Sharing’ keyword.

If a user with a profile giving read and write access on the account object uses the component to change the account name, he would NOT be able to update the name as an exception “ INSUFFICIENT_ACCESS_OR_READONLY” will be thrown.
Explanation: As the Sharing is put to Read only for the user (via the OWD), the ‘With Sharing’ keyword does NOT validate the update of the account name. The ‘With Sharing’ keyword does not check the CRUD and FLS permissions of the user.

Example 3: A component was developed and published on the opportunity record page to show some information about the opportunity. This component is using tags not leveraging on the LDS (i.e. ‘lightning:input’ with readonly to true). The Organization-Wide Defaults (OWD) of the org is put to Public Read Only for the object Opportunity.

The code below shows the APEX controller of the component. As you can see this controller has the ‘With Sharing’ keyword.

Let’s imagine a user with a profile giving read access to only some of the opportunity fields. The other opportunity fields being not visible for his profile.
If such a user consults the component built, he would be able to see all the opportunity fields, regardless of the FLS permissions put in place in the org.
Explanation: As the Sharing is put to Read only for the user (via the OWD), the ‘With Sharing’ keyword validates the user has access to the opportunity records. The ‘With Sharing’ keyword does not check the CRUD and FLS permissions of the user.

So, it is clear that even with the keyword ‘With Sharing’, users can view and modify information they should not view or modify. It is obviously something that need to be prevented.

CRUD and FLS Solution 1 : The DescribeSObjectResult class

This class provides some very useful methods to check and ensure the CRUD and FLS permissions in the APEX code:

  • IsCreateable() : can be used before a DML in order to ensure that the user trying to create a record can really do it. By example, check the permission of the customer to create an opportunity with the field amount included: Schema.sObjectType.Opportunity.fields.Amount.isCreateable().
  • IsAccessible() : can be used before SOQL to check that fields and objects are accessible by the user.
  • IsUpdateable() : can be used before DML.
  • IsDeleteable() : can be used before DML. By example, check that the user can delete an opportunity : Opportunity.SObjectType.getDescribe().isDeleteable().

The code below shows a safe solution for the example 1. The code is using the methods of the class DescribeSObjectResult in order to enforce the Update permissions on the account object and on the account fields.

CRUD and FLS Solution 2 : ‘WITH SECURITY_ENFORCED’ keyword

As the methods of the class DescribeSObjectResult can be quite verbose, Salesforce recently made GA a new keyword: ‘WITH SECURITY_ENFORCED’. This keyword is used to enforce Object accessibility and FLS permissions in a SOQL.

Example :
[SELECT Id, Name, Website FROM Account WITH SECURITY_ENFORCED]
If the field access is hidden for at least one field present in the SELECT clause of the SOQL, the query throws an exception indicating insufficient permissions and no result.

It is also important to note that this keyword should be used with Apex classes with API version 48.0 or later.

The code below shows a safe solution for the example 3. The code is using the ‘WITH SECURITY_ENFORCED’ keyword in order to enforce the accessibility permissions on the opportunity object and on the opportunity fields.

Key Takeaways:

  • Use lightning tags leveraging on the Lightning Data Service whenever possible.
  • If not doable, be aware that the ‘With Sharing’ keyword is not enough because it does not ensure CRUD and FLS permissions.
  • Therefore, use solutions such as DescribeSObjectResult class methods and ‘WITH SECURITY_ENFORCED’ to ensure that CRUD and FLS permissions are enforced.

--

--

Jonathan Maes
All Things PaaS

Salesforce System & Application Architect certified, Salesforce Lightning champion, Manager (Lead) at Deloitte Digital.