
Cómo añadir verificación telefónica y biométrica a su aplicación iOS
Tiempo de lectura: 10 minutos
Autenticación de dos factores (2FA) añade una capa adicional de seguridad para los usuarios que acceden a información sensible. Existen varios tipos de 2FA, por ejemplo:
Algo que sepas (nombre de usuario, contraseña)
Algo que tienes (tu teléfono/SIM)
Algo que eres (huella dactilar biométrica o escáner de retina)
En este tutorial, vamos a cubrir cómo usted puede agregar los tres de estos a una aplicación de iOS utilizando el Nexmo Verify SDK.
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.
Primeros pasos
El uso del SDK le permitirá añadir una capa adicional de seguridad. Garantizará que el usuario está vinculado a un dispositivo físico específico capturando el ID del dispositivo y un código PIN SMS/TTS. Certificar que el usuario está iniciando sesión desde el mismo dispositivo que el intento de inicio de sesión anterior reduce el spam/fraude.
Utilizaremos una aplicación de inicio (Swift 3) que utiliza una aplicación Back4App para el inicio de sesión del usuario (algo que ya sabes). Usaremos el SDK Verify para nuestra solución 2FA a través de SMS y TTS, y Touch ID de Apple para la verificación biométrica (algo que eres).
Configure su base de datos Back{4}App
Back{4}App es un backend que te permite crear y alojar aplicaciones Parse (muy útil desde que Parse cerró). Si no tienes una cuenta de Back{4}App, regístrate y crea una aplicación.

Una vez creada la aplicación, haz clic en el botón "Servidor" dentro de la sección "Configuración del núcleo". Se le dirigirá a una página con las credenciales de su nueva aplicación. Una vez que haya tomado nota de su ID de aplicación y clave de cliente, haga clic en el botón Atrás y vaya al "Panel de control" situado dentro de la sección "Configuración básica". Una vez redirigido al panel de control, diríjase a la sección "Núcleo", pulse "Editar" (en la esquina superior derecha) y añada las siguientes columnas a la clase "Usuario":
Comprobación" (número)
Ahorro (Numbers)
'sitekey' (Archivo - imagen para usuarios)
phoneNumber (cadena)
smsVerification' (valor booleano - permite a los usuarios activar la verificación por SMS al iniciar sesión)

Ahora que Back{4} apps está configurado, podemos empezar a crear nuestra aplicación de inicio.
Obtenga la aplicación Starter
Empecemos obteniendo la aplicación de inicio de GitHub. En tu Terminal, ejecuta lo siguiente:
El repositorio tiene una rama "getting-started" (pre-2FA), que te permite seguir el tutorial a continuación, y una rama "master", que contiene la versión final de este tutorial.
Abra el NexmoBankingApp.xcproj en XCode. Selecciona "NexmoBankingApp" para abrir la configuración de tu aplicación, y actualiza el "Bundle Identifier" del proyecto a un identificador válido y un nombre de aplicación registrado en el Developer Portal de Apple. Añade tu Back4App Application ID y Client Key en AppDelegate.swift.
let configuration = ParseClientConfiguration {
$0.applicationId = "BACK4APP_APP_ID"
$0.clientKey = "BACK4APP_CLIENT_KEY"
$0.server = "https://parseapi.back4app.com"
}
Parse.initializeWithConfiguration(configuration)Una vez introducido, dirígete a 'ViewController.swift' y añade un usuario ficticio a la base de datos descomentando la llamada a la función 'signUpDemoAccount()' en el método 'viewDidLoad()' de 'ViewController.swift':
override func viewDidLoad() {
super.viewDidLoad()
self.onlineID.delegate = self
signUpDemoAccount() //Uncomment to create dummy user
}Actualice los campos nombre de usuario, contraseña, correo electrónico y número de teléfono del PFUser en la función 'signUpDemoAccount()'.
func signUpDemoAccount() {
var user = PFUser()
user.username = "ENTERUSERNAME"
user.password = "ENTERPASSWORD"
user.email = "ENTEREMAILADDRESS@DEMO.NET"
user["phoneNumber"] = "ENTER-YOUR-PHONE-HERE"
user["smsVerification"] = false
user["checking"] = 5000
user["saving"] = 10000
let sitekeyImage = UIImage(named: "nexmo.png")
let imageData = UIImagePNGRepresentation(sitekeyImage!)
let imageFile = PFFile(name:"nexmo.png", data:imageData!)
user["sitekey"] = imageFile
user.signUpInBackground {
(success, error) -> Void in
if !success {
print(error.debugDescription)
} else {
print("User signed up.")
}
}
}
Ejecute la aplicación. El PFUser será creado y poblará el tablero de Back4App. Para evitar la creación de otro usuario cuando vuelva a iniciar la aplicación, debe comentar la llamada a la función 'signUpDemoAccount()' en el método 'viewDidLoad()' después de ejecutar la aplicación por primera vez.

