Secure your code using Inherited Sharing

As you are commonly using with sharing or without sharing in apex class, but using without sharing is insecure when you are exposing you data outside and you need to mention false positive statement to pass security review of you code for AppExchange.

Designing Apex classes that can run in either with sharing or without sharing mode at runtime is an advanced technique. Such a technique can be difficult to distinguish from one where a specific sharing declaration is accidentally omitted

Now you can specify the Inherited Sharing keyword on an Apex class, which allows the class to run your apex code with or without sharing settings, depending on the class that called it.

An explicit inherited sharing declaration makes the intent clear, avoiding ambiguity arising from an omitted declaration or false positives from security analysis tooling.

Using inherited sharing enables you to pass AppExchange Security Review and ensure that your privileged Apex code is not used in unexpected or insecure ways.

An Apex class with inherited sharing runs as with sharing when used as:

  • An Aura component controller
  • A Visualforce controller
  • An Apex REST service
  • Any other entry point to an Apex transaction

Difference between an Apex class that is marked with inherited sharing and one with an omitted sharing declaration. If the class is used as the entry point to an Apex transaction, an omitted sharing declaration runs as without sharing. However, inherited sharing ensures that the default is to run as with sharing. A class declared as inherited sharing runs as without sharing only when explicitly called from an already established without sharing context.

Example :-

public inherited sharing class InheritedSharingClass{
    public List<Contact> getAllTheSecrets(){
        return [SELECT Name FROM Contact];
    }
}
<apex:page controller="InheritedSharingClass">
    <apex:repeat value="{!allTheSecrets}" var="record">
        {!record.Name}
    </apex:repeat>
</apex:page>

Apex class used here, with inherited sharing and a Visualforce invocation of that Apex code. Because of the inherited sharing declaration, only contacts for which the running user has sharing access are displayed. If the declaration is omitted, even contacts that the user has no rights to view are displayed due to the insecure default behavior.

Advertisements

Understanding Sharing in Apex Class

To enforce sharing rule on an apex class we use key work – with sharing or with out sharing.  And non-sharing-speficied classes – which is sometime really confusing.

By default Apex code run on the System Context, which means In System context apex code can access all Objects and fields – object permission, field-level security(FLS), sharing rules are not applied for the current user.

With Sharing –

with sharing means “With Security Sharing Setting enforced” for the current user for the class.

public with sharing class sharingClass {
// Code here
}

Without sharing

without sharing mean “without security sharing setting enforced” for the current user to the accessing class.

public without sharing class noSharingClass {
// Code here
}

Further Details –

  • The sharing setting of the class where method is defined is applied, not of the class where method is called.
    • For example –  if a method is defined in a class declared with with sharing is called by a class declared with without sharing, the method executes with sharing rules enforced
  • If a class is declared as “with sharing” then, the sharing settings apply to all code contained in the class, including initialization code, constructors and methods. However.
  • Both inner classes and outer classes can be declared as with sharing.
  • Inner Classes DO NOT inherit sharing settings from the container class.
  • Classes inherit this setting from a parent class when one class extends or implements another.
  • If a class is not declared either with sharing or without sharing, then by default, such a class is executed in system mode, i.e. without sharing mode; and current sharing rules remain in effect- which means that if any other class that has sharing enforced, calls such a non-specified-sharing class, then the called or non-specified-sharing class is executed in “with sharing” mode.
  • If class B extends class A, then all code in class B inherits the same sharing settings that class A . However, class B’s inner classes do not inherit class B’s sharing settings.
  • If a class is not declared either with sharing or without sharing, then by default, such a class is executed in system mode, i.e. without sharing mode; and current sharing rules remain in effect- which means that if any other class that has sharing enforced, calls such a non-specified-sharing class, then the called or non-specified-sharing class is executed in “with sharing” mode.
    • But If you run a class that has no sharing in Execute Anonymous, or in Chatter, it is treated as “with sharing.”
  • If a with sharing class calls a without sharing class, then the called method(s) will be executed in the mode of the class in which they were defined, in this case, the called method(s) will execute in without sharing mode.

 

  • public with sharing class A {}
  • public without sharing class B{}
  • public class C{}  // Class C is a non-specified-sharing class > without sharing
  1. class B extends A
    1. class B’s code now executes in class A’s mode, i.e. in “with sharing” mode. As the extended class A mode apply on class B.
  2. class B calls class A
    1. called code will now be executed in the mode of the class in which it was defined, in this case, in class A’s mode, i.e. in “with sharing” mode.
  3. class C calls class A
    1. called method’s code in class A will execute in class A’s mode, i.e. in “with sharing” mode.
  4. class C extends class A
    1. code in class C now executes in the parent class A’s mode, i.e. in “with sharing” mode.
  5. class A calls C
    1.  code in class C is executed in class C’s mode, i.e. in “without sharing” mode although it’s sharing settings are unspecified in the class’ declaration.
    2. Class C has no keyword so the caller class i.e class A decides the behaviour and hence sharing rules apply
  6. class A extends C
    1. class A’s code now executes in the parent class C’s mode, i.e. in “without sharing” mode.
    2. If A is “public with sharing class A extends C”, then it is “with sharing,”

