Segurança

Os recursos deste guia descrevem os recursos de gerenciamento de segurança que você pode implementar no app controlador de política de dispositivo (DPC). Este documento contém exemplos de código e também é possível usar o app Testar DPC como uma fonte de exemplo de código para recursos empresariais do Android.

Um app de DPC pode ser executado no modo de proprietário do perfil em dispositivos pessoais ou no modo de proprietário em dispositivos totalmente gerenciados. Esta tabela indica quais recursos estão disponíveis quando o DPC é executado no modo de proprietário do perfil ou de proprietário do dispositivo:

Recurso Proprietário do perfil Proprietário do dispositivo
Desativar o acesso a apps
Bloquear apps de fontes desconhecidas
Restringir contas no Google Play
Ativar a proteção contra a redefinição para a configuração original da empresa
Monitore registros de processos empresariais e relatórios remotos de bugs
Conceder e remover o acesso a um certificado do cliente
Redefinição de senha segura
Desafio de segurança do perfil de trabalho

Desativar o acesso a apps

Para organizações que querem impedir que os funcionários joguem ou assistam o YouTube em dispositivos Android durante determinados horários do dia ou determinados dias da semana, um DPC pode desativar temporariamente o acesso aos apps.

Para desativar o acesso a apps, um DPC em execução no modo proprietário do dispositivo ou do perfil configura setPackagesSuspended() e, em seguida, o app selecionado age como se estiver desativado (o Acesso rápido do Google esmaece o app). Quando um usuário toca no app, uma caixa de diálogo do sistema informa que o app está suspenso.

Enquanto um app está suspenso, ele não pode iniciar atividades e as notificações para o pacote são suprimidas. Os pacotes suspensos não aparecem na tela de visão geral, não podem mostrar caixas de diálogo (incluindo avisos e snackbars) e não podem reproduzir áudio nem fazer o dispositivo vibrar.

As telas de início podem descobrir se um app está suspenso chamando o método isPackageSuspended(). Para detalhes sobre como configurar a suspensão de apps, consulte setPackagesSuspended.

Bloquear apps de fontes desconhecidas

Os apps que não são instalados no Google Play (ou em outras app stores confiáveis) são chamados de apps de fontes desconhecidas. Dispositivos e dados correm maior risco quando as pessoas instalam esses apps.

Para evitar que alguém instale apps de fontes desconhecidas, os componentes de administrador de dispositivos totalmente gerenciados e perfis de trabalho podem adicionar a restrição de usuário DISALLOW_INSTALL_UNKNOWN_SOURCES.

Restrição em todo o dispositivo do perfil de trabalho

Quando o administrador de um perfil de trabalho adiciona DISALLOW_INSTALL_UNKNOWN_SOURCES, a restrição se aplica apenas ao perfil de trabalho. No entanto, o administrador de um perfil de trabalho pode aplicar uma restrição a todo o dispositivo definindo uma configuração gerenciada para o Google Play. A restrição em todo o dispositivo está disponível no Android 8.0 (ou versões mais recentes) quando o app Google Play instalado é a versão 80812500 ou mais recente.

Para restringir as instalações de apps ao Google Play, siga estas etapas:

  1. Defina um pacote de configurações gerenciadas para o pacote com.android.vending do Google Play.
  2. No pacote, coloque um valor booleano para a chave verify_apps:device_wide_unknown_source_block.
  3. Adicione a restrição de usuário ENSURE_VERIFY_APPS.

O exemplo a seguir mostra como verificar se o Google Play oferece suporte a essa configuração e definir o valor como true:

Kotlin

internal val DEVICE_WIDE_UNKNOWN_SOURCES = "verify_apps:device_wide_unknown_source_block"
internal val GOOGLE_PLAY_APK = "com.android.vending"

// ...

// Add the setting to Google Play's existing managed config. Supported in
// Google Play version 80812500 or higher--older versions ignore unsupported
// settings.
val dpm = context.getSystemService(Context.DEVICE_POLICY_SERVICE) as DevicePolicyManager
var existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putBoolean(DEVICE_WIDE_UNKNOWN_SOURCES, true)
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig)

// Make sure that Google Play Protect verifies apps.
dpm.addUserRestriction(adminName, UserManager.ENSURE_VERIFY_APPS)
dpm.addUserRestriction(adminName, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES)

Java

static final String DEVICE_WIDE_UNKNOWN_SOURCES =
    "verify_apps:device_wide_unknown_source_block";
static final String GOOGLE_PLAY_APK = "com.android.vending";

// ...


// Add the setting to Google Play's existing managed config. Supported in
// Google Play version 80812500 or higher--older versions ignore unsupported
// settings.
DevicePolicyManager dpm =
    (DevicePolicyManager) context.getSystemService(Context.DEVICE_POLICY_SERVICE);
Bundle existingConfig =
    dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putBoolean(DEVICE_WIDE_UNKNOWN_SOURCES, true);
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig);

// Make sure that Google Play Protect verifies apps.
dpm.addUserRestriction(adminName, UserManager.ENSURE_VERIFY_APPS);
dpm.addUserRestriction(adminName, UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES);

A interface do usuário nas configurações do sistema permanece ativa, mas o sistema bloqueia a instalação do app. Essa restrição afeta instalações futuras. Os apps instalados anteriormente permanecem no dispositivo. Os usuários do dispositivo podem continuar instalando apps no perfil pessoal usando o Android Debug Bridge (adb).

Para saber mais sobre fontes desconhecidas, leia Opções alternativas de distribuição.

Restringir contas no Google Play

Às vezes, uma organização pode permitir que as pessoas adicionem Contas do Google pessoais (para ler e-mails no Gmail, por exemplo), mas não quer que a conta pessoal instale apps. Seu DPC pode definir uma lista de contas que as pessoas podem usar no Google Play.

Os componentes de administração de dispositivos totalmente gerenciados ou perfis de trabalho podem restringir as contas definindo uma configuração gerenciada para o Google Play. A restrição de conta está disponível quando o app Google Play instalado tem a versão 80970100 ou mais recente.

Para limitar as contas no Google Play, faça o seguinte:

  1. Defina um pacote de configurações gerenciadas para o pacote com.android.vending do Google Play.
  2. No pacote, coloque os endereços de e-mail separados por vírgula como um valor de string para a chave allowed_accounts.

O exemplo a seguir mostra como limitar contas:

Kotlin

internal val ALLOWED_ACCOUNTS = "allowed_accounts"
internal val GOOGLE_PLAY_APK = "com.android.vending"

// ...

// Limit Google Play to one work and one personal account. Use
// a comma-separated list of account email addresses (usernames).
val googleAccounts = "ali@gmail.com,ali.connors@example.com"

// Supported in Google Play version 80970100 or higher.
val existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putString(ALLOWED_ACCOUNTS, googleAccounts)
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig)

Java

static final String ALLOWED_ACCOUNTS = "allowed_accounts";
static final String GOOGLE_PLAY_APK = "com.android.vending";

// ...


// Limit Google Play to one work and one personal account. Use
// a comma-separated list of account email addresses (usernames).
String googleAccounts = "ali@gmail.com,ali.connors@example.com";

// Supported in Google Play version 80970100 or higher.
Bundle existingConfig =
    dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putString(ALLOWED_ACCOUNTS, googleAccounts);
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig);

Para limitar o Google Play apenas à conta de trabalho, defina allowed_accounts como a conta gerenciada única assim que seu DPC souber o endereço de e-mail da conta. Uma string vazia impede que os usuários usem qualquer conta no Google Play.

Ativar proteção contra redefinição da configuração original da empresa

Ao usar a proteção contra redefinição de fábrica da empresa, as organizações podem especificar quais Contas do Google podem provisionar um dispositivo que foi redefinido para a configuração original.

A proteção contra redefinição para a configuração original para o consumidor é projetada para impedir o roubo do dispositivo. Antes de permitir que qualquer pessoa provisione o dispositivo após a redefinição para a configuração original não autorizada (como usar um EMM), o assistente de configuração exige que o usuário faça a autenticação em qualquer Conta do Google que estava anteriormente no perfil pessoal do dispositivo.

Em um ambiente corporativo, a redefinição para a configuração original é uma ferramenta importante para gerenciar os dispositivos dos funcionários quando eles saem da organização. No entanto, se a organização não souber as credenciais da conta de um funcionário, a proteção contra redefinição para configuração original poderá bloquear a capacidade da organização de emitir um dispositivo para outro funcionário.

Controlar o provisionamento após uma redefinição para a configuração original

Quando executado no modo proprietário do dispositivo, seu DPC pode usar setFactoryResetProtectionPolicy() para controlar quais contas estão autorizadas a provisionar um dispositivo após a redefinição para a configuração original. Se essa configuração for definida como null ou definida como uma lista vazia, as contas autorizadas a provisionar um dispositivo após a redefinição para a configuração original serão as contas no perfil pessoal do dispositivo.

Um DPC pode configurar essas contas durante o ciclo de vida de um dispositivo totalmente gerenciado.

  1. O administrador de TI pode usar o método people.get da API People com o valor especial me. Isso recupera o userId da conta conectada. O userID é retornado na chave resourceName no formato people/[userId] como uma string de número inteiro. As contas recém-criadas podem não estar disponíveis para fins de redefinição para a configuração original por 72 horas.
  2. Você também pode permitir que um ou mais administradores de TI desbloqueiem o dispositivo após uma redefinição para a configuração original. Peça para cada administrador de TI fazer login na própria Conta do Google e seguir a etapa 1 e compartilhar o userId com você. Assim, você poderá adicionar esses userIds à lista na próxima etapa.
  3. O DPC define uma restrição de app adequada usando setFactoryResetProtectionPolicy() para definir a lista de userId que pode provisionar um dispositivo que foi redefinido para a configuração original.
  4. O DPC permite que as contas que podem provisionar dispositivos após a redefinição para a configuração original enviem a transmissão com.google.android.gms.auth.FRP_CONFIG_CHANGED como uma intent explícita para evitar que ela seja descartada devido a restrições em segundo plano.

Kotlin

const val ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

// List of userId that can provision a factory reset device.
// You can use the value returned calling people/me endpoint.
val accountIds = listOf("000000000000000000000")

dpm.setFactoryResetProtectionPolicy(
    adminName,
    FactoryResetProtectionPolicy.Builder()
        .setFactoryResetProtectionAccounts(accountIds)
        .setFactoryResetProtectionEnabled(true)
        .build()
)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Java

static final String ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

// List of userId that can provision a factory reset device.
// You can use the value returned calling people/me endpoint.
List<String> accountIds = new ArrayList<String>();
accountIds.add("000000000000000000000");

dpm.setFactoryResetProtectionPolicy(
    adminName,
    new FactoryResetProtectionPolicy.Builder()
        .setFactoryResetProtectionAccounts(accountIds)
        .setFactoryResetProtectionEnabled(true)
        .build());

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Legado

Para dispositivos que não podem usar setFactoryResetProtectionPolicy(), introduzido no nível 30 da API, o DPC pode usar setApplicationRestrictions para adicionar as contas escolhidas à configuração gerenciada factoryResetProtectionAdmin para o pacote com.google.android.gms.

Kotlin

const val GOOGLE_PLAY_APK = "com.android.vending"
const val FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin"
const val DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

val existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, false)
newConfig.putString(FACTORY_RESET_PROTECTION_ADMIN, googleAccounts)
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Java

static final String GOOGLE_PLAY_APK = "com.android.vending";
static final String FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin";
static final String DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

Bundle existingConfig =
        dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, false);
newConfig.putStringArray(FACTORY_RESET_PROTECTION_ADMIN,
        accountIds.toArray(new String[accountIds.size()]));
dpm.setApplicationRestrictions(adminName, GOOGLE_PLAY_APK, newConfig);

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Desativar a proteção contra redefinição da configuração original da empresa

Para desativar a proteção contra redefinição para a configuração original, seu DPC pode usar setFactoryResetProtectionPolicy()ao transmitir o valor null.

Kotlin

const val ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

dpm.setFactoryResetProtectionPolicy(adminName, null)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Java

static final String ACTION_FRP_CONFIG_CHANGED =
    "com.google.android.gms.auth.FRP_CONFIG_CHANGED";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

