
Añadir 2FA a una aplicación Android con Nexmo y Firebase Login
Tiempo de lectura: 7 minutos
En Firebase Auth Quickstart proporciona un gran tutorial sobre cómo añadir autenticación a tu aplicación, pero sin autenticación de dos factores (2FA), ¡es un poco inseguro! Añadir una capa extra de seguridad a tu aplicación es simple usando Nexmo Verify SDK. ¡Vamos a empezar!
Obtener la aplicación de ejemplo
Comienza clonando el repositorio de GitHub en tu Terminal. El repositorio original cambia constantemente, así que puedes clonar la rama inicial para el tutorial desde un repositorio bifurcado de nexmo-community.
Vonage API Account
To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.
This tutorial also uses a virtual phone number. To purchase one, go to Numbers > Buy Numbers and search for one that meets your needs.
Crear un nuevo proyecto en la consola Firebase
Inicie sesión en Firebase con tu Account de Google y ve a la consola. Crea un nuevo proyecto dándole un nombre y actualizando el país en el que resides. Una vez creado, haz clic en la opción "Añadir Firebase a tu aplicación Android". Introduce el nombre de tu paquete (por defecto para la app demo es: com.google.firebase.quickstart.auth) y el certificado de firma de depuración SHA-1. Ignora el archivo 'google-services.json' que se descarga ya que necesitarás descargar una nueva versión una vez que añadamos los métodos de inicio de sesión OAuth a la aplicación. No necesitas editar los archivos build.gradle, porque esto ya se ha hecho por ti en el proyecto de ejemplo.

Configurar los métodos de inicio de sesión
La aplicación de ejemplo viene con los siguientes métodos de inicio de sesión: Email/Contraseña, Anónimo y OAuth. Ambos proveedores de OAuth (Google y Twitter) deben estar configurados y la clave/secreto de la API de inicio de sesión de Twitter debe introducirse en 'ids.xml'. Si tienes problemas para encontrarlo, busca el archivo a través de la herramienta de búsqueda en la esquina superior derecha de Android Studio. Una vez configurados los métodos de autenticación, ve a la configuración del proyecto, descarga el archivo "google-services.json" y añádelo a la carpeta de la aplicación en la vista del proyecto.
Correo electrónico e inicio de sesión anónimo: Habilita ambos métodos en la sección Autenticación de la consola de Firebase.
Google: Google Sign In debería estar configurado para tu aplicación Android después de añadir el certificado de firma SHA-1 de depuración en la consola de Firebase. Habilita el método Google OAuth en la sección Autenticación de la consola.
Twitter: En la consola Firebase, habilita Twitter para la autenticación. A continuación, crea una nueva aplicación en el portal para desarrolladores de Twitter. Copia la URL de devolución de llamada (disponible en la sección Autenticación de Twitter de la consola Firebase) e introdúcela en el campo correspondiente para terminar de crear la aplicación de Twitter. Por último, ve a la Configuración de la aplicación de Twitter y haz clic en "Gestionar claves y tokens de acceso". Copia la clave de consumidor (API Key) y el secreto de consumidor (API Secret) en la consola Firebase y en 'ids.xml'.

Abrir y actualizar el proyecto
En Android Studio, elige la opción de abrir un proyecto existente. Navega hasta donde se clonó el repositorio y selecciona el 'auth' situado dentro de la carpeta 'quickstart-android'. Tendrás que actualizar el SDK de Android a la versión 25, las herramientas de compilación a la versión 25.0.0, y también actualizar la versión del JDK a 1.8, ya que necesitarás estas actualizaciones para compilar correctamente los archivos gradle. Una vez cargado el proyecto en Android Studio, instala cualquier dependencia que falte y sincroniza el proyecto para eliminar errores. Crea un AVD que utilice la API 24 para ejecutar correctamente la aplicación al final del tutorial. Por último, actualiza los Google Play Services de tu proyecto en Herramientas > Android > SDK Manager > SDK Tools a la versión 38.
Crear aplicación Nexmo
Después de crear una Account Nexmose le redirigirá al panel de control de Nexmo. Haga clic en la pestaña "Verify" y en "SDK", haga clic en el enlace "Your apps". Cree una nueva aplicación (con el tiempo máximo de inactividad establecido en Instant) y anote el ID de la aplicación y el secreto compartido. El tiempo máximo de inactividad es un parámetro que determina durante cuánto tiempo permanecerá verificado el usuario.

