If you’re trying to access the camera and microphone with
getUserMedia() in a cross origin iframe on a recent version of Chrome, by default it will fail.
We’ve encountered this situation several times as users of the Pipe audio and video recording platform tried to embed Pipe in Wix websites or Google Site which use iframes to embed external HTML and JS code.
The cause stems from a series of security & privacy changes that were made to Chrome in 2017 and 2018:
- Chrome 60 introduced Feature Policy which gave devs a way to control usage of sensitive features inside their websites
- Chrome 64 blocked camera and microphone access in cross origin iframes by default and required Feature Policy to grant access
Feature Policy allows you to control what sensitive APIs and features are available to the website in the browser. You can control whether or not these features are available through the
Feature-Policy HTTP header OR by using the
allow attribute in HTML iframes.
Sensitive features now include:
- accessing the
- accessing the accelerometer or USB devices
Below, we will be focusing on the
allow attribute in iframes as it relates to camera and microphone access through
getUserMedia(), for a more detailed overview of Feature Policy check out this excellent introduction article.
allow attribute of the
iframe HTML element enables you to control the sensitive features available within that iframe. The syntax is quite simple, it has the following form:
<iframe src="" allow="feature_name allow_list"></iframe>
You can specify allow lists for more than one feature by using semicolons:
<iframe src="" allow="feature_name allow_list;feature_name allow_list"></iframe>
Thus, to allow camera and microphone access in a cross origin iframe you need to add the following
allow attribute to your iframe:
<!--Allow camera and microphone access within the context of this iframe--> <iframe src="https://example.com" allow="camera;microphone"></iframe>
which is equivalent to:
<!--Allow camera and microphone access within the context of this iframe--> <iframe src="https://example.com" allow="camera *;microphone *"></iframe>
The above will allow any page, hosted on any domain to request access to the camera and microphone of the user while loaded through the above iframe.
To tighten things up you can be more granular about which domains have access to those features as the
allow_list can have any of the following values:
*: used above, the feature is allowed in top-level browsing contexts and in nested contexts (iframes)
'self': the feature is allowed in top-level browsing contexts and same-origin nested contexts. The feature is not allowed in cross-origin documents for nested browsing contexts.
'none': The feature is not allowed at all in top-level and nested browsing contexts.
<origin(s)>: The feature is allowed in specific origin(s), for example
Without the iframe
allow attribute above, camera and microphone access won't be allowed in cross origin iframes in browsers that have Feature Policy implemented (see browser support below). If you're listening for
getUserMedia() errors you'll get a
NotAllowedError because requests blocked by Feature Policy fail in a similar way as it would if a user had denied a permission prompt.
This is the reason why our own Pipe recorder cannot get camera and microphone access in Chrome when embedded in a website that is built with Wix. Wix adds any embedded content through a cross origin iframe which does not have the required
Until the release of Feature Policy, the camera and microphone API was already controlled by an older attribute named
allowusermedia, but this attribute is now deprecated and you should use the new
allow attribute with the correct values instead, in order to control the access.
If both the old attribute and the new attributes are specified the more restrictive policy will take precedence (in Chrome). For example, the following iframe would not be allowed to request access to the camera, because
allow="camera 'none'" is more restrictive than
<iframe allowusermedia allow="camera 'none'" src="https://example.com"></iframe>
It is very important to remember that iframes inherit the feature policy settings of their parent page, this means that if both the page and iframe specify a feature policy list, the more restrictive policy will apply. So, if features in your iframe still do not work, make sure there's not a more restrictive policy imposed through HTTP headers on the parent page.
Chrome 60 introduced Feature Policy support for both the HTTP header and the
allow attribute and from our tests, other Chromium based browsers also support the feature like Opera and the new Edge based on Chromium.
For a full list of browsers that support the feature see caniuse.com.
frame.featurePolicy for iframes or
document.featurePolicy for the page/browser/main document. More details can be found here.
- Introduction to Feature Policy
- Features disabled by default in Chrome for Cross-Origin iframes. These features will have to be specifically enabled in iframes through the Feature Policy.
- Feature Policy spec