Thursday, April 5, 2018

The LockerService For Lightning Components

The LockerService For Lightning Components

This is an introductory post about a new security feature for Lightning Components called "LockerService (LS)". LockerService uses various technologies and techniques to make Lightning Components secure. It will be available as a critical update as part of Summer '16 and will be enforced in Winter '17

DOM Manipulation Libraries
JavaScript has come a long way in recent years. Many DOM manipulation utilities we couldn’t live without in libraries like jQuery are now standard in the language. Modern frameworks like the Lightning Component Framework also provide abstractions that make jQuery less relevant. For example, let’s say you have to set the value of a score input field to 100.

Using jQuery, you would:

Assign a unique id to the input element
Use a jQuery selector to find the input element in the DOM
Assign the value to that DOM element

====================
// Markup:

<input id="score" />

// Code:

var scoreElement = $("#score");

scoreElement.val(100);
======================


Using the Lightning Component Framework, you would:

Declare a score attribute
Bind the input field to the score attribute
Set the value of the score attribute: the bound input field will automatically display the new value.
view sourceprint?

===================
// Markup:

<aura: attribute name="score" type="integer" />

<input value="{!v.score}" />

// Code:
component.set("v.score", 100);
====================

At a high level, LockerService uses various technologies and techniques that are intended to do the following:
Prevent:
  • Components from causing XSS and similar security issues
  • Components from reading other component’s rendered data without any restrictions
  • Components from calling undocumented/private APIs
Enable:
  • Cool new features like client-side API versioning similar to REST API versioning*
  • Faster security review
  • Better and more secure JS development practices
  • Running 3rd party JS frameworks like React, Angular and so on*
  • Easily adding or removing new security features and policies
*Some of the features will have limitations and will come during or after Winter 2017 #safeHarbor

Availability

In Winter ’17, LockerService can be activated or deactivated in your org. Note: To ensure compatibility with LockerService before the Summer ’17 release, test your Lightning components in a sandbox or a Developer Edition org.
In Spring ’17, the existing LockerService critical update will tighten Content Security Policy (CSP) to eliminate the possibility of cross-site scripting attacks. These CSP changes will only be enforced in sandbox and Developer Edition orgs. If you have a sandbox or Developer Edition org with the LockerService critical update activated, the stricter CSP will apply when Spring ’17 rolls out. If you deactivate the LockerService critical update before the Spring ’17 release, the stricter CSP won’t be applied.
In Summer ’17, LockerService will be auto-activated for all orgs with no option to disable.

Components Installed from Managed Packages

To control whether LockerService is enforced for components installed from a managed package:
  1. From Setup, enter Lightning Components in the Quick Find box, and then select Lightning Components.
  2. Select the Enable LockerService for Managed Packages checkbox to enforce LockerService for components
    installed from a managed package.
    Note: The checkbox is only visible when the critical update is activated.
If you deselect the Enable LockerService for Managed Packages checkbox, LockerService is not enforced for
components installed from a managed package. Components that you create in your org still run with enforcement of LockerService restrictions.

Under The Hood

To understand the technology under the hood, let’s take an example app.  The below example Lightning app has four components: a button, a Weather component (that internally has a Map sub-component) and a Financecomponent.

Before LockerService

Before LockerService, the DOM tree and JS access for the example lightning app would look like the following image.
In this scenario:
  1. Any JS of any component can call any JS functions of any other component as they are all loaded in the DOM
  2. Any JS can also call any undocumented/private Lightning APIs
  3. Any JS can access real DOM and get rendered data from other components.
  4. Components that are not security reviewed can potentially have security issues.

After LockerService

The same lightning app with all the techniques and technologies used in LockerService will look something like the following image.

With the LockerService turned ON

  1. Salesforce-authored components and JS run in “System mode” (similar to the Operating System’s system mode) and have full access to everything.
  2. Custom components run in “User mode” and don’t have access to the real Document or real “window” object.
  3. Custom components instead gets a custom DOM (“secureDOM”), custom Window and so on.
  4. Custom components can access other components’ DOM as long as they are in the same namespace but won’t be able to access other components’ DOM that are in different namespace. For example, JS in the “Weather” component can access DOM of “Map” component, but won’t be able to access DOM elements of the “Finance” or “button” component.
  5. In addition, custom components will only be able to access public and documented Lightning JS APIs and won’t be able to access Lightning framework’s “private” APIs.
  6. “Use strict” and CSP are enabled and enforced for security of all components.
In Spring ’17, LockerService tightens CSP to eliminate the possibility of cross-site scripting attacks by disallowing the unsafe-inline and unsafe-eval keywords for inline scripts (script-src). Eliminate use of these keywords in your code, and update third-party libraries to modern versions that don’t depend on unsafe-inline or unsafe-eval. These CSP changes are only enforced in sandbox and Developer Edition orgs.
Note:
  • When LockerService is activated in sandbox or Developer Edition orgs, you can’t edit rich-text fields and the fields are grayed out. We’re working on removing that limitation in a future release.
  • IE11 doesn’t support CSP, so we recommend using other supported browsers for enhanced security.

Additional Resources

  1. Lighting Components Developer Guide – More details about LockerService and how it works in Lighting components.
  2. Lightning LockerService Video – Get detailed guidance from Salesforce staff.
  3. Salesforce Lightning CLI – Use the code review tool to check your code for LockerService compatibility.
  4. LockerService API Viewer – Check the DOM APIs exposed by LockerService

Code Example

In the below picture, we have a simple ui:button that uses a div (that’s in “c” namespace) for it’s label. Notice how the console.log differs for window, document and div when LockerService is turned ON. Also notice that when the custom component’s JS tries to “walk the DOM” by doing div.parentNode.innerHTML to get the button’s innerHTML, it gets “undefined” because button is in a different “ui” namespace.

No comments:

Post a Comment