Seguridad

Las funciones de esta guía describen las capacidades de administración de seguridad que puedes implementar en tu app de controlador de política de dispositivo (DPC). Este documento contiene muestras de código y también puedes usar la app de DPC de prueba como fuente de código de muestra para las funciones empresariales de Android.

Una app de DPC puede ejecutarse en el modo de propietario del perfil en dispositivos personales o en el modo de propietario del dispositivo en dispositivos completamente administrados. En esta tabla, se indica qué funciones están disponibles cuando el DPC se ejecuta en el modo de propietario del perfil o de propietario del dispositivo:

Función Propietario del perfil Propietario del dispositivo
Cómo inhabilitar el acceso a las apps
Cómo bloquear apps de fuentes desconocidas
Cómo restringir cuentas en Google Play
Habilitar la protección contra el restablecimiento de la configuración de fábrica de la empresa
Supervisar los registros de procesos empresariales y los informes de errores remotos
Cómo otorgar acceso a un certificado de cliente y quitarlo
Restablecimiento seguro de contraseñas
Desafío de seguridad para perfiles de trabajo

Inhabilitar el acceso a las apps

Para las organizaciones que desean impedir que los empleados jueguen o miren YouTube en sus dispositivos Android durante ciertos momentos del día o determinados días de la semana, un DPC puede inhabilitar temporalmente el acceso a las apps.

Para inhabilitar el acceso a las apps, un DPC que se ejecuta en el modo de propietario del dispositivo o propietario del perfil configura setPackagesSuspended() y, luego, la app seleccionada actúa como si estuviera inhabilitada (el selector de Google inhabilita la app). Cuando un usuario presiona la app, ve un diálogo del sistema que indica que la app está suspendida.

Mientras una app está suspendida, no puede iniciar actividades y se suprimen las notificaciones del paquete. Los paquetes suspendidos no aparecen en la pantalla de descripción general, no pueden mostrar diálogos (incluidos avisos y barras de notificaciones) y no pueden reproducir audio ni hacer vibrar el dispositivo.

Los selectores pueden llamar al método isPackageSuspended() para saber si se suspendió una app. Si deseas obtener detalles para configurar la suspensión de apps, consulta setPackagesSuspended.

Bloquea apps de fuentes desconocidas

Las apps que no se instalan desde Google Play (ni otras tiendas de aplicaciones confiables) se denominan apps de fuentes desconocidas. Los dispositivos y los datos pueden correr un mayor riesgo cuando las personas instalan estas apps.

Para evitar que alguien instale apps desde fuentes desconocidas, los componentes de administrador de los dispositivos completamente administrados y los perfiles de trabajo pueden agregar la restricción de usuario de DISALLOW_INSTALL_UNKNOWN_SOURCES.

Restricción en todo el dispositivo del perfil de trabajo

Cuando el administrador de un perfil de trabajo agrega DISALLOW_INSTALL_UNKNOWN_SOURCES, la restricción solo se aplica al perfil de trabajo. Sin embargo, el administrador de un perfil de trabajo puede establecer una restricción para todo el dispositivo estableciendo una configuración administrada para Google Play. La restricción en todo el dispositivo está disponible en Android 8.0 (o versiones posteriores) cuando la app de Google Play instalada es la versión 80812500 o posterior.

Para restringir la instalación de apps a Google Play, sigue estos pasos:

  1. Establece un paquete de configuración administrado para el paquete de Google Play com.android.vending.
  2. En el paquete, coloca un valor booleano para la clave verify_apps:device_wide_unknown_source_block.
  3. Agrega la restricción de usuario de ENSURE_VERIFY_APPS.

En el siguiente ejemplo, se muestra cómo puedes verificar que Google Play admita esta configuración y establecer el valor en 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);

La interfaz de usuario en la configuración del sistema permanece activa, pero el sistema bloquea la instalación de apps. Esta restricción afecta las instalaciones futuras; las apps instaladas anteriormente permanecerán en el dispositivo. Los usuarios de los dispositivos pueden seguir instalando apps en el perfil personal mediante Android Debug Bridge (adb).

Para obtener más información sobre fuentes desconocidas, consulta Opciones de distribución alternativas.

Cómo restringir cuentas en Google Play

A veces, una organización puede querer permitir que las personas agreguen Cuentas de Google personales (por ejemplo, para leer los correos electrónicos en Gmail), pero no quiere que la cuenta personal instale apps. Tu DPC puede establecer una lista de cuentas que las personas pueden usar en Google Play.

Los componentes de administrador de los dispositivos completamente administrados o los perfiles de trabajo pueden restringir las cuentas mediante una configuración administrada para Google Play. La restricción de la cuenta está disponible cuando la app de Google Play instalada es la versión 80970100 o posterior.

Para limitar la cantidad de cuentas en Google Play, haz lo siguiente:

  1. Establece un paquete de configuración administrado para el paquete de Google Play com.android.vending.
  2. En el paquete, coloca las direcciones de correo electrónico separadas por comas como un valor de string para la clave allowed_accounts.

En el siguiente ejemplo, se muestra cómo puedes limitar las cuentas:

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 Google Play solo a la cuenta de trabajo, establece allowed_accounts en la única cuenta administrada en cuanto tu DPC conozca la dirección de correo electrónico de la cuenta. Las cadenas vacías evitan que se use una cuenta en Google Play.

Habilitar la protección contra el restablecimiento de la configuración de fábrica de la empresa

Con la protección empresarial contra el restablecimiento de la configuración de fábrica, las organizaciones pueden especificar qué Cuentas de Google pueden aprovisionar un dispositivo cuya configuración de fábrica se haya restablecido.

La protección contra el restablecimiento de la configuración de fábrica del consumidor está diseñada para impedir el robo de dispositivos. Antes de permitir que alguien aprovisione el dispositivo después de un restablecimiento de la configuración de fábrica no autorizado (como con un EMM), el asistente de configuración requiere que el usuario se autentique en cualquier Cuenta de Google que haya estado en el perfil personal del dispositivo.

En un entorno empresarial, el restablecimiento de la configuración de fábrica es una herramienta importante para administrar los dispositivos de los empleados cuando este abandona la organización. Sin embargo, si la organización no conoce las credenciales de las cuentas de un empleado, la protección contra el restablecimiento de la configuración de fábrica puede bloquear la capacidad de la organización de enviar un dispositivo a otro empleado.

Control del aprovisionamiento después de un restablecimiento de la configuración de fábrica

Cuando se ejecuta en el modo de propietario del dispositivo, tu DPC puede usar setFactoryResetProtectionPolicy() para controlar qué cuentas están autorizadas a aprovisionar un dispositivo después de un restablecimiento de la configuración de fábrica. Si la estableces como null o una lista vacía, las cuentas autorizadas para aprovisionar un dispositivo después de un restablecimiento de la configuración de fábrica son las cuentas en el perfil personal del dispositivo.

Un DPC puede configurar estas cuentas durante la vida útil de un dispositivo completamente administrado.

  1. El administrador de TI puede usar el método people.get de la API de Personas con el valor especial me. De esta manera, se recupera el userId de la cuenta a la que accediste. El userID se muestra en la clave resourceName en el formato people/[userId] como una string de número entero. Es posible que las cuentas creadas recientemente no estén disponibles para restablecer la configuración de fábrica durante 72 horas.
  2. También puedes permitir que uno o más administradores de TI desbloqueen el dispositivo después de restablecer la configuración de fábrica. Haz que cada uno de estos administradores de TI acceda a su Cuenta de Google, que también siga el paso 1 y comparta su userId contigo para que puedas agregar estos userIds a la lista en el siguiente paso.
  3. El DPC establece una restricción de apps apropiada con setFactoryResetProtectionPolicy() para establecer la lista de userId que pueden aprovisionar un dispositivo con restablecimiento de la configuración de fábrica.
  4. El DPC habilita las cuentas que pueden aprovisionar dispositivos después de un restablecimiento de la configuración de fábrica mediante el envío del com.google.android.gms.auth.FRP_CONFIG_CHANGED de transmisión como un intent explícito para evitar que se pierdan debido a restricciones en 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);

Heredado

