Definir uma permissão de app personalizada

Este documento descreve como os desenvolvedores de apps podem usar os recursos de segurança fornecidos pelo Android para definir as próprias permissões. Ao definir permissões personalizadas, um app pode compartilhar recursos e capabilities com outros apps. Para saber mais sobre permissões, consulte a visão geral de permissões.

Contexto

O Android é um sistema operacional separado por privilégios, em que cada app é executado com uma identidade de sistema distinta (ID do usuário do Linux e ID do grupo). Partes do sistema também são separadas em identidades distintas. Assim, o Linux isola apps uns dos outros e do sistema.

Os apps podem expor a funcionalidade deles a outros aplicativos definindo permissões que outros apps podem solicitar. Eles também podem definir permissões que são disponibilizadas automaticamente para outros apps assinados com o mesmo certificado.

Assinatura de apps

Todos os APKs precisam ser assinados com um certificado cuja chave privada seja mantida pelo desenvolvedor. O certificado não precisa ser assinado por uma autoridade certificadora. É permitido, e normal, que os apps Android usem certificados autoassinados. O objetivo dos certificados no Android é distinguir os autores dos apps. Isso permite que o sistema conceda ou negue acesso dos apps a permissões no nível da assinatura e conceda ou negue solicitação para receber a mesma identidade do Linux de outro app.

Conceder permissões de assinatura após o tempo de fabricação do dispositivo

No Android 12, (nível 31 da API) e versões mais recentes, o atributo knownCerts para permissões no nível da assinatura permite que você consulte as sínteses dos certificados de assinatura no momento da declaração.

Declare o atributo knownCerts e use a flag knownSigner no atributo protectionLevel do app para uma permissão específica no nível da assinatura. O sistema vai conceder essa permissão a um aplicativo solicitante se qualquer signatário na linhagem de assinatura dele, incluindo o signatário atual, corresponder a um dos resumos declarados com a permissão no atributo knownCerts.

A flag knownSigner permite que dispositivos e apps concedam permissões de assinatura a outros aplicativos sem precisar assinar os apps no momento da fabricação e envio do dispositivo.

IDs de usuário e acesso a arquivos

No momento da instalação, o Android atribui a cada pacote um ID de usuário do Linux diferente. A identidade permanece constante durante a vida útil do pacote nesse dispositivo. Em um dispositivo diferente, o mesmo pacote pode ter um UID diferente; o que importa é que cada pacote tenha um UID distinto em determinado dispositivo.

Como a aplicação da segurança ocorre no nível do processo, o código de dois pacotes normalmente não pode ser executado no mesmo processo, porque eles precisam ser executados como usuários do Linux diferentes.

Todos os dados armazenados por um app recebem o ID do usuário desse app e normalmente não podem ser acessados por outros pacotes.

Para saber mais sobre o modelo de segurança do Android, consulte Visão geral de segurança do Android.

Definir e aplicar permissões

Para aplicar suas próprias permissões, primeiro é necessário declará-las no AndroidManifest.xml usando um ou mais elementos <permission>.

Convenção de nomenclatura

O sistema não permite que vários pacotes declarem uma permissão com o mesmo nome, a menos que todos os pacotes sejam assinados com o mesmo certificado. Se um pacote declarar uma permissão, o sistema também não vai permitir que o usuário instale outros pacotes com o mesmo nome de permissão, a menos que eles sejam assinados com o mesmo certificado do primeiro.

Recomendamos adicionar o nome do pacote dos apps como prefixo nas permissões, usando a nomeação no estilo de domínio inverso, seguido por .permission. e uma descrição da capacidade que a permissão representa com letras maiúsculas em SNAKE_CASE. Por exemplo: com.example.myapp.permission.ENGAGE_HYPERSPACE.

Essa recomendação evita conflitos na nomenclatura e ajuda a identificar com clareza o proprietário e a intenção de uma permissão personalizada.

Exemplo

Por exemplo, um app que precise controlar quais outros aplicativos podem iniciar uma das atividades pode declarar uma permissão para essa operação desta forma:

<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.example.myapp" >
    
    <permission
      android:name="com.example.myapp.permission.DEADLY_ACTIVITY"
      android:label="@string/permlab_deadlyActivity"
      android:description="@string/permdesc_deadlyActivity"
      android:permissionGroup="android.permission-group.COST_MONEY"
      android:protectionLevel="dangerous" />
    ...
</manifest>

O atributo protectionLevel é obrigatório e relata ao sistema como o usuário precisa ser informado sobre apps que exigem a permissão ou que podem manter a permissão, conforme descrito na documentação vinculada.

O atributo android:permissionGroup é opcional e usado apenas para ajudar o sistema a mostrar permissões para o usuário. Na maioria dos casos, você define um grupo de sistema padrão (listado em android.Manifest.permission_group), mas também pode definir seu próprio grupo, como descrito na próxima seção. Recomendamos usar um grupo já criado, porque isso simplifica a interface de permissões mostrada ao usuário.

Você precisa fornecer um rótulo e uma descrição para a permissão. Eles são recursos de string mostrados ao usuário quando aparece uma lista de permissões (android:label) ou detalhes sobre uma única permissão (android:description). O rótulo é curto: algumas palavras que descrevem a funcionalidade principal que a permissão está protegendo. A descrição contém algumas frases descrevendo o que pode ser feito por apps com a permissão. Nossa convenção é uma descrição de duas frases, em que a primeira descreve a permissão e a segunda avisa o usuário sobre o que poderá dar errado se um app receber a permissão.

Confira um exemplo de rótulo e descrição para a permissão CALL_PHONE:

<string name="permlab_callPhone">directly call phone numbers</string>
<string name="permdesc_callPhone">Allows the app to call non-emergency
phone numbers without your intervention. Malicious apps may cause unexpected
calls on your phone bill.</string>

Criar um grupo de permissões

Como mostrado na seção anterior, você pode usar o atributo android:permissionGroup para ajudar o sistema a descrever as permissões para o usuário. Na maioria dos casos, você define um grupo de sistema padrão (listado em android.Manifest.permission_group), mas também pode definir seu próprio grupo com <permission-group>.

O elemento <permission-group> define um rótulo para um conjunto de permissões, tanto aquelas declaradas no manifesto com elementos <permission> quanto aquelas declaradas em outro lugar. Isso afeta apenas a forma como as permissões são agrupadas quando apresentadas ao usuário. O elemento <permission-group> não especifica as permissões que pertencem ao grupo, mas fornece um nome ao grupo.

Você pode colocar uma permissão no grupo atribuindo o nome do grupo ao atributo permissionGroup do elemento <permission>.

O elemento <permission-tree> declara um namespace para um grupo de permissões que são definidas no código.

Recomendações para permissões personalizadas

Você pode definir permissões personalizadas para seus apps e solicitar permissões personalizadas de outros aplicativos definindo elementos <uses-permission>. No entanto, avalie com atenção se é necessário fazer isso.

  • Se você estiver projetando um pacote de apps que expõem a funcionalidade um ao outro, tente projetar os apps de forma que cada permissão seja definida apenas uma vez. Faça isso se todos os apps não estiverem assinados com o mesmo certificado. Mesmo que os apps sejam assinados com o mesmo certificado, é uma prática recomendada definir cada permissão apenas uma vez.
  • Se a funcionalidade só estiver disponível para apps assinados com a mesma assinatura do app de fornecimento, talvez seja possível evitar a definição de permissões personalizadas usando verificações de assinatura. Quando um dos seus apps fizer uma solicitação de outro app, o segundo app poderá verificar se os dois apps estão assinados com o mesmo certificado antes de obedecer à solicitação.

Se uma permissão personalizada for necessária, considere se apenas os apps assinados pelo mesmo desenvolvedor que o aplicativo que executa a verificação de permissões precisam acessá-la, como ao implementar comunicações seguras entre processos entre dois aplicativos do mesmo desenvolvedor. Nesse caso, recomendamos o uso de permissões de assinatura. Permissões de assinatura são transparentes para o usuário e evitam permissões que precisam ser confirmadas por ele, o que pode ser confuso.

Continue lendo sobre:

<uses-permission>
Referência da API para a tag de manifesto que declara as permissões necessárias do sistema do seu app.

Talvez você também tenha interesse em:

Visão geral de segurança do Android
Uma discussão detalhada sobre o modelo de segurança da plataforma Android.