dpm.setFactoryResetProtectionPolicy(adminName, null);

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Legado

Para dispositivos que não podem usar setFactoryResetProtectionPolicy(), introduzido no nível 30 da API, o DPC pode usar setApplicationRestrictions para definir uma chave valor de true na configuração gerenciada disableFactoryResetProtectionAdmin para o pacote com.google.android.gms.

Kotlin

const val GOOGLE_PLAY_APK = "com.android.vending"
const val FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin"
const val DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin"
const val GMSCORE_PACKAGE = "com.google.android.gms"

// ...

val existingConfig = dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK)
val newConfig = Bundle(existingConfig)
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, true)

dpm.setApplicationRestrictions(
    adminName, GOOGLE_PLAY_SERVICES_PACKAGE, restrictions
)

val frpChangedIntent = Intent(ACTION_FRP_CONFIG_CHANGED)

frpChangedIntent.setPackage(GMSCORE_PACKAGE)
context.sendBroadcast(frpChangedIntent)

Java

static final String GOOGLE_PLAY_APK = "com.android.vending";
static final String FACTORY_RESET_PROTECTION_ADMIN = "factoryResetProtectionAdmin";
static final String DISABLE_FACTORY_RESET_PROTECTION_ADMIN = "disableFactoryResetProtectionAdmin";
static final String GMSCORE_PACKAGE = "com.google.android.gms";

// ...

Bundle existingConfig =
        dpm.getApplicationRestrictions(adminName, GOOGLE_PLAY_APK);
Bundle newConfig = new Bundle(existingConfig);
newConfig.putBoolean(DISABLE_FACTORY_RESET_PROTECTION_ADMIN, true);

dpm.setApplicationRestrictions(
    adminName, GOOGLE_PLAY_SERVICES_PACKAGE, restrictions);

Intent frpChangedIntent = new Intent(ACTION_FRP_CONFIG_CHANGED);

frpChangedIntent.setPackage(GMSCORE_PACKAGE);
context.sendBroadcast(frpChangedIntent);

Monitore registros de processos corporativos e relatórios remotos de bugs

No console de EMM, um administrador pode monitorar dispositivos totalmente gerenciados usando registros de processo empresarial e relatórios remotos de bugs.

Registrar atividade corporativa do dispositivo

Um DPC em execução no modo proprietário do dispositivo pode identificar atividades suspeitas rastreando remotamente a atividade do dispositivo, incluindo inicializações de apps, atividade do Android Debug Bridge (adb) e desbloqueios de tela. Os registros do processo não exigem o consentimento do usuário.

Para ativar ou desativar a geração de registros, um DPC chama setSecurityLoggingEnabled().

Quando um novo lote de registros está disponível, um DeviceAdminReceiver recebe o callback onSecurityLogsAvailable(). Para recuperar os registros (depois de receber o callback), um DPC chama retrieveSecurityLogs().

Os DPCs também podem chamar retrievePreRebootSecurityLogs() para buscar registros de segurança gerados no ciclo de reinicialização anterior. Esse é o intervalo entre a última reinicialização do dispositivo e a reinicialização anterior. Dispositivos sem suporte a retrieveSecurityLogs() retornam null. Caso seu app recupere registros usando retrievePreRebootSecurityLogs() e retrieveSecurityLogs(), você precisará verificar se há entradas duplicadas.
Observação: esse recurso registra apenas a atividade em dispositivos totalmente gerenciados com um único usuário ou usuários afiliados no dispositivo. Esse recurso não funciona em dispositivos pessoais, porque registra a atividade em todo o dispositivo.

Essa configuração pode ser útil na auditoria pós-segurança porque registra os seguintes tipos de ações:

  • Sempre que o app é iniciado do zero. Isso pode ajudar a identificar se há malware que começa com um app comprometido.
  • Tentativas de desbloqueio malsucedidas em um dispositivo. Isso pode identificar se há várias tentativas de desbloqueio malsucedidas em um curto período.
  • Comandos do adb potencialmente nocivos quando um usuário conecta o dispositivo a um computador usando um cabo USB.

Para saber mais detalhes sobre como ler registros, consulte SecurityLog.

