Controlar os recursos do navegador com a política de permissões

Gerencie como sua página e os iframes de terceiros nela têm acesso aos recursos do navegador.

Kevin K. Lee
Kevin K. Lee

A política de permissões, anteriormente conhecida como política de recursos, permite que o desenvolvedor controle os recursos do navegador disponíveis para uma página, os iframes e sub-recursos dela declarando um conjunto de políticas para o navegador aplicar. Essas políticas são aplicadas a origens fornecidas em uma lista de origens de cabeçalho de resposta. A lista de origens pode conter da mesma origem e/ou cruzada, e permite que o desenvolvedor controle o acesso próprio e de terceiros aos recursos do navegador.

O usuário tem a decisão final de permitir o acesso a recursos mais eficientes e precisa dar permissão explícita com uma solicitação.

A política de permissões permite que o site de nível superior defina o que ele e terceiros pretendem usar e remove o trabalho do usuário de determinar se a solicitação de acesso ao recurso é legítima ou não. Por exemplo, ao bloquear o recurso de geolocalização para todos os terceiros pela Política de permissões, o desenvolvedor pode ter certeza de que nenhum terceiro terá acesso à geolocalização do usuário.

Alterações na política de permissões

A política de permissões era conhecida como política de recursos. Os conceitos principais permanecem os mesmos, mas há algumas mudanças importantes junto com o nome.

Uso de campos estruturados

Os campos estruturados fornecem um conjunto de estruturas de dados comuns para padronizar a análise e a serialização dos valores do campo do cabeçalho HTTP. Saiba mais sobre campos estruturados na postagem do blog da Fastly, "Como melhorar o HTTP com campos de cabeçalho estruturados".

Antiga
  geolocation 'self' https://example.com; camera 'none'

Antes, com a política de recursos.

Novo
  geolocation=(self "https://example.com"), camera=()

Agora com a política de permissões.

Combinar cabeçalhos com o atributo iframe allow

Com a política de recursos, é possível incluir o recurso em um frame de origem cruzada. Para isso, adicione a origem à lista de origens do cabeçalho ou um atributo allow à tag de iframe. Com a política de permissões, se você adicionar um frame de origem cruzada à lista de origens, a tag de iframe dessa origem precisará incluir o atributo allow. Se a resposta não tiver um cabeçalho "Permissions Policy", o valor padrão * vai ser considerado na lista de origem. Adicionar o atributo allow ao iframe permite o acesso ao recurso.

Portanto, recomendamos que os desenvolvedores definam explicitamente o cabeçalho da política de permissões na resposta para que os iframes de origem cruzada que não estejam listados na lista de origens sejam impedidos de acessar esse recurso, mesmo que allow esteja presente.

A política de recursos ainda pode ser usada após o Chrome 88, mas funciona como um alias da política de permissões. Além da sintaxe, não há diferença na lógica. Se os cabeçalhos "Política de permissões" e "Política de recursos" forem usados juntos, o cabeçalho Permissions-Policy terá prioridade mais alta e vai substituir o valor fornecido pelo cabeçalho Feature-Policy.

Como uso a política de permissões?

Visão rápida

