Autenticación en wearables

Las apps para Wear OS pueden ejecutarse de manera independiente sin una app complementaria. Es decir, una app para Wear OS necesita administrar la autenticación por su cuenta cuando accede a datos de Internet. Sin embargo, el tamaño pequeño de la pantalla del reloj y las capacidades de entrada reducidas limitan las opciones de autenticación que puede usar una app para Wear OS.

En esta guía, se tratan los métodos de autenticación que se recomienda usar en las apps para Wear OS y las alternativas disponibles si dichos métodos no se ajustan al caso práctico de una app.

Para obtener más información sobre cómo diseñar una buena experiencia de acceso, consulta la guía de UX de acceso.

Modo de Invitado

No se solicita autenticación para todas las funcionalidades. En su lugar, proporciona tantas funciones como sea posible para el usuario, sin necesidad de que acceda.

Es posible que los usuarios descubran e instalen tu app para Wear sin haber usado la app para dispositivos móviles. Por lo tanto, es posible que no tengan una cuenta y no conozcan las funciones que ofrece. Asegúrate de que la funcionalidad del modo de invitado muestre con precisión las funciones de tu app.

Es posible que algunos dispositivos permanezcan desbloqueados por más tiempo

En los dispositivos compatibles que ejecutan Wear OS 5 o versiones posteriores, el sistema detecta si el usuario lleva el dispositivo en la muñeca. Si el usuario desactiva la detección de muñeca y, luego, se quita el dispositivo de la muñeca, el sistema mantiene el dispositivo desbloqueado durante un período más largo de lo que lo haría de otra manera.

Si tu app requiere un nivel de seguridad más alto, como cuando se muestran datos potencialmente sensibles o privados, primero verifica si la detección de muñeca está habilitada:

val wristDetectionEnabled =
        isWristDetectionAutoLockingEnabled(applicationContext)

Si el valor que se muestra de este método es false, pídele al usuario que acceda a una cuenta en tu app antes de mostrar contenido específico del usuario.

Métodos de autenticación recomendados

Usa los siguientes métodos de autenticación con el objeto de habilitar apps independientes para Wear OS y obtener credenciales de autenticación de usuarios:

Pasa tokens mediante la capa de datos

La app complementaria para teléfonos puede transferir datos de autenticación de forma segura a la app para Wear OS con la capa de datos de wearables. Transfiere credenciales como mensajes o elementos de datos.

Por lo general, este tipo de autenticación no requiere ninguna acción por parte del usuario. Sin embargo, evita realizar la autenticación sin informarle al usuario que está accediendo. Puedes hacer esto con una pantalla simple que se pueda descartar y que muestre que la cuenta se está transfiriendo desde un dispositivo móvil.

Importante: Tu app para Wear debe ofrecer al menos un método más de autenticación, ya que esta opción solo funciona en relojes vinculados con Android cuando está instalada la app para dispositivos móviles correspondiente. Proporciona un método de autenticación alternativo para los usuarios que no tengan la app para dispositivos móviles correspondiente o cuyos dispositivos Wear OS estén vinculados con un dispositivo iOS.

Pasa tokens con la capa de datos de la app para dispositivos móviles, como se muestra en el siguiente ejemplo:

val token = "..." // Auth token to transmit to the wearable device.
val dataClient: DataClient = Wearable.getDataClient(context)
val putDataReq: PutDataRequest = PutDataMapRequest.create("/auth").run {
    dataMap.putString("token", token)
    asPutDataRequest()
}
val putDataTask: Task<DataItem> = dataClient.putDataItem(putDataReq)

Detecta eventos de cambio de datos en la app de reloj, como se muestra en el siguiente ejemplo:

val dataClient: DataClient = Wearable.getDataClient(context)
dataClient.addListener{ dataEvents ->
    dataEvents.forEach { event ->
        if (event.type == DataEvent.TYPE_CHANGED) {
            val dataItemPath = event.dataItem.uri.path ?: ""
            if (dataItemPath.startsWith("/auth")) {
                val token = DataMapItem.fromDataItem(event.dataItem).dataMap.getString("token")
                // Display interstitial screen to notify the user they are being signed in.
                // Then, store the token and use it in network requests.
            }
        }
    }
}

Para obtener más información sobre el uso de la capa de datos de wearables, consulta Cómo enviar y sincronizar datos en Wear OS.

Usa OAuth 2.0

Wear OS admite dos flujos basados en OAuth 2.0, que se describen en las siguientes secciones:

  • Otorgamiento de código de autorización con clave de prueba para el intercambio de código (PKCE), como se define en RFC 7636
  • Otorgamiento de autorización de dispositivo, como se define en RFC 8628

Nota: Para ayudar a garantizar que tu app no se cierre cuando se active el modo ambiente en el reloj, habilita la opción "Siempre encendida" con AmbientModeSupport.attach en la actividad que realiza la autenticación. Para obtener más información sobre las prácticas recomendadas del modo ambiente, consulta Cómo mantener tu app visible en Wear.

Clave de prueba para el intercambio de código (PKCE)

Para usar la PKCE de manera efectiva, usa RemoteAuthClient.

