By: Hugo van Krimpen
But, to your disappointment, the security review fails because of an insecure implementation of your third-party library. The response is that the third-party library performs DOM manipulation and might therefore modify your environment in unintended or even malicious ways. Or worse: the library might be able to read your data in the LWC and pass it to a remote server.
As of recently, we’ve faced this response from Salesforce more and more: we specifically need to implement our third-party applications in managed packages in a separate container so it will not have access to other Salesforce components. In order to prevent these security issues and pass the security review, they ask to implement the third-party library using
But what is a lightning container? In this blog, we give you a detailed explanation. However, to get a complete understanding, you need to understand Lightning Locker first.
Lightning Locker is an architectural concept that limits how components in one namespace can access components or data in another namespace. Without the Lightning Locker, a developer would be able to access and edit everything on the org. In the worst-case scenario, third-party applications would even be able to read, store and share your data!
Lightning Locker is enabled by default for all components using API version 40 or higher. Components with API version 39 or lower do not implement the Lightning Locker and are therefore less secure and not compliant with the latest Salesforce security standards. A component using an API higher than version 40 that is not Lightning Locker compliant will not function properly or throw errors in your browser's console. It applies to most modern Salesforce functionalities, like aura components, applications, lightning web components and flows.
Want to know which objects are available? See the official documentation.
- A component can only traverse the DOM and access elements created by a component in the same namespace. Accessing the DOM
< c-child-element >is allowed as it is in the same namespace. Accessing the DOM of
< lightning-button >is not allowed, as that component resides in the lightning namespace.
Please see the Salesforce developer documentation for a full list of restrictions.
So how does this relate to a lightning container? A lightning container (< lightning:container >) is an aura component that enforces a static resource to be loaded in a separated Lightning Locker. Anything in this container is guaranteed to be unable to access anything outside the container. Only data specifically passed to the container can be accessed by anything inside it. This way the developer (and in the bigger picture: the end user) is ensured only necessary data is passed to the third-party library, reducing the risk of malicious attacks.
A lightning container takes a static resource and loads it in an iFrame. This static component can be anything: a Visualforce Page, Aura Component, Lightning Web Component, or a website using a third-party library React, AngularJS or D3.
Once the container is loaded, a Salesforce developed module allows for messaging between the aura component and the contents of the container. Using this messaging service, you can pass data to the container or pass data from the container back to your component.
Lightning Container Example
Sending and receiving a message on the aura side is relatively easy.
Sending and receiving messages in the container is a bit harder. Salesforce requires you to download their lightning-container module using node.js and add it to the application. Alternatively, you can create a lightning-container.js file in your container code and add the following code to achieve the same:
Note: LCC.onlineSupport implements more than the two functions described above. E.g. it also contains a function to directly call an AuraEnabled apex class from within the container. For our scenario, we decided not to include these and go with a messaging system instead.
In your application, you can now import the LCM module. E.g. in a LWC resource, simply add the following to your import statements.
import LCM from './lightning-container.js'
And finally register handler functions for the messaging events:
You are now completely set to message back and forth between your aura component and your lightning container. Pass the data you want your container to show using your third-party library and have it handled it in the correct way.
Recap & Discussion
To sum up, Lightning Locker is a great architectural decision to ensure separation of concerns between different components in your application. It ensures that only the data you actually want to pass to a component is accessible to it and only functionality registered as global will be accessible to others. Lightning container is an extra implementation layer around the Lightning Locker. It allows the developer to develop an application separated from Salesforce. Ultimately, this application can be integrated with Salesforce using the messaging service, ensuring the two components can only communicate using whatever has been implemented.
lightning:container is an aura-only component and does not yet exist in the LWC space. Therefore, anyone who actively develops using LWC needs to find a way to implement an aura component in their application and have it react to the already existing LWC source. We had a similar challenge and decided to use a pubsub framework to send messages to the aura component, which in its turn would interact with the application in the
lightning:container. Suboptimal to call it the least, but it is the most secure (and required) method of implementing this.
Still some lingering questions? Don’t hesitate to contact me.
About the author
Hugo van Krimpen has over 4 years experience in the Salesforce consultancy and programming environment. The last 2 years he has been researching new Salesforce grounds working for Appsolutely. He is always looking for the new and next gadget or tool. This team player is helping our customers with finding the right solution.