Vuelva a ejecutar la aplicación. Podrás acceder a la información de la Account del usuario introduciendo las credenciales del usuario recién creado.
Bien, ahora vamos a reforzar la seguridad de la aplicación añadiendo 2FA.
Configuración de Nexmo App
Regístrese en una Account de Nexmo y vaya a su panel de control de cliente. Haga clic en la pestaña Verify y añada una nueva aplicación en 'Your Apps'. Configure su aplicación con un nombre, un tiempo de inactividad de Instant (tiempo máximo que el usuario permanecerá verificado; en este caso, los usuarios caducarán inmediatamente) y la longitud del código PIN.

A continuación, vamos a añadir el Nexmo Verify SDK. Verify SDK puede ser fácilmente añadido a tu proyecto usando Cocoapods. Crea un Podfile en el directorio de tu proyecto, añade el pod 'NexmoVerify' dentro del archivo, e instala el pod via Terminal. (Si no encuentra el pod, ejecute pod update para actualizar Cocoapods).
Inside Podfile
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
target 'NexmoBankingApp' do
# Comment this line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for NexmoBankingApp
pod ‘NexmoVerify’
endUna vez completada la instalación del pod, cierra Xcode y abre el nuevo archivo de proyecto 'xcworkspace'. Ya está listo para sumergirse en el código.
Si quieres saber más sobre el NexmoVerify puedes consultar el código fuente en Github.
Sumergirse en el código
Ahora que tiene sus dependencias en su lugar y ha obtenido las credenciales de la aplicación Nexmo, es el momento de añadirlas a su archivo 'AppDelegate'.
En AppDelegate.swift:
import NexmoVerify //Add to top of the file
fileprivate var appID = "YOUR_NEXMO_APP_ID"
fileprivate var sharedSecret = "YOUR_NEXMO_SHARED_SECRET" Inicializar Cliente Nexmo
Inicializar el Cliente Nexmo dentro de la función 'didFinishLaunchingWithOptions' del archivo 'AppDelegate'.
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
let configuration = ParseClientConfiguration {
$0.applicationId = "BACK4APP_APP_ID"
$0.clientKey = "BACK4APP_CLIENT_KEY"
$0.server = "https://parseapi.back4app.com"
}
Parse.initializeWithConfiguration(configuration)
NexmoClient.start(applicationId: appID, sharedSecretKey: sharedSecret)
return true
}
Añadir verificación biométrica a SitekeyViewController
Al iniciar sesión con éxito, ya que proporcionamos Back4Apps con la combinación de nombre de usuario y contraseña, la segunda pantalla lleva al usuario a su verificación sitekey donde vamos a añadir la verificación biométrica Touch ID.
Manejemos al usuario presionando el botón de inicio de sesión utilizando la API LocalAuthentication de Apple para solicitar una verificación Touch ID. Si el dispositivo no es compatible con Touch ID (no hay lector de huellas dactilares), el usuario se salta la verificación biométrica. Añade un segue ('signInStopped') para que cuando el usuario no pueda pasar con éxito la verificación Touch ID, se le cierre la sesión y se le devuelva a la página de inicio de sesión. En función de la configuración de preferencias de verificación por SMS del usuario, la función de flujo de trabajo Continuar activará una solicitud de verificación después de pasar a la pantalla de verificación del PIN (que crearemos a continuación) o mostrará la página de Account del usuario.
import LocalAuthentication
@IBAction func signInButton(_ sender: AnyObject) {
initialWorkFlow()
}
func initialWorkFlow() {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
let reason = "Authenticate with Touch ID"
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason, reply:
{(success, error) in
if success {
self.continueWorkflow()
}
else {
let alert = UIAlertController(title: "Failed Identification", message: "Touch ID Authentication Failed. Sign In process stopped.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Continue", style: .default) {
UIAlertAction in
PFUser.logOut()
self.performSegue(withIdentifier: "signInStopped", sender: self)
}
alert.addAction(defaultAction)
self.present(alert, animated: true, completion: nil)
}
})
}
else {
print("Touch ID not available")
self.continueWorkflow()
}
}
func continueWorkflow() {
if (PFUser.current()?["smsVerification"] as! Bool) {
self.performSegue(withIdentifier: "verifyPin", sender: self)
}
else {
self.performSegue(withIdentifier: "showAccount", sender: self)
}
}