A fin de realizar una solicitud de Auth a un proveedor de OAuth desde tu app para Wear OS, crea un objeto OAuthRequest. Este objeto consiste en una URL que dirige a tu extremo de OAuth para obtener un token y un objeto CodeChallenge. A continuación, te mostramos un código de ejemplo para crear una solicitud de Auth:

val request = OAuthRequest.Builder(this.applicationContext)
    .setAuthProviderUrl(Uri.parse("https://...."))
    .setClientId(clientId)
    .setCodeChallenge(codeChallenge)
    .build()

Una vez que compiles la solicitud de Auth, envíala a la app complementaria con el método sendAuthorizationRequest().

val client = RemoteAuthClient.create(this)
client.sendAuthorizationRequest(request,
    { command -> command?.run() },
    object : RemoteAuthClient.Callback() {
        override fun onAuthorizationResponse(
            request: OAuthRequest,
            response: OAuthResponse
        ) {
            // Extract the token from the response, store it and use it in network requests.
        }

        override fun onAuthorizationError(errorCode: Int) {
            // Handle error
        }
    }
)

Esta solicitud activará una llamada a la app complementaria, que luego presentará una IU de autorización en un navegador web en el teléfono celular del usuario. El proveedor de OAuth 2.0 autenticará al usuario y obtendrá su consentimiento para los permisos solicitados. La respuesta se envía a la URL de redireccionamiento que se genera automáticamente.

Luego de que la solicitud se procesa correctamente o falla, el servidor de OAuth 2.0 redirecciona a la URL especificada en la solicitud. Si el usuario aprueba la solicitud de acceso, la respuesta contendrá un código de autorización. Si no la aprueba, entonces esta contendrá un mensaje de error.

La respuesta lucirá como una cadena de consulta y se parecerá a uno de los ejemplos siguientes:

  https://wear.googleapis.com/3p_auth/com.your.package.name?code=xyz
  https://wear.googleapis-cn.com/3p_auth/com.your.package.name?code=xyz

Se cargará una página que dirigirá al usuario a la app complementaria, la cual verificará la URL de respuesta y la retransmitirá a la app de reloj de terceros con la API de onAuthorizationResponse.

Una vez hecho esto, la app de reloj podrá intercambiar el código de autorización por un token de acceso.

Nota: Una vez que se haya compilado el objeto OAuthRequest, podrás acceder a redirectUrl para dirigirte a la URL de redireccionamiento.

Otorgamiento de autorización de dispositivo

Cuando se usa el otorgamiento de autorización de dispositivo, el usuario abre el URI de verificación en otro dispositivo. Luego, el servidor de autorización les solicita aprobar o rechazar la solicitud.

Con el objetivo de facilitar este proceso, usa un RemoteActivityHelper para abrir una página web en el dispositivo móvil vinculado del usuario, como se muestra en el siguiente ejemplo:

// Request access from the authorization server and receive Device Authorization Response.
val verificationUri = "..." // Extracted from the Device Authorization Response.
RemoteActivityHelper.startRemoteActivity(
    this,
    Intent(Intent.ACTION_VIEW)
        .addCategory(Intent.CATEGORY_BROWSABLE)
        .setData(Uri.parse(verificationUri)),
    null
)
// Poll the authorization server to find out if the user completed the user authorization
// step on their mobile device.

Si tienes una app para iOS, usa vínculos universales e intercepta este intent en tu app, en lugar de depender del navegador para autorizar el token.

Otros métodos de autenticación

Wear OS admite otros métodos de acceso, que se describen en las siguientes secciones.

Acceso con Google

El Acceso con Google permite que el usuario acceda con su Cuenta de Google actual. Es fácil de incorporar y ofrece la mejor experiencia del usuario, especialmente si ya lo implementas en tus apps para dispositivos de mano.

Si no pueden utilizarse los métodos de autenticación recomendados descritos, la siguiente solución preferida es el Acceso con Google, ya que también funciona bien con el sistema iOS. En la siguiente sección, se describe cómo completar una integración básica con el Acceso con Google.

Requisitos previos

Antes de comenzar a integrar el Acceso con Google en tu app para Wear OS, debes configurar un proyecto de la Consola de API de Google y tu proyecto de Android Studio. Para obtener más información, consulta Comienza a integrar Acceso con Google en tu app para Android.

Existen dos requisitos previos adicionales para usar el Acceso con Google en una app o sitio que se comunica con un servidor de backend:

  • Crea un ID de cliente de aplicación web de OAuth 2.0 para tu servidor de backend. Este ID de cliente es diferente del ID de cliente de tu app. Para obtener más información, consulta Cómo habilitar el acceso al servidor.
  • Identifica al usuario cuya sesión está activa de forma segura en el servidor. Para ello, envía el token de ID del usuario mediante HTTPS. Para aprender a autenticar tu usuario en el servidor de backend, consulta Autenticación con un servidor de backend.

Integra el Acceso con Google en tu app

