Secure your site with Feature-Policy header

This is a post from of my experience in debugging an issue which led me to understand the HTTP header Feature-Policy. In this post, I’ll explain the issue my team faced, what is Feature-Policy and how to secure your site with Feature-Policy header. Feature-Policy has now been renamed to Permissions-Policy. But since my experience was with Feature-Policy, I’m going to use it instead of Permissions-Policy.

I’ll start with the story. My team was working on a WebRTC project using AWS Chime. The requirement was to develop a video conference app. We deployed the application in an EC2 instance behind a NGINX proxy. Our client configured both the servers for us. It was time for us to show a demo to our clients. We deployed it in the QA environment and performed a sanity check. Guess what, though everything was fine in our local environment, things weren’t the same in the QA environment. It was the typical “Hey.. it worked in my local” scenario.

What was the issue?

For better context, read my previous post about the getUserMedia API. When invoking this API, the browser requests permission from the user if it doesn’t have permission to access media devices. In our case, the browser didn’t prompt for permission but behaved as if the user denied it. The below images show the expected and actual behaviors.

Expected behavior

Page requests permission

Actual behavior

If you are working in a WebRTC project and if your browser directly denies permission to access media devices without even requesting for permissions, this post might help you.

Debugging the issue

While debugging with chrome debugger tool, we took a look under the network tab. We noticed a response header Feature-Policy added to the JavaScript that has the getUserMedia API logic. These turned my focus to Feature-Policy.

Feature-Policy none in response header

Here, all the features, including camera and microphone were also set to none. This restricted the browser from accessing the media devices.

Where did the JS file get response headers from?

The static files are hosted in a server, in my case it was an AWS EC2 server. On loading the page, the browser downloads these files to load the page. Download is done by a simple GET request to the server. In our case, the downloaded file had the response headers.

What is Feature-Policy?

Feature Policy allows web developers to selectively enable, disable, and modify the behavior of certain APIs and web features in the browser.

https://developers.google.com/web/updates/2018/06/feature-policy

The above is my favorite definition of Feature-Policy.

What is a feature?

Feature refers to the features provided by the browser. If you have read my previous post about the getUserMedia API, I wrote a little about it. The browser provides features like camera, microphone, picture-in-picture, etc., and functions to access these features. You can find the list of features available here.

What is a policy?

As per Google’s documentation, Policies are a contract between developer and browser. It tells your browser whether to allow an API or not. For example, if you add a policy to deny access to camera, this policy will modify the browser’s default behavior by restricting the access to camera. The syntax to add a policy is as given below.

Feature-Policy: <feature> <allow list>
  • *: The feature is allowed in top-level browsing contexts and in nested browsing contexts (iframes).
  • 'self': The feature is allowed in top-level browsing contexts and same-origin nested browsing contexts. It is disallowed in cross-origin documents in nested browsing contexts.
  • 'none': The feature is disallowed in top-level browsing contexts and disallowed in nested browsing contexts.
  • <origin(s)>: specific origins to enable the policy for (e.g. https://www.thegeeksclan.com).

Why use Feature-Policy?

To tighten your site’s security

Using Feature-Policy, we can tighten the site’s security by preventing an iFrame or any third party from accessing your browser’s features such as media devices, geolocation, etc.

Have more control

Feature-Policy gives more control to the developers in deciding which feature should be allowed. The developer can also set the visibility. For example, you can to grant access to your camera to specific list of sites.

Track number of users using the features

With the Report only mode, you can track the number of users who use a browser feature.

How to secure your site with Feature-Policy?

You can configure Feature-Policy in your server. In my case, it was NGINX server and I’ll be explaining how to configure the header in NGINX. Open the NGINX configuration file that has the server configuration. Add the header Feature-Policy using the add_header mod. Below is an example.

add_header Feature-Policy "microphone none;camera none;geolocation none;midi none;notifications none;push none;sync-xhr none;magnetometer none;gyroscope none;speaker none;vibrate none;fullscreen none;payment none;";

To control which feature should be allowed, you can add the configuration in the config file. This is what we did to fix our issue. In our case, all the features had none configured. We fixed it by updating the header configured in NGINX configuration.

add_header Feature-Policy "microphone 'self' <URL>;camera 'self' <URL>;geolocation none;midi none;notifications none;push none;sync-xhr none;magnetometer none;gyroscope none;speaker none;vibrate none;fullscreen none;payment none;";

The Reporting API

Using the Reporting API, we can report a Feature-Policy violation. When a site page violates a Feature-Policy, it can be reported to a server or be handled with in a page. Check this page out for more information on how to use the Reporting API.

Report only mode

Adding Feature-Policy header will restrict the page from accessing the feature (when set to none). Adding the Report API to it will trigger a request to the configured Report URL on violations. But what if you do not want to restrict the page from accessing the feature and want to report it anyway? It is possible by using the Feature-Policy-Report-Only header instead of Feature-Policy header. Below is an example.

add_header Feature-Policy-Report-Only "microphone none;camera none;geolocation none;";

This will not restrict the user from accessing camera, microphone or geolocation. But will send a report to the configured server.

That’s all about Feature-Policy for now. I’m planning to update this post with more details on the Reporting API in the future. Thanks for reading.

What’s next?

For more information, take a look at our post about getUserMedia API.

Checkout our tutorials here.


I hope this post was helpful 😊. If you find this post informative, support us by sharing this with fellow programmers in your circle 😀.

For any suggestions, improvements, reviews or if you like us to cover a specific topic, please leave a comment.
Follow us on twitter @thegeeksclan and in Facebook.
#TheGeeksClan #DevCommunity

error

Enjoy this blog? Please spread the word :)