Añadir View Controller para Verificación y Añadir Lógica 2FA al VC
Añade un nuevo archivo a tu proyecto ('VerifyPinViewController') y crea un controlador de vista en el Storyboard utilizando el Interface Builder. Abra el menú "Utilidades" haciendo clic en el botón situado en la parte superior derecha del Interface Builder. Haga clic en el botón 'Identity Inspector' e introduzca el nombre de la nueva clase después de hacer clic en el enlace el controlador de vista en el IB al archivo. A continuación, añada un cuadro de texto ('pinCode' - IBOutlet) junto con un botón ('verifyPin' - IBAction) para enviar el código pin. Crear un segue ('verifyPin') que está conectado a la 'SitekeyViewController' y el controlador de vista de nueva creación.
Dentro del método 'viewDidAppear' del nuevo controlador de vista añadido, llama a la función de abajo.
import Foundation
import UIKit
import Parse
import NexmoVerify
class VerifyViewController : UIViewController {
@IBOutlet weak var pinCode: UITextField!
@IBAction func verifyButton(_ sender: Any) {
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
let alert = UIAlertController( title: "User Phone Verification", message: "Your identity is being verified.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Continue", style: .default) {
UIAlertAction in
self.verifyUser()
}
alert.addAction(defaultAction)
present(alert, animated: true, completion: nil)
}
Toma el número de teléfono del usuario de la base de datos de Back4Apps y lanza una solicitud de verificación usando el método getVerifiedUser(). Crea un segue ('pinVerified') que esté conectado desde 'VerifyPinController' a 'StatementViewController'.
func verifyUser() {
VerifyClient.getVerifiedUser(countryCode: "US", phoneNumber: PFUser.current()?["phoneNumber"] as! String,
onVerifyInProgress: {
},
onUserVerified: {
self.performSegue(withIdentifier:"pinVerified", sender: self)
},
onError: { verifyError in
switch (verifyError) {
case .invalidPinCode:
UIAlertView(title: "Wrong Pin Code", message: "The pin code you entered is invalid.", delegate: nil, cancelButtonTitle: "Try again!").show()
case .invalidCodeTooManyTimes:
let alert = UIAlertController(title: "Unsucessful Identification", message: "Logging out. Goodbye.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Goodbye", style: .default) {
UIAlertAction in
VerifyClient.cancelVerification() { error in
if let error = error {
// something wen't wrong whilst attempting to cancel the current verification request
return
}
}
self.performSegue(withIdentifier: "logout", sender: self)
}
alert.addAction(defaultAction)
self.present(alert, animated: true, completion: nil)
default:
print(verifyError.rawValue)
break
}
})
}Además, llame al método checkPinCode proporcionado por el cliente Nexmo cuando se pulse el botón para verificar el PIN proporcionado por el usuario.
@IBAction func verifyButton(sender: AnyObject) {
if pinCode.text!.isEmpty {
let alert = UIAlertController(title: "Enter Pin Code", message: "Please check your phone and enter the pin code send via SMS.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Back", style: .default, handler: nil)
alert.addAction(defaultAction)
present(alert, animated: true, completion: nil)
}
else {
VerifyClient.checkPinCode(pinCode.text!)
}
} Añadir la opción de verificación por SMS al iniciar sesión
A continuación, añada la lógica que permite al usuario activar la verificación por SMS. Añade un elemento switch UI a tu 'StatementViewController' como un IBOutlet. Añade también una variable booleana que contenga el valor del interruptor. El valor del interruptor se almacena en la base de datos al cerrar la sesión del usuario. Si el interruptor está activado, se activará una verificación por SMS en el siguiente inicio de sesión. Después de que aparezca la vista, compruebe los valores de las cuentas corrientes y de ahorro para validar que no son nulos.
@IBOutlet weak var switch2FA: UISwitch!
var switchBoolValue:Bool!
func logout() {
if switchBoolValue == true {
let alert = UIAlertController(title: "SMS Verification", message: "Perform SMS verification on login?", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Continue", style: .default) {
UIAlertAction in
PFUser.current()?["smsVerification"] = true
PFUser.current()?.saveInBackground()
self.performSegue(withIdentifier: "logoutUser", sender: self)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(defaultAction)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
}
else {
print("SMS FALSE successful logout")
PFUser.current()?["smsVerification"] = false
PFUser.current()?.saveInBackground()
self.performSegue(withIdentifier: "logoutUser", sender: self)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
if (PFUser.current()?["saving"] == nil || PFUser.current()?["checking"] == nil) {
PFUser.logOut()
self.performSegue(withIdentifier: "logout", sender: self)
}
else {
switch2FA.addTarget(self, action: #selector(StatementViewController.switchMoved), for: UIControlEvents.valueChanged)
switchBoolValue = true
}
}
func switchMoved() { // stores value for the switch
if switch2FA.isOn {
switchBoolValue = true
print("switch on")
}
else {
switchBoolValue = false
print("switch off")
}
}
Ejecutar 2FA en Usuario Verificado en Acción Específica


Para transacciones más seguras, como una transferencia de fondos de un usuario de una cuenta a otra, puede activar una solicitud de verificación para confirmar la acción de solicitud del usuario.
Añade un nuevo controlador ('TransferPinViewController') con un campo de texto ('pinCode' - IBOutlet) y un botón ('verifyButton' - IBAction) en el archivo del storyboard. Crear un segue ('verifyTransfer') desde el 'TransferViewController' al nuevo controlador de vista creado.
Los cheques, los ahorros, el importe de la transferencia, la fuente de la transferencia y el total después de la transferencia se enviarán con el segue. Actualiza las funciones de transferencia ('checkingToSaving' y 'savingToChecking') para enviar al usuario al 'TransferPinViewController' tras verificar el saldo disponible para la transferencia.
func checkingToSaving() {
print("checkingToSaving")
if checkingAmount - transferAmt > 0 {
print("NEWTOTAL: \(checkingAmount - transferAmt)")
transferSource = "checkingToSaving"
afterTransferTotal = checkingAmount - transferAmt
self.performSegue(withIdentifier: "verifyTransfer", sender: self)
}
else {
print("ERROR")
let alert = UIAlertController(title: "Transfer Error", message: "You do not have the requested transfer amount in your Checking Account. Please try again.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Back", style: .default, handler: nil)
alert.addAction(defaultAction)
self.present(alert, animated: true, completion: nil)
}
}
func savingToChecking() {
if savingAmount - transferAmt > 0 {
transferSource = "savingToChecking"
afterTransferTotal = savingAmount - transferAmt
self.performSegue(withIdentifier: "verifyTransfer", sender: self)
}
else {
print("ERROR")
let alert = UIAlertController(title: "Transfer Error", message: "You do not have the requested transfer amount in your Savings Account. Please try again.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Back", style: .default, handler: nil)
alert.addAction(defaultAction)
self.present(alert, animated: true, completion: nil)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any!) {
if (segue.identifier == "verifyTransfer") {
let verifyTransferVC = segue.destination as! TransferPinViewController;
verifyTransferVC.checkingAmount = checkingAmount
verifyTransferVC.savingAmount = savingAmount
verifyTransferVC.transferAmt = transferAmt
verifyTransferVC.transferSource = transferSource
verifyTransferVC.afterTransferTotal = afterTransferTotal
}
}
Crea una función que llame al método 'getVerifiedUser' para iniciar la verificación del usuario. Esta función debe ser llamada cuando se carga la vista.
import NexmoVerify //Add to top of the file
override func viewDidLoad() {
super.viewDidLoad()
verify()
}
func verify() {
VerifyClient.getVerifiedUser(countryCode: "US", phoneNumber: PFUser.current()?["phoneNumber"] as! String,
onVerifyInProgress: {
},
onUserVerified: {
self.performTransfer()
},
onError: { verifyError in
switch (verifyError) {
case .invalidPinCode:
UIAlertView(title: "Wrong Pin Code", message: "The pin code you entered is invalid.", delegate: nil, cancelButtonTitle: "Try again!").show()
case .invalidCodeTooManyTimes:
let alert = UIAlertController(title: "Unsucessful Identification", message: "Logging out. Goodbye.", preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "Goodbye", style: .default) {
UIAlertAction in
VerifyClient.cancelVerification() { error in
if let error = error {
// something wen't wrong whilst attempting to cancel the current verification request
return
}
}
self.performSegue(withIdentifier: "logout", sender: self)
}
alert.addAction(defaultAction)
self.present(alert, animated: true, completion: nil)
default:
print(verifyError.rawValue)
break
}
})
}Como se muestra arriba, llama a la función 'performTransfer' dentro del método callback 'onUserVerified'. Como hicimos en el controlador de vista de verificación anterior, llame al método 'checkPinCode' dentro de su botón IBAction para comprobar el PIN proporcionado por el usuario. Por último, crea un segue ('sucessfulTransfer') desde el 'VerifyPinViewController' al 'StatementViewController' para devolver al usuario a la pantalla de Statements en caso de transferencia exitosa.
@IBOutlet weak var pincode: UITextField!
@IBAction func checkPin(sender: AnyObject) {
VerifyClient.checkPinCode(pincode.text!)
}
func performTransfer() {
if transferSource == "checkingToSaving" {
checkingAmount = checkingAmount - transferAmt
savingAmount = savingAmount + transferAmt
PFUser.current()?["checking"] = checkingAmount
PFUser.current()?["saving"] = savingAmount
PFUser.current()?.saveInBackground()
OperationQueue.main.addOperation {
self.performSegue(withIdentifier: "successfulTransfer", sender: self)
}
}
else if transferSource == "savingToChecking"{
savingAmount = savingAmount - transferAmt
checkingAmount = checkingAmount + transferAmt
PFUser.current()?["saving"] = savingAmount
PFUser.current()?.saveInBackground()
PFUser.current()?["checking"] = checkingAmount
PFUser.current()?.saveInBackground()
OperationQueue.main.addOperation {
self.performSegue(withIdentifier: "successfulTransfer", sender: self)
}
}
}Eso es todo lo que necesitas hacer para habilitar la autenticación de dos factores en tu aplicación iOS utilizando Verify SDK de Nexmo.
Hoy en día, habilitar 2FA es imprescindible para gestionar el acceso a información sensible y asegurar la correcta identificación del usuario. En este tutorial, aseguramos la aplicación demo con los tres métodos de autenticación. Usando un combo de nombre de usuario y contraseña, aseguramos algo que el usuario conoce (credenciales de acceso). Implementando Verify iOS SDK de Nexmo, nos aseguramos de verificar algo que el usuario tiene (acceso a su teléfono capturando el ID del dispositivo del usuario y la dirección IP). Añadiendo Touch ID de Apple nos aseguramos de algo que el usuario es (él mismo) mediante el uso de la verificación biométrica.
El proceso de añadir 2FA es sencillo utilizando el SDK de Verify y la API de autenticación local de Apple, y añade una capa extra de seguridad que protege la información sensible de tus usuarios.
No dude en enviarme sus opiniones o preguntas a través de Twitter @sidsharma_27.