NOTE – We can’t enforce field level security(FLS) or profile permissions with “with sharing,” as this would make code much more difficult to debug because of failures.

If you do not specify “with sharing” or “without sharing” for the inner class, it behaves according to the calling class mode, or “without sharing” if called directly.

Hello World ! LWC

Follow this trialhead module –

https://trailhead.salesforce.com/content/learn/projects/quick-start-lightning-web-components

2. Install CLI (Command Line Interface). Download from this link –

macOS https://sfdc.co/sfdx_cli_osx
Windows 32-bit https://sfdc.co/sfdx_cli_win
Windows 64-bit https://sfdc.co/sfdx_cli_win64

2. To check CLI install proper, go to VS Code terminal > write sfdx enter

You can get the output –

Usage: sfdx COMMAND [command-specific-options]
Help topics, type “sfdx help TOPIC” for more details:
sfdx force # tools for the salesforce developer
sfdx plugins # manage plugins
sfdx update # update sfdx-cli

Create a Salesforce DX Project
  1. In Visual Studio code, open the Command Palette by pressing Ctrl+Shift+P on Windows or Cmd+Shift+P on macOS.
  2. Type SFDX.
  3. Select SFDX: Create Project.
  4. Enter HelloWorldLightningWebComponent as the project name.
  5. Press Enter.
  6. Select a folder to store the project.
  7. Click Create Project. You should see something like this as your base setup.
Create a Lightning Web Component
  1. In Visual Studio code, open the Command Palette by pressing Ctrl+Shift+P on Windows or Cmd+Shift+P on macOS.
  2. Type SFDX.
  3. Select SFDX: Create Lightning Web Component.
  4. Press Enter to accept the default force-app/main/default/lwc.
  5. Enter helloWorld for the name of the new component.
  6. Press Enter.
  7. View the newly created files in Visual Studio Code.
  8. In the HTML file, helloWorld.html, copy and paste the following code.
<template>
<lightning-card title="HelloWorld" icon-name="custom:custom14">
<div class="slds-m-around_medium">
<p>Hello, {greeting}!</p>
<lightning-input label="Name" value={greeting} onchange={changeHandler}></lightning-input>
</div>
</lightning-card>
</template>

9. In the JavaScript file, helloWorld.js, copy and paste the following code.

import { LightningElement, track } from 'lwc';
export default class HelloWorld extends LightningElement {
    @track greeting = 'World';
    changeHandler(event) {
        this.greeting = event.target.value;
    }
}

10. In the XML file helloWorld.js-meta.xml, copy and paste the following code.

<?xml version="1.0" encoding="UTF-8"?>
<LightningComponentBundle xmlns="http://soap.sforce.com/2006/04/metadata" fqn="helloWorld">
  <apiVersion>45.0</apiVersion>
  <isExposed>true</isExposed>
  <targets>
    <target>lightning__AppPage</target>
    <target>lightning__RecordPage</target>
    <target>lightning__HomePage</target>
  </targets>