En el caso de los dispositivos que no pueden usar setFactoryResetProtectionPolicy(), que se introdujo con el nivel de API 30, tu DPC puede usar setApplicationRestrictions para agregar las cuentas elegidas a la configuración administrada factoryResetProtectionAdmin para el paquete 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);

Inhabilitar la protección contra el restablecimiento de la configuración de fábrica de la empresa

Para inhabilitar la protección contra el restablecimiento de la configuración de fábrica, tu DPC puede usar setFactoryResetProtectionPolicy() y pasar el 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);

Heredado

En el caso de los dispositivos que no pueden usar setFactoryResetProtectionPolicy(), que se introdujo con el nivel de API 30, tu DPC puede usar setApplicationRestrictions para establecer un par clave-valor true en la configuración administrada disableFactoryResetProtectionAdmin para el paquete 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);

Supervisar los registros de procesos empresariales y los informes de errores remotos

En tu consola de EMM, un administrador puede supervisar los dispositivos completamente administrados mediante informes de errores remotos y registros de procesos empresariales.

Registrar la actividad de los dispositivos empresariales

Un DPC que se ejecuta en el modo de propietario del dispositivo puede identificar actividad sospechosa realizando un seguimiento remoto de la actividad del dispositivo, incluidos los inicios de apps, la actividad de Android Debug Bridge (adb) y los desbloqueos de pantalla. Los registros de procesos no requieren el consentimiento del usuario.

Para habilitar o inhabilitar el registro, un DPC llama a setSecurityLoggingEnabled().

Cuando hay un nuevo lote de registros disponible, un DeviceAdminReceiver recibe la devolución de llamada onSecurityLogsAvailable(). Para recuperar los registros (después de recibir la devolución de llamada), un DPC llama a retrieveSecurityLogs().

Los DPC también pueden llamar a retrievePreRebootSecurityLogs() para recuperar los registros de seguridad generados en el ciclo de reinicio anterior. Este es el intervalo entre el último reinicio del dispositivo y el anterior. Los dispositivos que no admiten retrieveSecurityLogs() muestran null. Si tu app recupera registros con retrievePreRebootSecurityLogs() y retrieveSecurityLogs(), debes verificar si hay entradas duplicadas.
Nota: Esta función solo registra la actividad en dispositivos completamente administrados con un solo usuario o usuarios afiliados en el dispositivo. Esta función no está disponible en dispositivos personales, ya que registra la actividad en todo el dispositivo.

Este parámetro de configuración puede ser útil en la auditoría posterior al evento de seguridad, ya que registra los siguientes tipos de acciones:

  • Cada vez que se acaba de iniciar la app Esto podría ayudar a identificar si hay software malicioso que comienza con una app comprometida.
  • Intentos de desbloqueo fallidos en un dispositivo. Esto podría identificar si hay varios intentos de desbloqueo fallidos en un período corto.
  • Comandos de adb potencialmente dañinos cuando un usuario conecta el dispositivo a una computadora con un cable USB.

Si quieres obtener detalles para leer registros, consulta SecurityLog.

Mientras desarrollas y realizas pruebas, puedes forzar al sistema para que ponga a disposición cualquier registro de seguridad existente para tu DPC, sin necesidad de esperar un lote completo. En Android 9.0 (nivel de API 28) o versiones posteriores, ejecuta el siguiente comando de Android Debug Bridge (adb) en tu terminal:

adb shell dpm force-security-logs

El sistema limita la frecuencia con la que puedes usar la herramienta y, además, informa cualquier ralentización intencional en el resultado de la terminal. Si hay registros disponibles, tu DPC recibe la devolución de llamada onSecurityLogsAvailable().

Cómo solicitar un informe de errores de forma remota

Un DPC que se ejecuta en modo de propietario del dispositivo puede solicitar de forma remota informes de errores para los dispositivos de usuarios que tienen un solo usuario o usuarios afiliados. El informe de errores captura la actividad del dispositivo en el momento exacto en que se solicita el informe de errores, pero también puede incluir actividad de las últimas horas, según la frecuencia con la que se actualiza el búfer de logcat.

Para solicitar informes de errores de forma remota, el DPC llama a requestBugreport():

Cómo otorgar y quitar el acceso a un certificado de cliente