Añade las credenciales Nexmo (así como las OAuth si no lo hiciste en el paso anterior) a 'ids.xml'.
Añade la dependencia de Nexmo al Build.gradle de la aplicación
Añada la siguiente línea de código a su archivo Build.gradle a nivel de aplicación para incluir Nexmo Verify SDK en su aplicación como dependencia. Sincronice el archivo gradle para resolver cualquier dependencia que falte.
compile 'com.nexmo:verify:4.0.0' Añadir una nueva clase para el Cliente Nexmo
Crea una nueva clase en tu proyecto llamada 'TwoFactorApplication.java' e introduce el siguiente código en el archivo. Aquí creas el cliente Nexmo y le proporcionas los valores que almacenaste en 'ids.xml' previamente.
package com.google.firebase.quickstart.auth;
import android.app.Application;
import android.content.Context;
Import android.util.Log;
import com.nexmo.sdk.NexmoClient;
import com.nexmo.sdk.core.client.ClientBuilderException;
import com.nexmo.sdk.verify.client.VerifyClient;
public class TwoFactorApplication extends Application {
private VerifyClient verifyClient;
private NexmoClient nexmoClient;
private boolean verified;
private static final String TAG = “TWOFACTORAPPLICATION”;
public VerifyClient getVerifyClient(boolean verifiedValue) {
verified = verifiedValue;
return this.verifyClient;
}
@Override
public void onCreate() {
super.onCreate();
acquireVerifyClient();
}
public void acquireVerifyClient() {
Context context = getApplicationContext();
try {
this.nexmoClient = new NexmoClient.NexmoClientBuilder()
.context(context)
.applicationId(getResources().getString(R.string.nexmo_application_id))
.sharedSecretKey(getResources().getString(R.string.nexmo_shared_secret))
.build();
} catch (ClientBuilderException e) {
e.printStackTrace();
Log.d(TAG, e.toString());
return;
}
this.verifyClient = new VerifyClient(nexmoClient);
}
}En el archivo 'AndroidManifest.xml', añade los permisos necesarios para el SDK Verify y el nombre de la aplicación a la etiqueta de aplicación:
<application
android:name="com.google.firebase.quickstart.auth.TwoFactorApplication"
Añade el siguiente código a la BaseActivity
Declara las siguientes variables en la BaseActivity:
application (de tipo: TwoFactorApplication)
Verificado (de tipo: booleano)
En un método 'onCreate()' se lanza el contexto de aplicación devuelto llamando a 'this.getApplication();'. Esto devuelve la aplicación propietaria de la actividad (TwoFactorApplication). Luego creamos un método llamado 'addVerificationListener' para actuar como oyente para continuar el flujo de trabajo de la aplicación en una verificación 2FA exitosa. Dentro de este método obtenemos el VerifyClient proporcionado por la librería Nexmo y añadimos el método addVerifyListener().
//Import Statements
import java.io.IOException;
import com.nexmo.sdk.verify.client.VerifyClient;
import com.nexmo.sdk.verify.event.UserObject;
import com.nexmo.sdk.verify.event.VerifyClientListener;
import com.nexmo.sdk.verify.event.VerifyError;
Import android.os.Bundle;
//Declaration
public TwoFactorApplication twoFactorApp;
protected boolean verified;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
twoFactorApp = (TwoFactorApplication) this.getApplication();
}
protected void addVerificationListener() {
twoFactorApp.getVerifyClient(verified).addVerifyListener(new VerifyClientListener() {
@Override
public void onVerifyInProgress(VerifyClient verifyClient, UserObject user) {
}
@Override
public void onUserVerified(VerifyClient verifyClient, UserObject user) {
verified = true;
}
@Override
public void onError(VerifyClient verifyClient, VerifyError errorCode, UserObject user) {
}
@Override
public void onException(IOException exception) {
}
});
} Actualizar el código de GoogleSignInActivity
Mueva la llamada al método 'signIn()' de la función onClick al método 'onStart()' si el valor de 'verified' es igual a true. En su lugar, cuando el usuario haga clic en el botón de inicio de sesión, inicie la interfaz de usuario gestionada Verify SDK y llame al método 'addVerificationListener()'. Por último, cambie el valor de 'verified' a false cuando se detenga la Actividad para asegurarse de que el usuario tenga que iniciar sesión cada vez.
@Override
public void onStart() {
super.onStart();
if (verified == true) {
signIn();
}
mAuth.addAuthStateListener(mAuthListener);
}
@Override
public void onStop() {
super.onStop();
verified = false;
mAuth.signOut();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
@Override
public void onClick(View v) {
if (i == R.id.sign_in_button) {
twoFactorApp.getVerifyClient(verified).getVerifiedUserFromDefaultManagedUI();
addVerificationListener();
} else if (i == R.id.sign_out_button) {
signOut();
} else if (i == R.id.disconnect_button) {
revokeAccess();
}
} Actualizar el código de EmailPasswordActivity
Al igual que en el último paso, mueva la llamada al método de inicio de sesión de la función onClick al método 'onStart()'. En su lugar, inicie la interfaz de usuario gestionada Verify SDK y llame al método 'verificationCallback()' cuando el usuario haga clic en el botón de inicio de sesión. Una vez más, cambie 'verified' a false en el método 'onStop()'.
@Override
public void onStart() {
super.onStart();
if (verified == true) {
signIn(mEmailField.getText().toString(), mPasswordField.getText().toString());
}
mAuth.addAuthStateListener(mAuthListener);
}
@Override
public void onStop() {
super.onStop();
verified = false;
mAuth.signOut();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
@Override
public void onClick(View v) {
if (i == R.id.sign_in_button) {
twoFactorApp.getVerifyClient(verified).getVerifiedUserFromDefaultManagedUI();
addVerificationListener();
} else if (i == R.id.sign_out_button) {
signOut();
} else if (i == R.id.disconnect_button) {
revokeAccess();
}
}
private void signOut() {
mAuth.signOut();
verified = false;
updateUI(null);
} Actualizar el código de AnonymousAuthActivity
De nuevo, movemos la llamada al método de inicio de sesión de 'onClick' al método 'onStart()' para ser llamado si el usuario ha sido verificado. Cuando el usuario pulsa el botón de inicio de sesión, activa la interfaz de usuario gestionada Verify y llama al método 'addVerificationListener()' cuando el usuario pulsa el botón de inicio de sesión.
@Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
if (verified) {
signInAnonymously();
}
}
@Override
public void onStop() {
super.onStop();
mAuth.signOut();
verified = false;
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
private void signOut() {
mAuth.signOut();
verified = false;
updateUI(null);
}
@Override
public void onClick(View v) {
int i = v.getId();
if (i == R.id.button_anonymous_sign_in) {
twoFactorApp.getVerifyClient(verified).getVerifiedUserFromDefaultManagedUI();
addVerificationListener();
} else if (i == R.id.button_anonymous_sign_out) {
signOut();
} else if (i == R.id.button_link_account) {
linkAccount();
}
} Actualizar el código de TwitterLoginActivity
El flujo de inicio de sesión para TwitterLoginActivity es un poco más complicado que las actividades de inicio de sesión anteriores. El botón de inicio de sesión de Twitter inicializa la secuencia de inicio de sesión de Twitter OAuth. Aquí se permite a un usuario continuar con el flujo de inicio de sesión después de haber proporcionado el código PIN correcto (onUserVerified).
@Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
if(!verified) {
twoFactorApp.getVerifyClient(verified).getVerifiedUserFromDefaultManagedUI();
addVerificationListener();
}
}
@Override
public void onStop() {
super.onStop();
verified = false;
mAuth.signOut();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
private void signOut() {
mAuth.signOut();
verified = false;
Twitter.logOut();
updateUI(null);
}
mLoginButton.setCallback(new Callback() {
@Override
public void success(Result result) {
Log.d(TAG, "twitterLogin:success" + result);
verified = true;
handleTwitterSession(result.data);
}
@Override
public void failure(TwitterException exception) {
Log.w(TAG, "twitterLogin:failure", exception);
updateUI(null);
}
});Ahora todos los proveedores OAuth junto con los métodos de email/contraseña y login anónimo tienen un flujo que asegura que el usuario completa el segundo factor de autenticación para acceder a la Account. La versión habilitada para 2FA de este tutorial está disponible en la rama rama 'final' del repositorio.

El SDK de Verify le permite dedicar más tiempo al desarrollo de su aplicación al proporcionarle una solución de interfaz de usuario gestionada que le permite realizar solicitudes de verificación de forma segura y sencilla. Me encantaría saber si tienes alguna pregunta o comentario. Tweetéame https://twitter.com/sidsharma_27 o envíame un correo electrónico directamente.