</LightningComponentBundle>

11. Deploy the code to your org.

With the default folder right-clicked, SFDX: Deploy Source to Org is selected in the options list.

12. Now the new LWC will be available in org. Edit the home page

Capture (2)

If you are deploying will get error –

Error: read ECONNRESET
Run below commands in terminals of VS Code –
set https-proxy https://username:brosalesforce@gmail.com:8080
set proxy https://username:brosalesforce@gmail.com:8080
set sslVerify false
set strict-ssl false

Using Lightning Component in Communities

You can use a custom lightning component in your community, you can drag and drop to add the component to you community page in Community Builder

To appear in Community Builder, a component must implement the  interface forceCommunity:availableForAllPageTypes

<aura:component implements="forceCommunity:availableForAllPageTypes" access="global">
    <aura:attribute name="greeting" type="String" default="Hello" access="global" />
    <aura:attribute name="subject" type="String" default="World" access="global" />
 {!v.greeting}, {!v.subject}
</aura:component>

Mark your resources, such as a component, with access=”global” to make the resource usable outside of your own org.

NOTE – When you add custom components to your community, they can bypass the object- and field-level security (FLS) you set for the guest user profile. Lightning components don’t automatically enforce CRUD and FLS when referencing objects or retrieving the objects from an Apex controller. This means that the framework continues to display records and fields for which users don’t have CRUD permissions and FLS visibility. You must manually enforce CRUD and FLS in your Apex controllers.

Cacheable apex method [Winter-19]

You can mark an Apex method as storable (cacheable) instead of using setStorable() on every JavaScript action that calls the Apex method to centralize your caching notation for a method in the Apex class.

This change applies to orgs with Lightning components in Lightning Experience, Salesforce Classic, and all versions of the Salesforce app.

Marking a method as storable improves your component’s performance by quickly showing cached data from client-side storage without waiting for a server trip. If the cached data is stale, the framework retrieves the latest data from the server. Caching is especially beneficial for users on high-latency, slow, or unreliable connections, such as 3G networks.

Prior to Winter ’19, to cache data returned from an Apex method, you had to call setStorable() in JavaScript code on every action that called the Apex method. Now you can mark the Apex method as storable (cacheable) and get rid of any setStorable() calls in JavaScript code.

To cache data returned from an Apex method for any component with an API version of 44.0 or later, annotate the Apex method with @AuraEnabled(cacheable=true). For example:

@AuraEnabled(cacheable=true)
public static Account getAccount(Id accountId) {
    // your code here
}

To update an existing component to API version 44.0, remove setStorable() calls in JavaScript code. Annotate the Apex method with @AuraEnabled(cacheable=true) instead of @AuraEnabled, or you get an error response for the action.

Loading a Record using LDS

To load record using LDS is by including force:recordData in your component while specifying the recordId, mode and layoutType or fields attribute.

In the force:recordData tag, specify the ID of the record to be loaded, a list of fields, and the attribute to which to assign the loaded record. force:recordData must specify the following.

  • The ID of the record to load
  • Which component attribute to assign the loaded record
  • A list of fields to load

You can explicitly specify a list of fields to load with the fields attribute. For example, fields=”Name,BillingCity,BillingState”.

or, you can specify a layout using the layoutType attribute. All fields on that layout are loaded for the record. Layouts are typically modified by administrators, so layoutType isn’t as flexible as fields when you want to request specific fields. Loading record data using layoutType allows your component to adapt to layout definitions. Valid values for layoutType are FULL and COMPACT.

 








Lightning Data Service(LDS) in Salesforce

Lightning Data Service(LDS) will work as data layer in Lightning. It is like Standard Controller in Visualforce page, providing access to data without querying. Use LDS to load, create, edit or delete a record in your component without Apex code. LDS handles sharing rules and field-level security for you.

Without LDS each component make independent server call to perform CRUD operation on a record, even all components are pulling same record data. This independent server calls can also lead to an inconsistencies, lead to situations where a server call refreshes one component leaving other components out of date.