Si un DPC que se ejecuta en el modo de propietario de perfil o propietario del dispositivo otorga a una app de terceros la capacidad de administrar certificados, la app puede otorgarse acceso a los certificados que instala sin intervención del usuario. Para instalar un certificado al que puedan acceder todas las apps de un perfil, usa installKeyPair().

Para conocer qué parámetros configurar, consulta installKeyPair(). Esta característica funciona en conjunto con la API existente para administrar certificados.

Situación de implementación

Sin el método installKeyPair():

  • Los usuarios deben presionar el nombre del certificado y, luego, Permitir cada vez que quieran otorgar acceso a un certificado.
  • Los usuarios ven un mensaje cuando instalan un certificado y deben asignarle un nombre.

Con el método installKeyPair():

  • No es necesario que los usuarios presionen Permitir cada vez que quieran otorgar acceso a un certificado.
  • Los usuarios no pueden cambiar el nombre de los certificados.
  • Los administradores tienen más control, ya que pueden bloquear certificados para apps que no deberían tener acceso a certificados específicos.

Quitar un certificado de cliente

Después de otorgar acceso a un certificado de cliente, para quitar de forma remota los certificados de cliente instalados a través de installKeyPair(), llama a removeKeyPair().

Un DPC que se ejecuta en modo de propietario del dispositivo o de propietario del perfil, o el instalador de certificados delegados pueden llamar a removeKeyPair(). Esto quita un certificado y un par de claves privadas instalados bajo un alias de clave privada determinado.

Situación de implementación

Usa esta función si una organización migra a una forma de certificado de cliente más segura. Si un administrador lanza un certificado nuevo y su distribución tarda una cantidad significativa de tiempo, el administrador puede revocar los certificados obsoletos después de que se complete la migración.

Restablecimiento seguro de contraseña

Tu DPC puede restablecer la contraseña de un usuario autorizando el cambio con un token seguro y registrado previamente. Los propietarios de dispositivos y perfiles pueden llamar a las APIs de restablecimiento de contraseña segura para cambiar la contraseña de los dispositivos y perfiles de trabajo, respectivamente. El restablecimiento de contraseñas seguro reemplaza a resetPassword() con las siguientes mejoras:

Debes usar el restablecimiento seguro de contraseñas si tu compilación de DPC está orientada a Android 8.0 (nivel de API 26) o versiones posteriores. Llamar a resetPassword() arroja una SecurityException en los DPC que se orientan a Android 8.0 o versiones posteriores, por lo que es posible que debas actualizar tu DPC.

Configura y activa un token

Tu DPC debe configurar y activar un token antes de restablecer una contraseña. Dado que es posible que tu DPC no pueda usar el token de inmediato, debes establecer el token con anticipación al momento en que un administrador de TI podría necesitarlo.

Un token de restablecimiento de contraseña es un valor aleatorio criptográficamente seguro y debe tener al menos 32 bytes de longitud. Crea un token para cada dispositivo y perfil; no reutilices ni compartas los tokens generados.

Te recomendamos que almacenes tokens o los medios para desencriptar un token encriptado en un servidor. Si almacenas tokens de forma local en el almacenamiento encriptado por credenciales, tu DPC no podrá restablecer la contraseña hasta que el usuario desbloquee el dispositivo o el perfil. Si almacenas los tokens de forma local en el almacenamiento encriptado por dispositivo, y esto se ve comprometido, un atacante podría usar el token para obtener acceso a un perfil de trabajo o a un usuario principal.

Puedes generar un token nuevo en tu DPC o recuperar uno de un servidor. En el siguiente ejemplo, se muestra un DPC que genera un token y lo informa a un 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);
}

En la mayoría de los casos, tu DPC necesita activar un token después de configurarlo. Sin embargo, cuando el usuario no tiene una contraseña de pantalla de bloqueo, el sistema activa un token inmediatamente. Para activar un token, pídele al usuario que confirme sus credenciales. Tu DPC puede llamar al método createConfirmDeviceCredentialIntent() de KeyguardManager para obtener un Intent que inicie la confirmación. Explícale al usuario del dispositivo en la interfaz de usuario por qué le pides que se autentique. En el siguiente fragmento, se muestra cómo puedes activar un token en tu 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
}

