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

Gerencie como sua página e os iframes de terceiros nela acessam os recursos do navegador.

Kevin K. Lee
Kevin K. Lee

A política de permissões, antes 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 às origens fornecidas em uma lista de origens de cabeçalho de resposta. A lista de origens pode conter origens iguais e diferentes, e permite que o desenvolvedor controle o acesso de terceiros e próprios aos recursos do navegador.

O usuário tem a decisão final de permitir o acesso a recursos mais avançados e precisa dar permissão explícita aceitando um aviso.

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

Mudanças na Política de permissões

A Permissions Policy era conhecida como Feature Policy. 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 de valores de campos de cabeçalho HTTP. Saiba mais sobre campos estruturados na postagem do blog da Fastly, "Melhorando o HTTP com campos de cabeçalho estruturados".

Antigo
  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 allow do iframe

Com a Política de recursos, você pode adicionar o recurso a um frame de origem cruzada adicionando a origem à lista de origens do cabeçalho ou um atributo allow à tag iframe. Com a Permissions Policy, se você adicionar um frame de origem cruzada à lista de origens, a tag iframe dessa origem precisará incluir o atributo allow. Se a resposta não tiver um cabeçalho de política de permissões, a lista de origens será considerada com o valor padrão de *. 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 estão listados na lista de origens sejam bloqueados 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á maior prioridade 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, confira um cenário comum em que você é proprietário de um site e quer controlar como ele 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 em que você confia.
  • Seu site também mostra 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")

E defina explicitamente o atributo allow para a tag de iframe do site de confiança:

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

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

Neste exemplo, a lista de origens 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 atributo allow.
  3. Um iframe veiculado de um subdomínio diferente (subdomain.your-site-example) que não foi adicionado à lista de origens e tem o atributo "allow" definido na tag de iframe não pode usar o recurso. Subdomínios diferentes são considerados do mesmo site, mas de origens diferentes.
  4. Um iframe de origem cruzada (trusted-site.example) que foi adicionado à lista de origens e tem o atributo allow definido na tag do iframe pode usar o recurso.
  5. Um iframe de origem cruzada (trusted-site.example) adicionado à lista de origens, sem o atributo allow, não pode usar o recurso.
  6. Um iframe de origem cruzada (ad.example) que não foi adicionado à lista de origens é bloqueado para usar o recurso, mesmo que o atributo allow esteja incluído na tag do iframe.

Cabeçalho de resposta HTTP Permissions-Policy

O usuário faz uma solicitação, o servidor responde com o cabeçalho da Política de permissões e o navegador concede acesso com base nesse cabeçalho.

Permissions-Policy: <feature>=(<token>|<origin(s)>)

Use um cabeçalho Permissions-Policy na resposta do servidor para definir as origens permitidas de 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 mesma origem.

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

Confira 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 precisa ser a do incorporador. Se a página do incorporador não receber as permissões, os iframes incorporados nela também serão bloqueados, mesmo que sejam adicionados à lista de origens, 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 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 tópicos de navegação do usuário for permitido apenas para a mesma origem 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 tópicos.

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

Atributo allow do iframe

Configuração do iframe

Para uso entre origens, um iframe precisa do atributo allow na tag para acessar o recurso.

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

Exemplo:

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

Gerenciar a navegação no iframe

Configuração de navegação no iframe

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

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

Para ver isso em ação, acesse a demonstração de navegação por iframe.

Exemplos de configurações da política de permissões

Os exemplos das configurações a seguir podem ser encontrados 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, todo o código veiculado de https://your-site.example e os códigos veiculados do iframe https://trusted-site.example e https://ad.example têm acesso ao recurso de geolocalização no navegador do usuário. O atributo "allow" também precisa ser definido no próprio iframe, além de adicionar a origem à lista de origens do cabeçalho.

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

Recurso permitido apenas na mesma origem

Arquitetura de apenas mesma origem permitida para acessar o recurso

Permissions-Policy: geolocation=(self)

Usar o token self permite o uso da geolocalização apenas para a mesma origem. 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 o recurso apenas para sua página e mais ninguém.

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

Recurso permitido na mesma origem e em origens cruzadas 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 para https://trusted-site.example. Não se esqueça 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 listado na lista de origens, além de ter o atributo "allow" na tag iframe, terão acesso ao recurso do usuário.

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

Recurso bloqueado em todas as origens

Arquitetura de todas as origens bloqueadas para acessar o recurso

Permissions-Policy: geolocation=()

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

Usar a API JavaScript

A API JavaScript atual da Feature Policy é encontrada como um objeto no documento ou no elemento (document.featurePolicy or element.featurePolicy). A API JavaScript para a Permissions Policy ainda não foi implementada.

A API Feature Policy pode ser usada para políticas definidas pela Permissions Policy, com algumas limitações. Há dúvidas restantes sobre uma 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 for permitido para o uso de origem padrão.
  • O comportamento é o mesmo para as políticas definidas pela Permissions Policy e pela Feature Policy anterior.
  • Quando allowsFeature() é chamado em um elemento iframe (iframeEl.featurePolicy.allowsFeature('geolocation')), o valor retornado reflete se o atributo "allow" está definido no iframe.

featurePolicy.allowsFeature(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 fazia a política de recursos. Agora, esse método informa que é possível permitir o recurso para essa origem. Você precisa fazer uma verificação adicional para saber se o iframe tem o atributo allow definido ou não. O desenvolvedor precisa realizar uma verificação adicional do atributo allow no elemento iframe para determinar se o recurso é permitido para a origem de terceiros.

Verificar recursos em um iframe com o objeto element

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

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

featurePolicy.allowedFeatures()

  • Retorna uma lista de recursos permitidos para o uso da origem padrão.
  • O comportamento é o mesmo para as duas políticas definidas pela Permissions Policy e pela Feature Policy.
  • 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 pela Permissions Policy e pela Feature Policy.

Integração do Chrome DevTools

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

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

  1. Abra o Chrome DevTools.
  2. Abra o painel Application para verificar os recursos permitidos e proibidos de cada frame.
  3. Na barra lateral, selecione o frame que você quer inspecionar. Você vai encontrar uma lista de recursos que o frame selecionado pode usar e outra com os recursos bloqueados nele.

Migração da Feature-Policy

Se você estiver usando o cabeçalho Feature-Policy, siga estas etapas 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 Feature Policy só são compatíveis com navegadores baseados no Chromium, e os cabeçalhos da Permissions Policy são compatíveis desde o Chrome 88, é seguro atualizar os cabeçalhos atuais com a Permissions Policy.

Antigo
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 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 o document que o contém. O método element.allowsFeature(feature) considera o atributo "allow", enquanto document.allowsFeature(feature, origin) não.

Verificar o acesso aos recursos com document

Para continuar usando document como o nó de base, faça uma verificação adicional do atributo allow na tag 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 atual usando document, é recomendável chamar allowsFeature() no objeto element, como no exemplo anterior.

API Reporting

A API Reporting oferece um mecanismo 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 quiser testar o recurso experimental, siga o tutorial e ative a flag em chrome://flags/#enable-experimental-web-platform-features. Com a flag ativada, você pode observar as violações da Política de permissões nas DevTools na guia "Application":

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

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, é possível receber relatórios de violação da política de qualquer violação que ocorra nesse frame configurando um endpoint chamado "default", como no exemplo anterior. Os subframes vão precisar da própria configuração de relatórios.

Saiba mais

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