Antes de nos aprofundarmos, vamos analisar um cenário comum em que você é o proprietário de um site e deseja controlar como seu site e o código de terceiros usam os recursos do navegador.

  • Seu site é https://your-site.example.
  • Seu site incorpora um iframe da mesma origem (https://your-site.example).
  • Seu site incorpora um iframe de https://trusted-site.example confiável.
  • Seu site também exibe anúncios veiculados por https://ad.example.
  • Você quer permitir a geolocalização apenas para seu site e o site confiável, não para o anúncio.

Nesse caso, use o seguinte cabeçalho:

Permissions-Policy: geolocation=(self "https://trusted-site.example")

Além disso, defina explicitamente o atributo allow como a tag de iframe do site confiável:

<iframe src="https://trusted-site.example" allow="geolocation">

Diagrama de visão geral rápida do uso da política de permissões.

Nesse exemplo, a lista de origem do cabeçalho permite que apenas seu site (self) e trusted-site.example usem o recurso de geolocalização. ad.example não tem permissão para usar a geolocalização.

  1. Seu site your-site.example tem permissão para usar o recurso de geolocalização com o consentimento do usuário.
  2. Um iframe de mesma origem (your-site.example) pode usar o recurso sem o uso do atributo allow.
  3. Um iframe veiculado de um subdomínio diferente (subdomain.your-site-example) que não foi adicionado à lista de origem e tem o atributo de permissão definido na tag de iframe é impedido de usar o recurso. Subdomínios diferentes são considerados do mesmo site, mas de origem cruzada.
  4. Um iframe de origem cruzada (trusted-site.example) adicionado à lista de origem e que tem o atributo allow definido na tag de iframe pode usar o recurso.
  5. Um iframe de origem cruzada (trusted-site.example) adicionado à lista de origem, sem o atributo allow, está impedido de usar o recurso.
  6. Um iframe de origem cruzada (ad.example) que não foi adicionado à lista de origem não pode usar o recurso, mesmo que o atributo allow esteja incluído na tag de iframe.

Cabeçalho de resposta HTTP Permissions-Policy

O usuário faz uma solicitação, o servidor responde com o cabeçalho &quot;Permissions Policy&quot; e o navegador concede acesso com base nesse cabeçalho.

Permissions-Policy: &lt;feature&gt;=(&lt;token&gt;|&lt;origin(s)&gt;)

Use um cabeçalho Permissions-Policy na resposta do servidor para definir as origens permitidas para um recurso. O valor do cabeçalho pode usar uma combinação de tokens e strings de origens. Os tokens disponíveis são * para todas as origens e self para a mesma origem.

Se o cabeçalho for para vários recursos, separe-os com vírgulas. Se você listar várias origens, separe cada uma delas com um espaço. Para cabeçalhos que listam uma origem de solicitação de origem cruzada, a tag de iframe precisa incluir o atributo allow.

Aqui estão alguns exemplos de pares de chave-valor:

  • Sintaxe: [FEATURE]=*
    • Política aplicada a todas as origens
    • Exemplo: geolocation=*
  • Sintaxe: [FEATURE]=(self)
    • Política aplicada à mesma origem
    • Exemplo: geolocation=(self)
  • Sintaxe: [FEATURE]=(self [ORIGIN(s)])
    • Política aplicada à mesma origem e às origens especificadas
    • Exemplo: geolocation=(self "https://a.example" "https://b.example")
    • self é uma abreviação de https://your-site.example.
  • Sintaxe: [FEATURE]=([ORIGIN(s)])
    • Política aplicada à mesma origem e às origens especificadas
    • Exemplo: geolocation=("https://your-site.example" "https://a.example" "https://b.example")
    • Ao usar essa sintaxe, uma das origens deve ser a do incorporado. Se a própria página de incorporação não receber as permissões, os iframes incorporados a ela também serão bloqueados, mesmo que sejam adicionados à lista de origem, porque a política de permissões delega permissões. Também é possível usar o token self.
  • Sintaxe: [FEATURE]=()
    • Recurso bloqueado para todas as origens
    • Exemplo: geolocation=()

Subdomínios e caminhos diferentes

Subdomínios diferentes, como https://your-site.example e https://subdomain.your-site.example, são considerados no mesmo site, mas de origem cruzada. Portanto, adicionar um subdomínio à lista de origens não permite o acesso a outro subdomínio do mesmo site. Cada subdomínio incorporado que quiser usar o recurso precisa ser adicionado separadamente à lista de origens. Por exemplo, se o acesso aos temas de navegação do usuário tiver permissão para a mesma origem apenas com o cabeçalho Permissions-Policy: browsing-topics=(self), um iframe de um subdomínio diferente do mesmo site, https://subdomain.your-site.example, não terá acesso aos temas.

Caminhos diferentes, como https://your-site.example e https://your-site.example/embed, são considerados da mesma origem, e não precisam ser incluídos na lista de origens.

Atributo allow do iframe

Configuração de iframes

Para o uso de origem cruzada, um iframe precisa do atributo allow na tag para ter acesso ao recurso.

Sintaxe: <iframe src="[ORIGIN]" allow="[FEATURE] <'src' | [ORIGIN(s)]"></iframe>

Exemplo:

<iframe src="https://trusted-site.example" allow="geolocation">

Processar a navegação no iframe

Configuração da navegação no iframe

Por padrão, se um iframe navegar para outra origem, a política não será aplicada à origem de destino do iframe. Ao listar a origem de navegação do iframe no atributo allow, a política de permissões aplicada ao iframe original será aplicada à origem de navegação do iframe.

<iframe src="https://trusted-site.example" allow="geolocation https://trusted-site.example https://trusted-navigated-site.example">

Para vê-lo em ação, acesse a demonstração de navegação no iframe.

Exemplos de configurações de políticas de permissões

Confira os exemplos das configurações abaixo na demonstração.

Recurso permitido em todas as origens

Arquitetura de todas as origens com permissão para acessar o recurso

Permissions-Policy: geolocation=*
<iframe src="https://trusted-site.example" allow="geolocation">
<iframe src="https://ad.example" allow="geolocation">

Quando a lista de origens é definida como o token *, o recurso é permitido para todas as origens presentes na página, incluindo ela mesma e todos os iframes. Neste exemplo, todos os códigos fornecidos por https://your-site.example e por https://trusted-site.example iframe e https://ad.example têm acesso ao recurso de geolocalização no navegador do usuário. Lembre-se de que o atributo allow também precisa ser definido no próprio iframe, além da adição da origem à lista de origens do cabeçalho.

Essa configuração pode ser conferida na demonstração.

Recurso permitido somente na mesma origem

Arquitetura da mesma origem que tem permissão para acessar o recurso

Permissions-Policy: geolocation=(self)

Com o token self, é possível usar a geolocalização apenas da mesma origem. As origens cruzadas não terão acesso ao recurso. Neste exemplo, apenas https://trusted-site.example (self) terá acesso à geolocalização. Use essa sintaxe se quiser usar o recurso somente para sua página.

Essa configuração pode ser conferida na demonstração.

Recurso permitido para origens cruzadas da mesma origem e específicas

Arquitetura de origens especificadas com permissão para acessar o recurso

Permissions-Policy: geolocation=(self "https://trusted-site.example")

Essa sintaxe permite o uso da geolocalização para si mesmo (https://your-site.example) e https://trusted-site.example. Lembre-se de adicionar explicitamente o atributo allow à tag iframe. Se houver outro iframe com <iframe src="https://ad.example" allow="geolocation">, https://ad.example não terá acesso ao recurso de geolocalização. Somente a página original e o https://trusted-site.example que estiverem na lista de origem, com o atributo de permissão na tag de iframe, terão acesso ao recurso do usuário.

Essa configuração pode ser conferida na demonstração.

Recurso bloqueado em todas as origens

Arquitetura de todas as origens com acesso bloqueado ao recurso

Permissions-Policy: geolocation=()

Com uma lista de origens vazia, o recurso é bloqueado para todas as origens. Essa configuração pode ser conferida na demonstração.

Usar a API JavaScript

A API JavaScript da política de recursos é encontrada como um objeto no documento ou no elemento (document.featurePolicy or element.featurePolicy). A API JavaScript para a política de permissões ainda não foi implementada.

A API Feature Policy pode ser usada para políticas definidas pela política de permissões, com algumas limitações. Há dúvidas restantes sobre a implementação da API JavaScript, e uma proposta foi feita para mover a lógica para a API Permissions. Participe da discussão se tiver alguma ideia.

featurePolicy.allowsFeature(feature)

  • Retorna true se o recurso tiver permissão para o uso de origem padrão.
  • O comportamento é o mesmo para as duas políticas definidas pela política de permissões e pela política de recurso anterior.
  • Quando allowsFeature() é chamado em um elemento de iframe (iframeEl.featurePolicy.allowsFeature('geolocation')), o valor retornado reflete se o atributo de permissão está definido no iframe.

featurePolicy.allowedFeature(feature, origin)

  • Retorna true se o recurso for permitido para a origem especificada.
  • Se o método for chamado em document, ele não vai mais informar se o recurso é permitido para a origem especificada, como a política de recursos fez. Agora, esse método informa que o recurso pode ter permissão para chegar àquela origem. É preciso fazer outra verificação para saber se o iframe tem o atributo allow definido. O desenvolvedor precisa fazer outra verificação do atributo allow no elemento iframe para determinar se ele tem permissão para a origem de terceiros.

Verificar se há recursos em um iframe com o objeto element

Você pode usar element.allowsFeature(feature), que considera o atributo de permissão, ao contrário de document.allowsFeature(feature, origin), que não considera.

const someIframeEl = document.getElementById('some-iframe')
const isCameraFeatureAllowed = someIframeEl.featurePolicy.allowsFeature('camera')

featurePolicy.allowedFeatures()

  • Retorna uma lista de recursos permitidos para o uso de origem padrão.
  • O comportamento é o mesmo para as duas políticas definidas pelas políticas de permissões e de recursos
  • Quando o nó associado é um iframe, o atributo allow é considerado.

featurePolicy.features()

  • Retorna uma lista de recursos disponíveis no navegador.
  • O comportamento é o mesmo para as duas políticas definidas pelas políticas de permissões e de recursos

Integração com Chrome DevTools

Integração do Chrome DevTools com a política de permissões

Veja como a política de permissões funciona no DevTools.

  1. Abra o Chrome DevTools.
  2. Abra o painel Aplicativo para verificar os recursos permitidos e não permitidos de cada frame.
  3. Na barra lateral, selecione o frame que você quer inspecionar. Você vai receber uma lista de recursos que o frame selecionado tem permissão para usar e uma lista dos recursos bloqueados nesse frame.

Migração da Feature-Policy

Se você estiver usando o cabeçalho Feature-Policy, implemente as etapas a seguir para migrar para a política de permissões.

Substituir cabeçalhos da política de recursos por cabeçalhos da política de permissões

Como os cabeçalhos da política de recursos só são compatíveis com navegadores baseados no Chromium, e os cabeçalhos da política de permissões são aceitos desde o Chrome 88, é seguro atualizar os cabeçalhos existentes com a política de permissões.

Antiga
Feature-Policy:
  autoplay *;
  geolocation 'self';
  camera 'self' 'https://trusted-site.example';
  fullscreen 'none';

Antes, com a política de recursos.

Novo
Permissions-Policy:
  autoplay=*,
  geolocation=(self),
  camera=(self "https://trusted-site.example"),
  fullscreen=()

Agora com a política de permissões.

Atualizar o uso do app document.allowsFeature(feature, origin)

Se você estiver usando o método document.allowsFeature(feature, origin) para verificar os recursos permitidos para iframes, use o método allowsFeature(feature) anexado ao elemento iframe, e não no document que o contém. O método element.allowsFeature(feature) considera o atributo de permissão, ao contrário do document.allowsFeature(feature, origin).

Verificando o acesso a recursos com o document

Para continuar usando document como nó de base, faça outra verificação para o atributo allow na tag de iframe.

<iframe id="some-iframe" src="https://example.com" allow="camera"></iframe>
Permissions-Policy: camera=(self "https://example.com")
const isCameraPolicySet = document.featurePolicy.allowsFeature('camera', 'https://example.com')

const someIframeEl = document.getElementById('some-iframe')
const hasCameraAttributeValue = someIframeEl.hasAttribute('allow')
&& someIframeEl.getAttribute('allow').includes('camera')

const isCameraFeatureAllowed = isCameraPolicySet && hasCameraAttributeValue

Em vez de atualizar o código existente usando document, é recomendável chamar allowsFeature() no objeto element, como no exemplo anterior.

API Reporting

A API Reporting oferece um mecanismo de geração de relatórios para aplicativos da Web de maneira consistente, e a API Reporting para violações da política de permissões está disponível como um recurso experimental.

Se você quiser testar o recurso experimental, siga as instruções e ative a flag em chrome://flags/#enable-experimental-web-platform-features. Com a flag ativada, é possível observar as violações da política de permissões no DevTools na guia "Application":

O exemplo a seguir mostra como o cabeçalho da API Reporting pode ser criado:

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"

Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0; report-to=main-endpoint;

Na implementação atual, você pode receber relatórios de violação da política de qualquer violação ocorrida nesse frame configurando um endpoint chamado "default", como no exemplo acima. Os subframes precisam ter a própria configuração de relatórios.

Saiba mais

Para entender melhor a política de permissões, consulte os seguintes recursos: