Security News
RubyGems.org Adds New Maintainer Role
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
A Cross Frame Container that handles securely embedding web content into a 3rd party domain
This project handles securely embedding web content into a 3rd party domain. Out of the box, it provides several features:
Include xfc.js
in your project.
Ensure process.env.NODE_ENV
is set correctly in the build enviornment. Logging is only enabled in non-production environments. The environment can be set in webpack using the DefinePlugin
// webpack.config.js
const webpack = require('webpack');
module.exports = {
/*...*/
plugins:[
new webpack.DefinePlugin({
'process.env.NODE_ENV': JSON.stringify('production')
})
]
};
The consumer is the application which is embedding the 3rd party applications within it.
// Create an app broker to manage embedded apps
XFC.Consumer.init()
// Mount the app at this URL and append its frame to the body element.
var frame = XFC.Consumer.mount(document.body, 'http://localprovider.com:8080/example/provider.html')
If the embedded app does not know which domain to trust, it may require secret authorization.
var frame = XFC.Consumer.mount(document.body, 'http://localprovider.com:8080/example/provider_b.html', {secret: 'abc123'})
To remove and clean up a mounted app, simply call unmount
method.
frame.unmount()
To load a new page within the existing frame, simply call load
method with the new URL.
frame.load(newURL)
By default, the height of iframe will automatically resize based on the height of the embedded content. This behavior can be changed by passing an extra option (resizeConfig
) into mount
method.
// Pass scrolling as true to resizeConfig to make scrollbar show up.
XFC.Consumer.mount(document.body, 'http://localprovider.com:8080/example/provider.html', { resizeConfig: { scrolling: true } });
resizeConfig
is an object that accepts the following attributes.
name | type | default value | usage |
---|---|---|---|
scrolling | boolean | false | When set to be true , scrollbar may show up on iframe. |
autoResizeWidth | boolean | false | When set to be true , iframe will autoresize on width instead of on height |
fixedHeight | string | empty string | If specified (e.g. '200px'), the height will stay at the specified value. NOTE: setting this attribute will turn off autoresizing. |
fixedWidth | string | empty string | If specified (e.g. '400px'), the width of iframe will stay at the specified value. NOTE: setting this attribute will turn off autoresizing. |
heightCalculationMethod | string | 'bodyOffset' | Accepted values:'bodyOffset' - use document.body.offsetHeight 'bodyScroll' - use document.body.scrollHeight 'documentElementOffset' - use document.documentElement.offsetHeight 'documentElementScroll' - use document.documentElement.scrollHeight 'max' - max of all of above options.'min' - min of all of above options. |
widthCalculationMethod | string | 'scroll' | Accepted values:'bodyOffset' - use document.body.offsetWidth 'bodyScroll' - use document.body.scrollWidth 'documentElementOffset' - use document.documentElement.offsetWidth 'documentElementScroll' - use document.documentElement.scrollWidth 'scroll' - max of bodyScroll and documentElementScroll 'max' - max of all of above options.'min' - min of all of above options. |
customCalculationMethod | function | null | When specified, XFC will use the given method to update iframe's size when necessary (e.g. dom changes, window resized, etc.) NOTE: context this is provided as iframe to this method, so in the method you can access the iframe by accessing this |
targetSelectors | string | null | When the embedded page contains elements styled with position: absolute , the iframe resizing logic won't calculate the height of the embedded page correctly because those elements are removed from normal document flow.In this case, targetSelectors can be used to specify those absolute positioned elements so that they will be taken into consideration when calculating the height of the embedded page. Multiple selectors may be specified by separating them using commas. If not specified, normal resizing logic will be used. NOTE: this attribute can be also specified from Provider's side, e.g. XFC.Provider.init({targetSelectors: '#target'}) |
Sometimes, it's useful for developers to add more attributes onto mounted iframes. A common use case, for instance, is adding allow
attribute to <iframe>
tag for cross-origin iframes in Chrome 64+ (See reference here). In those cases, we can pass an extra option called iframeAttrs
into mount
method as follows.
XFC.Consumer.mount(document.body, 'http://localprovider.com:8080/example/provider.html', { iframeAttrs: { allow: 'geolocation; camera' }});
Here iframeAttrs
is an object that contains entries, each of them being an entry of attribute's name and value.
Application lifecycles go through 3 stages as they load:
mounted
The application frame has been appended to the DOM and is loading the remote application site.launched
The application frame has loaded and the embedded application has begun authorization sequence. At this time the app is loaded, but is hidden to prevent clickjacking.authorized
The application has approved authorization and is now visible.unload
The application frame is about to unload due to redirect or other causes.These statuses are communicated to the consumer application environment in 2 ways.
data-status
attribute on the embedded iFrame wrapperThe cross frame container data-status
attribute can be used as a styling hook to hide containers until they have authorized
/* Hide mounted apps that haven't loaded or authorized */
.xfc[data-status='mounted'],
.xfc[data-status='launched'] {
display: none;
}
/* Reveal the app once its been authorized */
.xfc[data-status='authorized'] {
display: block;
}
Event listeners can be set up to listen for lifecycle changes to a cross frame container. The target of the event will be the embedded application frame which is an instance of EventEmitter.
// Listen for a container to trigger a mounted event
frame.on('xfc.mounted', function() {
console.log('mounted', frame.wrapper);
})
// Listen for a container to trigger a launched event
frame.on('xfc.launched', function() {
console.log('launched', frame.wrapper);
})
// Listen for a container to trigger an authorized event
frame.on('xfc.authorized', function(detail) {
console.log('authorized', detail);
})
// Listen for a container to trigger an unload event
frame.on('xfc.unload', function(detail) {
console.log('unloading', detail);
})
A provider application may request to launch another provider app fullscreen.
// Simulate opening a fullscreen link.
// In real implementation this would invoke a modal.
frame.on('xfc.fullscreen', function(url) {
window.open(url)
})
Each frame of the consumer can send custom events to its embedded provider through its trigger method.
// The following code will emit 'fetchDetail' event with an object containing additional info (e.g. 'id')
// onto the provider embedded in the frame
frame.trigger('fetchDetail', {id: 10});
The provider is the application which is embedded by the consumer.
// Only load within http://localconsumer.com:8080 origins
XFC.Provider.init({
acls: ['http://localconsumer.com:8080']
})
If the app is using secret authorization, it may pass in a secret and wildcard for authorization.
// Don't know which origin to trust, trust all origins that know the secret.
XFC.Provider.init({
acls: ['*'],
secret: 'abc123'
})
If the app is using a custom secret callback function for authorization, it may pass in a callback function for validation of the secret.
// Don't know which origin to trust, trust all origins that know the secret.
XFC.Provider.init({
acls: ['*'],
secret: function(secret) {
return Promise.resolve('Success');
}
})
If the app is using an alternate form a security and does require XFC to provide clickjacking support, a wildcard with no secret may be passed. Under these conditions, XFC will not hide the content and the consumer will automatically be authorized.
XFC.Provider.init({
acls: ['*']
})
An application may request to launch a pagelet fullscreen within the consumer application.
XFC.Provider.init({ acls: ['http://localconsumer.com:8080'] })
XFC.Provider.fullscreen('http://localconsumer.com:8080/workflow')
Provider can send custom events to the frame where it's embedded through trigger method.
// The following code will emit 'ProviderURL' event with an additional object containing URL info
// onto the frame where the provider is embedded
// NOTE: trigger method can only be called after initializing provider.
XFC.Provider.trigger('ProviderURL', {url: window.location.href});
Provider can send http errors to its frame by calling httpError method. This method will emit an 'xfc.provider.httpError' event onto the frame where the provider is embedded.
// httpError accepts a parameter that is an object containing message's detail information.
XFC.Provider.httpError({code: 500, message: 'Internal Server Error'});
All supported browsers are defined in here with browserslist queries.
Add localconsumer.com to/etc/hosts
.
Add localprovider.com to/etc/hosts
.
Install dependencies and start the server.
npm install
npm run dev
Navigate to http://localconsumer.com:8080/example
FAQs
A Cross Frame Container that handles securely embedding web content into a 3rd party domain
We found that xfc demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.
Security News
Node.js will be enforcing stricter semver-major PR policies a month before major releases to enhance stability and ensure reliable release candidates.
Security News
Research
Socket's threat research team has detected five malicious npm packages targeting Roblox developers, deploying malware to steal credentials and personal data.