Debes activar un token que establezca tu DPC antes de que se reinicie el dispositivo. Android almacena un token no activado en la memoria y no lo conserva después de un reinicio. Si el usuario reinicia el dispositivo antes de activar un token, tu DPC puede volver a configurar el mismo token o generar uno nuevo.

Tu DPC puede confirmar que un token está activo llamando a isResetPasswordTokenActive() y verificando que el resultado sea true.

Una vez que tu DPC establece y activa un token, este será válido hasta que el DPC borre o reemplace el token (o hasta que se restablezca la configuración de fábrica del dispositivo). El token es independiente de la contraseña y no se ve afectado si el usuario cambia o borra la contraseña.

Borra un token

Puedes llamar a clearResetPasswordToken() para borrar un token que tu DPC configuró antes. Es posible que debas revocar un token vulnerado o quitar la capacidad de restablecer la contraseña. En el siguiente ejemplo, se muestra cómo puedes hacer esto en tu 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 ...
}

Restablecer la contraseña

Cuando un administrador de TI necesite restablecer la contraseña, llama a resetPasswordWithToken() y pasa el token que tu DPC configuró y activó con anticipación:

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.
}

Una llamada a resetPasswordWithToken() muestra false y la contraseña no cambia cuando la contraseña nueva no cumple con las siguientes restricciones:

  • La cantidad de caracteres debe cumplir con cualquier restricción de longitud mínima de contraseñas. Llama a getPasswordMinimumLength() para saber si un administrador de TI estableció una restricción de longitud.
  • El rango y la complejidad de los caracteres de la contraseña cumplen con una restricción de composición. Llama a getPasswordQuality() para saber si un administrador de TI estableció una restricción de composición.

Si las restricciones de calidad de la contraseña no requieren que se establezca una contraseña, puedes pasar null o una string vacía a resetPasswordWithToken() para quitar la contraseña.

Comprobación de seguridad para perfiles de trabajo

Un DPC que se ejecuta en el modo de propietario de perfil puede requerir que los usuarios especifiquen un desafío de seguridad para las apps que se ejecutan en el perfil de trabajo. El sistema muestra el desafío de seguridad cuando el usuario intenta abrir una app de trabajo. Si el usuario completa con éxito la comprobación de seguridad, el sistema desbloquea el perfil de trabajo y lo desencripta, si es necesario.

Cómo funciona el desafío de seguridad del perfil de trabajo

  1. Si un DPC envía un intent ACTION_SET_NEW_PASSWORD, el sistema le solicita al usuario que configure una verificación de seguridad.
  2. El DPC también puede enviar un intent ACTION_SET_NEW_PARENT_PROFILE_PASSWORD para solicitarle al usuario que configure un bloqueo del dispositivo.

Un DPC puede establecer las políticas de contraseñas para la comprobación laboral de manera diferente a las políticas de otras contraseñas de dispositivos. Por ejemplo, la longitud mínima de la respuesta de comprobación del dispositivo puede ser diferente de la longitud requerida para otras contraseñas. Un DPC establece las políticas de desafío con los métodos habituales de DevicePolicyManager, como setPasswordQuality() y setPasswordMinimumLength().

Consideraciones

  • El DPC puede restablecer la contraseña en el perfil de trabajo, pero no puede restablecer la contraseña (personal) del dispositivo. Si un usuario elige establecer la misma contraseña personal y la de trabajo, la contraseña resetPassword() del perfil de trabajo se restablecerá solo en el perfil de trabajo, y la contraseña no será igual a la de la pantalla de bloqueo del dispositivo.
  • Un DPC puede personalizar la pantalla de credenciales para el desafío de trabajo usando setOrganizationColor() y setOrganizationName().
  • Los administradores de dispositivos no pueden usar resetPassword() para borrar contraseñas ni cambiar las que ya están configuradas. Los administradores de dispositivos aún pueden establecer una contraseña, pero solo cuando el dispositivo no tiene contraseña, PIN ni patrón.

Para obtener información adicional, consulta getParentProfileInstance() y la documentación de referencia en DevicePolicyManager.