LDS identifies and eliminates requests that invoke the same record data, sending a single shared data request that update all relevant components. Not only does this eliminate inconsistent data between components, it also provide a way to cache the data to work offline in case the user get disconnected and sync the data once connection is restored

So LDS provides reusable Aura components that –

  1. Minimize XMLHttpRequests(XHRs)
  2. Fetch record once, reduce network transfer, app server load and database server load.
  3. Cache record data on the client, separate from component metadata.
  4. Shared record data across components.
  5. Enable progressive record loading, caching and merging more fields and layouts into the cache.
  6. Enable proactive Cache population.
  7. Promote consistency by using only one instance of the record data across multiple components.
  8. Create notification when record data changes.

force:recordData

To use LDS , you have to include force:recordData in your component.

To load record in client side, you have to add force:recordData tag to your component and set your recordId, mode and layout or fields attributes.

  • recordId – specifies the record to load. Record can’t be loaded without a recordId.
  • mode – can be set to either EDIT or VIEW which determines the behaviour of notifications and what operations are available to perform with the record.
  • layout – specifies the layout(FULL or COMPACT) used to display the record, which determines what fields are included. Using layoutType allows your component to adapt to layout definitions.
  • fields – specifies which fields in the record to query.

The fields or layoutType attribute must be provided to load a record’s field data. Since admins usually modify layouts, using fields is a more flexible way to get the fields you need.

The force:recordData tag also supports a set of target* attributes, which are attributes that force:recordData populates itself. The target* attributes can be used to allow access from the UI.

  • targetRecord is populated with the loaded record
  • targetFields is populated with the simplified view of the loaded record
  • targetError is populated with any errors

< force:recordData aura:id="forceRecordCmp"
< !-- aura:id is required to reference the component in your Javascript controller -- >
recordId="{!v.recordId}"
layoutType="{!v.layout}"
fields="{!v.fieldsToQuery}"
mode="VIEW"
targetRecord="{!v.record}"
targetFields="{!v.simpleRecord}"
targetError="{!v.error}"
/ >

Aura.Action Vs aura:registerEvent in Lightning

Instead of an Aura.Action attribute, you could use  to register an onclick event in the child component. You’d have to define the event and create an action in the child’s controller to fire the event. This event-based approach requires a few extra steps but it’s more in line with standard practices for communicating between components.

Action has some known limitations:

  • It is discouraged to use component.set() with the Aura.Action attribute types.
  • It is discouraged to use $A.enqueueAction() in the child component to enqueue the action passed to the Aura.Action attribute.

If you want to build some more dynamic, or to overcome these limitations, the recommended way would be to fire an event from the child component that is handled by the parent component to perform the required action using aura:registerEvent

AuraActionEvent.evt

< aura:event type="COMPONENT" description="Event to Execute Aura.Action" / >
AuraActionChild.cmp
<aura:component  >
    <aura:registerEvent name="customEvent" type="c:AuraActionEvent" />

    <lightning:button label="Aura Action Event" onclick="{!c.fireAuraAction}"/>
</aura:component>

AuraActionChildController.js


({
    fireAuraAction : function(component, event, helper) {
        var compEvent = component.getEvent("customEvent");
        compEvent.fire();
    }
})

AuraActionParent.cmp


<aura:component >
<aura:handler name="customEvent" event="c:AuraActionEvent" action="{!c.handleComponentEvent}"/>

<c:AuraActionChild aura:id="auraActionButton" />
</aura:component>

AuraActionParentController.js


({
    handleComponentEvent : function(component, event, helper).  {
        var buttonClicked = event.getSource().getLocalId();
        if(buttonClicked == 'auraActionButton')
            alert('Aura Action using Event Concept');
        }
})

As you can see in the example, in this way you will need to write some extra code, however, we have a finer degree of control, as we could for example add other event handlers dynamically or pass more information to the parent using event attributes. Also,  we are more inline with standard practices for components communication.

Aura.Action attributes in Lightning


<apex:component >
    <aura:attribute name="onClick" type="Aura.Action" >
</apex:component >

An Aura.Action is a reference to an action in the framework. If a child component has an Aura.Action attributes, a parent component can pass in an action handler when it instantiates the child component in its.

Aura.Action is used pass a controller action from a parent component to child component that it contains and is used for on* handlers like onClick.

Limitations for Aura.Action attributes –

Although Aura.Action works for passing an action handler to a child component, its recommend registering an event in the child component and firing the event in the child’s controller instead.Then, handle the event in the parent component.

  • Don’t use cmp.set() in JavaScript code to reset an attribute of  type=”Aura.Action” after it’s previously been set. Doing so generates an error.
  • Don’t use $A.enqueueAction() in the child component to enqueue the action passed to the Aura.Action attribute.

Demonstration –

  1. Create a child component, which contain the Aura.Action attribute type.
  2. Child component also have a on* action handler like onClick.
  3. aura:attribute name should be same as expression inside the onclick action

childAction.cmp –


<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global" >
    <aura:attribute name="childAction" type="Aura.Action"/>

    <lightning:button label="Execute Aura.Action" onclick="{!v.childAction}"/>
</aura:component >

  1. Embed the child component in Parent and pass the Aura.Action attribute name here to call the ParentComponent controller.
  2. Define the Controller of the parent component.

parentAction.cmp


<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId" access="global">
     <c:Child childAction="{!c.parentAction}"/ >
</aura:component>

parentActionController.js


({
 parentAction : function(component, event, helper) {
    alert('Aura.Action Parent Compoentnt');
}
})

AuraAction.app


<aura:application extends="force:slds" >
    <c:parentAction/>
</aura:application >

 Instead of an Aura.Action attribute, you could use <aura:registerEvent> to register an onclick event in the child component. You’d have to define the event and create an action in the child’s controller to fire the event. This event-based approach requires a few extra steps but it’s more in line with standard practices for communicating between components.

 Next1 Click here for using aura:registerEvent over Aura.Action attribute

Apex Controller overview in Lightning

Apex controller with method annotated with @AuraEnabled only will be exposed to use in Lightning component.

public with sharing class SimpleServerSideController {

    //Use @AuraEnabled to enable client- and server-side access to the method
    @AuraEnabled
    public static String serverEcho(String firstName) {
        return ('Hello from the server, ' + firstName);
    }
}

Apex controller must follow these requirements.

  1. Methods must be static and marked public or global. Non-static methods aren’t supported.
  2. If a method returns an object, instance methods that retrieve the value of the object’s instance field must be public.
  3. Use unique names for client-side and server-side actions in a component. A JavaScript function (client-side action) with the same name as an Apex method (server-side action ) can lead to hard-to-debug issues. In debug mode, the framework logs a browser console warning about the clashing client-side and server-side action names.

@AuraEnabled Annotaion – The AuraEnabled annotation enables Lightning components to access Apex methods and properties.

  1. Use @AuraEnabled on Apex class static methods to make them accessible as remote controller actions in your Lightning components.
  2. Use @AuraEnabled on Apex instance methods and properties to make them serializable when an instance of the class is returned as data from a server-side action.

Caching Method Results –

To improve runtime performance, set @AuraEnabled(cacheable=true) to cache the method results on the client. To setcacheable=true, a method must only get data, it can’t mutate data.

Marking a method as storable (cacheable) improves your component’s performance by quickly showing cached data from client-side storage without waiting for a server trip. If the cached data is stale, the framework retrieves the latest data from the server. Caching is especially beneficial for users on high latency, slow, or unreliable connections such as 3G networks.

To cache data returned from an Apex method for any component with an API version of 44.0 or higher, you must annotate the Apex method  with  @AuraEnabled(cacheable=true). For example:

@AuraEnabled(cacheable=true)
public static Account getAccount(Id accountId) {
    // your code here
}

Prior to API version 44.0, to cache data returned from an Apex method, you had to call setStorable() in JavaScript code on every action that called the Apex method. For API version of 44.0 or higher, you must mark the Apex method as storable (cacheable) and you can get rid of any setStorable() calls in JavaScript code. The Apex annotation approach is better because it centralizes your caching notation for a method in the Apex class.

Returning Data from Server side Controller  Next1