Durante o desenvolvimento e o teste, é possível forçar o sistema a disponibilizar quaisquer registros de segurança existentes para seu DPC. Não é preciso esperar por um lote cheio. No Android 9.0 (API de nível 28) ou versões mais recentes, execute o seguinte comando do Android Debug Bridge (adb) no seu terminal:

adb shell dpm force-security-logs

O sistema limita a frequência de uso da ferramenta e informa qualquer desaceleração intencional na saída do terminal. Se houver registros disponíveis, o DPC vai receber o callback onSecurityLogsAvailable().

Solicitar remotamente um relatório do bug

Um DPC em execução no modo proprietário do dispositivo pode solicitar remotamente relatórios de bugs para dispositivos de usuário com apenas um usuário ou usuários afiliados. O relatório do bug captura a atividade do dispositivo no momento exato em que o relatório é solicitado, mas também pode incluir a atividade das últimas horas, dependendo da frequência com que o buffer do logcat é atualizado.

Para solicitar relatórios de bugs remotamente, o DPC chama requestBugreport():

Conceder e remover o acesso a um certificado do cliente

Se um DPC em execução no modo proprietário do perfil ou do dispositivo conceder a um app de terceiros a capacidade de gerenciar certificados, o app poderá conceder a si mesmo acesso aos certificados instalados sem a intervenção de um usuário. Para instalar um certificado que todos os apps em um perfil possam acessar, use installKeyPair().

Para saber quais parâmetros configurar, consulte installKeyPair(). Esse recurso funciona em conjunto com a API atual para gerenciar certificados.

Cenário de implantação

Sem o método installKeyPair():

  • Os usuários precisarão tocar no nome do certificado e em Permitir sempre que quiserem conceder acesso a um certificado.
  • Os usuários veem uma solicitação ao instalar um certificado e precisam nomear o certificado.

Com o método installKeyPair():

  • Os usuários não precisam tocar em Permitir sempre que quiserem conceder acesso a um certificado.
  • Os usuários não podem renomear certificados.
  • Os administradores têm mais controle e podem bloquear certificados de apps que não podem ter acesso a certificados específicos.

Remover um certificado do cliente

Depois de conceder acesso a um certificado do cliente, para remover remotamente certificados do cliente instalados usando installKeyPair(), chame removeKeyPair().

Um DPC em execução no modo de proprietário do dispositivo, de proprietário do perfil ou instalador de certificado delegado pode chamar removeKeyPair(). Isso remove um certificado e um par de chaves privadas instalados em um determinado alias de chave privada.

Cenário de implantação

Use esse recurso se uma organização estiver migrando para uma forma mais segura de certificado de cliente. Se um administrador lançar um novo certificado e a distribuição dele levar muito tempo, ele poderá revogar os certificados descontinuados após a conclusão da migração.

Senha de segurança redefinida

Seu DPC pode redefinir a senha de um usuário autorizando a alteração com um token seguro e pré-registrado. Os proprietários de dispositivos e de perfis podem chamar APIs de redefinição de senha segura para mudar a senha dos dispositivos e dos perfis de trabalho, respectivamente. A redefinição da senha segura substitui resetPassword() pelas melhorias abaixo:

Use a redefinição segura da senha se o build do DPC for destinado ao Android 8.0 (API de nível 26) ou versões mais recentes. Chamar resetPassword() gera uma SecurityException em DPCs destinados ao Android 8.0 ou versões mais recentes. Talvez seja necessário atualizar seu DPC.

Definir e ativar um token

Seu DPC precisa definir e ativar um token antes de redefinir uma senha. Como o DPC pode não conseguir usar o token imediatamente, você precisa definir o token com antecedência no momento em que um administrador de TI pode precisar usá-lo.

Um token de redefinição de senha é um valor aleatório criptograficamente forte e precisa ter pelo menos 32 bytes. Crie um token para cada dispositivo e perfil. Não reutilize nem compartilhe os tokens gerados.

Recomendamos armazenar tokens ou os meios para descriptografar um token em um servidor. Se você armazenar tokens localmente no armazenamento criptografado por credenciais, seu DPC não poderá redefinir a senha até que o usuário desbloqueie o dispositivo ou perfil. Se você armazenar localmente os tokens no armazenamento criptografado do dispositivo, que será comprometido, um invasor poderá usar o token para ter acesso a um perfil de trabalho ou a um usuário principal.

É possível gerar um novo token no DPC ou buscar um token em um servidor. Veja no exemplo abaixo um DPC gerando um token e o relatando a um servidor:

Kotlin

val token = ByteArray(32)

// Generate a new token
val random = SecureRandom()
random.nextBytes(token)

// Set the token to use at a later date
val success: Boolean
success = dpm.setResetPasswordToken(DeviceAdminReceiver.getComponentName(context), token)

// Activate the token and update success variable...

// Store the token on a server
if (success) {
 sendTokenToServer(token)
}

Java

byte token[] = new byte[32]; // Minimum size token accepted

// Generate a new token
SecureRandom random = new SecureRandom();
random.nextBytes(token);

// Set the token to use at a later date
boolean success;
success = dpm.setResetPasswordToken(DeviceAdminReceiver.getComponentName(getContext()), token);

// Activate the token and update success variable ...

// Store the token on a server
if (success) {
 sendTokenToServer(token);
}

Na maioria dos casos, o DPC precisa ativar um token após a configuração. No entanto, quando o usuário não tem uma senha para a tela de bloqueio, o sistema ativa um token imediatamente. Para ativar um token, peça ao usuário para confirmar as credenciais dele. Seu DPC pode chamar o método KeyguardManager createConfirmDeviceCredentialIntent() para receber um Intent que inicia a confirmação. Explique ao usuário do dispositivo na interface do usuário por que você está solicitando a autenticação. O snippet abaixo mostra como ativar um token no seu DPC:

Kotlin

// In your DPC, you'll need to localize the user prompt
val ACTIVATE_TOKEN_PROMPT = "Use your credentials to enable remote password reset"
val ACTIVATE_TOKEN_REQUEST = 1

// Create or fetch a token and set it in setResetPasswordToken() ...
val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
val confirmIntent = keyguardManager.createConfirmDeviceCredentialIntent(null, ACTIVATE_TOKEN_PROMPT)

if (confirmIntent != null) {
 startActivityForResult(confirmIntent, ACTIVATE_TOKEN_REQUEST)
 // Check your onActivityResult() callback for RESULT_OK
} else {
 // Null means the user doesn't have a lock screen so the token is already active.
 // Call isResetPasswordTokenActive() if you need to confirm
}

Java

// In your DPC, you'll need to localize the user prompt
static final String ACTIVATE_TOKEN_PROMPT =
 "Use your credentials to enable remote password reset";
static final int ACTIVATE_TOKEN_REQUEST = 1;

// Create or fetch a token and set it in setResetPasswordToken() ...

KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
Intent confirmIntent = keyguardManager.createConfirmDeviceCredentialIntent(
  null, ACTIVATE_TOKEN_PROMPT);

if (confirmIntent != null) {
 startActivityForResult(confirmIntent, ACTIVATE_TOKEN_REQUEST);
 // Check your onActivityResult() callback for RESULT_OK
} else {
 // Null means the user doesn't have a lock screen so the token is already active.
 // Call isResetPasswordTokenActive() if you need to confirm
}

Você precisa ativar um token que o DPC define antes de reiniciar o dispositivo. O Android armazena um token não ativado na memória e não o mantém após uma reinicialização. Se o usuário reiniciar o dispositivo antes de ativar um token, o DPC poderá definir o mesmo token novamente ou gerar um novo.

Seu DPC pode confirmar se um token está ativo chamando isResetPasswordTokenActive() e verificando se o resultado é true.

Depois que o DPC define e ativa um token, ele é válido até que o DPC exclua ou substitua o token ou o dispositivo seja redefinido para a configuração original. O token é independente da senha e não é afetado pela alteração ou limpeza da senha pelo usuário.

Excluir um token

Chame clearResetPasswordToken() para excluir um token definido pelo DPC anteriormente. Talvez seja necessário revogar um token comprometido ou remover a capacidade de redefinir a senha. O exemplo abaixo mostra como fazer isso no seu DPC:

Kotlin

val dpm = getDpm()
val admin = DeviceAdminReceiver.getComponentName(requireActivity())

// Clear the token
if (!dpm.clearResetPasswordToken(admin)) {
 // Report the failure and possibly try later ...
}

Java

DevicePolicyManager dpm = getDpm();
ComponentName admin = DeviceAdminReceiver.getComponentName(getActivity());

// Clear the token
if (!dpm.clearResetPasswordToken(admin)) {
 // Report the failure and possibly try later ...
}

Redefinir a senha

Quando um administrador de TI precisar redefinir a senha, chame resetPasswordWithToken() e transmita o token que seu DPC definiu e ativou com antecedência:

Kotlin

val token: ByteArray = getTokenFromServer()
val newPassword = "password"

try {
 val result: Boolean = dpm.resetPasswordWithToken(
 DeviceAdminReceiver.getComponentName(requireContext()),
 newPassword,
 token,
 0
 )

 if (result) {
 // The password is now 'password'
 } else {
 // Using 'password' doesn't meet password restrictions
 }
} catch (e: IllegalStateException) {
 // The token doesn't match the one set earlier.
}

Java

byte token[] = getTokenFromServer();
String newPassword = "password";

try {
 boolean result = dpm.resetPasswordWithToken(
  DeviceAdminReceiver.getComponentName(getContext()), newPassword, token, 0);

 if (result) {
 // The password is now 'password'
 } else {
 // Using `password` doesn't meet password restrictions
 }
} catch (IllegalStateException e) {
 // The token doesn't match the one set earlier.
}

Uma chamada para resetPasswordWithToken() retorna false e a senha não muda quando a nova senha não atende às seguintes restrições:

  • O número de caracteres atende a qualquer restrição mínima de tamanho de senha. Chame getPasswordMinimumLength() para saber se um administrador de TI definiu uma restrição de duração.
  • O intervalo e a complexidade dos caracteres na senha atendem a uma restrição de composição. Chame getPasswordQuality() para saber se um administrador de TI definiu uma restrição de composição.

Se as restrições de qualidade da senha não exigirem a definição de uma senha, transmita null ou uma string vazia para resetPasswordWithToken() para remover a senha.

Desafio de segurança de perfil de trabalho

Um DPC em execução no modo de proprietário do perfil pode exigir que os usuários especifiquem um desafio de segurança para apps executados no perfil de trabalho. O sistema mostra o desafio de segurança quando o usuário tenta abrir qualquer app de trabalho. Se o usuário concluir o desafio de segurança, o sistema desbloqueará e descriptografará o perfil de trabalho, se necessário.

Como funciona o desafio de segurança do perfil de trabalho

  1. Se um DPC enviar uma intent ACTION_SET_NEW_PASSWORD, o sistema solicitará que o usuário configure um desafio de segurança.
  2. O DPC também pode enviar uma intent ACTION_SET_NEW_PARENT_PROFILE_PASSWORD para solicitar que o usuário defina um bloqueio de dispositivo.

Um DPC pode definir as políticas de senha do desafio de trabalho de maneira diferente das políticas de outras senhas do dispositivo. Por exemplo, o tamanho mínimo da resposta do desafio de dispositivo pode ser diferente do tamanho exigido para outras senhas. Um DPC define as políticas de desafio usando os métodos comuns DevicePolicyManager, como setPasswordQuality() e setPasswordMinimumLength().

Considerações

  • O DPC pode redefinir a senha no perfil de trabalho, mas não a senha (pessoal) do dispositivo. Se um usuário optar por definir as senhas pessoal e de trabalho como a mesma, resetPassword() no perfil de trabalho fará com que a senha seja redefinida apenas no perfil de trabalho, e a senha não será a mesma da tela de bloqueio do dispositivo.
  • Um DPC pode personalizar a tela de credenciais do desafio de trabalho usando setOrganizationColor() e setOrganizationName().
  • Os administradores de dispositivos não podem usar resetPassword() para limpar senhas ou mudar as que já estão definidas. Os administradores do dispositivo ainda podem definir uma senha, mas apenas quando o dispositivo não tem senha, PIN ou padrão.

Para mais informações, consulte getParentProfileInstance() e a documentação de referência em DevicePolicyManager.