Revisa los siguientes pasos, que se detallan en las secciones a continuación, e impleméntalos para integrar el Acceso con Google en tu app para Wear OS:

  1. Configura el Acceso con Google.
  2. Agrega un botón de Acceso con Google.
  3. Inicia el flujo de acceso cuando se presione el botón de acceso.

Configura el Acceso con Google y compila un objeto GoogleApiClient

En el método onCreate() de tu actividad de acceso, configura el Acceso con Google para solicitar los datos del usuario que requiere tu app. Luego, crea un objeto GoogleApiClient con acceso a la API de Acceso con Google y las opciones que especificaste. Estos pasos se muestran en el siguiente ejemplo:

public class MyNewActivity extends AppCompatActivity {

    private static final int RC_SIGN_IN = 9001;

    private GoogleSignInClient mSignInClient;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        GoogleSignInOptions options =
                new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
                        .build();

        mSignInClient = GoogleSignIn.getClient(this, options);
    }
}

Agrega un botón de Acceso con Google a tu app

Para agregar un botón de Acceso con Google, sigue los pasos a continuación:

  1. Agrega el SignInButton al diseño de tu app:
  2.  <com.google.android.gms.common.SignInButton
     android:id="@+id/sign_in_button"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content" />
    
  3. En el método onCreate() de tu app, registra el OnClickListener de tu botón para que el usuario inicie sesión cuando lo presione:
  4. Kotlin

    findViewById<View>(R.id.sign_in_button).setOnClickListener(this)
    

    Java

    findViewById(R.id.sign_in_button).setOnClickListener(this);
    

Inicia el flujo de acceso y crea un intent de acceso

Para controlar las presiones del botón de acceso en tu método onCLick(), crea un intent de acceso con el método getSignInIntent(). Luego, inicia el intent con el método startActivityForResult().

Intent intent = mSignInClient.getSignInIntent();
startActivityForResult(intent, RC_SIGN_IN);

Se le solicita al usuario que seleccione una Cuenta de Google para acceder. Si solicitaste datos que exceden el perfil, el correo electrónico y el OpenID, también se le pedirá al usuario acceso a esos recursos.

Por último, en el método onActivityResult de la actividad, recupera el resultado de acceso con getSignInResultFromIntent. Una vez que lo hagas, podrás verificar si el acceso fue exitoso con el método isSuccess. Si el acceso se realiza correctamente, puedes llamar al método getSignInAccount para obtener un objeto GoogleSignInAccount que contiene información sobre el usuario que accedió, como su nombre. Estos pasos se muestran en el siguiente ejemplo:

Kotlin

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    super.onActivityResult(requestCode, resultCode, data)

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...).
    if (requestCode == RC_SIGN_IN) {
        Auth.GoogleSignInApi.getSignInResultFromIntent(data)?.apply {
            if (isSuccess) {
                // Get account information.
                fullName = signInAccount?.displayName
                mGivenName = signInAccount?.givenName
                mFamilyName = signInAccount?.familyName
                mEmail = signInAccount?.email
            }
        }
    }
}

Java

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);

    // Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...).
    if (requestCode == RC_SIGN_IN) {
        GoogleSignInResult signInResult = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
        if (signInResult.isSuccess()) {
            GoogleSignInAccount acct = signInResult.getSignInAccount();

            // Get account information.
            fullName = acct.getDisplayName();
            givenName = acct.getGivenName();
            familyName = acct.getFamilyName();
            email = acct.getEmail();
        }
    }
}

Para ver una app de ejemplo que implementa el Acceso con Google, consulta el ejemplo de Acceso con Google de Horologist en GitHub.

Autenticación de código personalizada

Como alternativa a los métodos de autenticación descritos anteriormente, puedes pedirle al usuario que se autentique desde otro dispositivo, como un teléfono celular o una tablet, y obtenga un código numérico de corta duración. Luego, el usuario ingresa el código en su dispositivo Wear OS para confirmar su identidad y recibe un token de Auth.

Este flujo de autenticación usa el módulo de acceso de tu app o una integración manual en el código un método de acceso del proveedor externo de Auth. Si bien este método de autenticación requiere trabajo manual y un esfuerzo adicional para que sea más seguro, puedes usarlo si necesitas obtener autenticación con anterioridad en tus apps independientes para Wear OS.

El flujo de Auth para esta configuración funciona de la siguiente manera:

  1. El usuario realiza una acción con la app de Wear OS que requiere autorización.
  2. La app para Wear OS presenta al usuario una pantalla de autenticación y le indica que debe ingresar un código desde una URL especificada.
  3. El usuario cambia a un dispositivo móvil, una tablet o una PC, inicia un navegador, navega a la URL especificada en la app para Wear OS y accede.
  4. El usuario recibe un código numérico de corta duración que debe ingresar en la pantalla de autenticación de la app para Wear OS con el teclado integrado en Wear OS:

  5. Desde este punto, puedes usar el código ingresado como prueba de que es el usuario correcto y, luego, intercambiarlo por un token de Auth almacenado y protegido en un dispositivo Wear OS para las llamadas autenticadas que se desvían.

Nota: El código que genera el usuario debe ser solo numérico y no puede contener caracteres alfabéticos.

En el siguiente gráfico, se muestra el flujo de Auth: