https://d226lax1qjow5r.cloudfront.net/blog/blogposts/how-to-add-two-factor-authentication-with-swift-and-vapor/blog_2fa_swift-vapor_1200x600.png

Cómo añadir autenticación de dos factores con Swift y Vapor

Publicado el November 24, 2020

Tiempo de lectura: 4 minutos

Introducción

La autenticación de dos factores (2FA) consiste en utilizar dos elementos diferentes para verificar tu identidad. Normalmente, algo que conoces, como una contraseña, junto con un código de verificación de un dispositivo físico, como un teléfono.

Este tutorial cubrirá cómo implementar un sistema de token de verificación con Vonage Verify API y Vapor. Una vez finalizado, podrás probar el sistema con una aplicación SwiftUI.

Requisitos previos

  • Xcode 12 y Swift 5 o superior.

  • Vapor 4.0 instalado en su máquina.

  • ngrok para exponer su máquina local a Internet.

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.

Crear un proyecto Vapor

Puede crear un proyecto Vapor utilizando el comando nuevo proyecto vapor new SwiftVerify -n en tu terminal. Una vez que el comando haya terminado cambia de directorio a la carpeta, que creó para ti usando cd SwiftVerify. Ahora puedes abrir el proyecto en Xcode usando vapor xcode.

Una vez abierto Xcode, comenzará a descargar las dependencias en las que se basa Vapor utilizando Swift Package Manager (SPM). Para ver las dependencias, puede abrir el archivo Package.swift archivo.

Creación de estructuras modelo

Una de las principales ventajas de utilizar Vapor es que puedes apoyarte en la seguridad de tipos del lenguaje Swift. Puedes modelar las entradas y salidas de tu servidor usando structs que se ajusten al protocolo Codable Vapor tiene un protocolo llamado Content para esto.

Comienza creando una estructura llamada Vonage para alojar todo el código del modelo. Cree un nuevo archivo en Fuentes > Aplicación llamado VonageClient.swift. En el nuevo archivo, crea la estructura Vonage struct:

public struct Vonage {
    private let apiKey: String
    private let apiSecret: String
    
    public init(apiKey: String, apiSecret: String) {
        self.apiKey = apiKey
        self.apiSecret = apiSecret
    }
}

La estructura se inicializa con la clave de API y el secreto de tu cuenta de API de Vonage y los almacena como propiedades locales para su uso posterior. Crearás dos puntos finales de API en el tutorial, uno para solicitar un código de verificación y otro para verificar si el código es correcto. Crea dos structs más dentro de la estructura Vonage para esto:

public struct RequestVerificationBody: Content {
    let number: String
    let brand: String = "SwiftVerify"
    var apiKey: String?
    var apiSecret: String?
    
    init(body: RequestVerificationBody, apiKey: String, apiSecret: String) {
        self.number = body.number
        self.apiKey = apiKey
        self.apiSecret = apiSecret
    }
    
    private enum CodingKeys: String, CodingKey {
        case number
        case brand
        case apiKey = "api_key"
        case apiSecret = "api_secret"
    }
}
    
public struct CheckVerificationBody: Content {
    let requestID: String
    let code: String
    var apiKey: String?
    var apiSecret: String?
    
    init(body: CheckVerificationBody, apiKey: String, apiSecret: String) {
        self.requestID = body.requestID
        self.code = body.code
        self.apiKey = apiKey
        self.apiSecret = apiSecret
    }
    
    private enum CodingKeys: String, CodingKey {
        case requestID = "request_id"
        case code
        case apiKey = "api_key"
        case apiSecret = "api_secret"
    }
}

Estos structs tienen un doble propósito; utilizar la entrada en el servidor y su salida. Las propiedades no opcionales y las propiedades sin valor por defecto, por ejemplo number en RequestVerificationBody se suministran cuando se realiza una petición al servidor.

El inicializador personalizado toma la versión de la estructura de la solicitud al servidor, la enriquece con las propiedades restantes y luego la utiliza para realizar una llamada a las API de Vonage. Las API de Vonage esperan campos en mayúsculas y minúsculas, por lo que los structs tienen la función CodingKeys para asignar los nombres de sus propiedades a su equivalente en mayúsculas y minúsculas.

Crear una solicitud de verificación

Debe realizar una llamada a la Verify API para crear una solicitud de verificación. El punto final al que desea llamar para crear una solicitud de verificación es /verify. Cree una función en la estructura Vonage struct para hacerlo:

public func requestVerification(with body: RequestVerificationBody, client: Client) -> EventLoopFuture<ClientResponse> {
    return client.post(URI(scheme: "https", host: "api.nexmo.com", path: "/verify/json")) { req in
        try req.content.encode(RequestVerificationBody(body: body, apiKey: apiKey, apiSecret: apiSecret), as: .json)
    }
}

La función toma el cuerpo de la petición realizada a su servidor y un archivo Client. Vapor's API de cliente permite realizar llamadas HTTP externas. Antes de que se envíe la petición post, el cuerpo se codifica con una estructura enriquecida RequestVerificationBody enriquecida. La función devuelve un EventLoopFuture que es un tipo genérico que hace referencia a un valor que aún no está disponible, en su caso, la respuesta de la solicitud de publicación.

El siguiente paso es definir la ruta, que es el punto final en su servidor que llamará a la función anterior. Abre routes.swiftcrea una instancia de la estructura de Vonage y define la nueva ruta:

func routes(_ app: Application) throws {
    let client = Vonage(apiKey: "API_KEY", apiSecret: "API_SECRET")
    
    app.post("request") { req -> EventLoopFuture<ClientResponse> in
        let body = try req.content.decode(Vonage.RequestVerificationBody.self)
        return client.requestVerification(with: body, client: req.client)
    }
}

Sustituya API_KEY y API_SECRET con tus credenciales del panel de la API de Vonage. En un entorno de producción, puedes usar la API de entorno para evitar exponer tus credenciales.

Cuando el /request servidor recibe una petición, decodificará el cuerpo de la petición en una estructura RequestVerificationBody y lo utilizará para llamar a la función que creó anteriormente. Por defecto flujo de trabajo 1 puede añadir una propiedad a la estructura RequestVerificationBodycon una clave de codificación asignada a workflow_id para cambiar esto.

El resultado de la llamada tendrá una propiedad status que, si es 0, significa que la acción se ha realizado correctamente. También incluirá una propiedad request_idque se utiliza para comprobar que el código es válido.

Compruebe el código

Comprobar si el código es válido es un proceso muy similar. Añada una función a la estructura Vonage para llamar a la Verify API, esta vez haciendo una petición post a /verify/check con un CheckVerificationBody struct:

public func checkVerification(with body: CheckVerificationBody, client: Client) -> EventLoopFuture<ClientResponse> {
    return client.post(URI(scheme: "https", host: "api.nexmo.com", path: "/verify/check/json")) { req in
        try req.content.encode(CheckVerificationBody(body: body, apiKey: apiKey, apiSecret: apiSecret), as: .json)
    }
}

A continuación, añada la ruta en routes.swift:

app.post("check") { req -> EventLoopFuture<ClientResponse> in
    let body = try req.content.decode(Vonage.CheckVerificationBody.self)
    return client.checkVerification(with: body, client: req.client)
}

De forma similar a la ruta de petición anterior, el resultado de la llamada tendrá una propiedad status donde 0 significa éxito.

Pruebe su servidor

Ahora que sus rutas están definidas, puede construir y ejecutar (CMD + R) su servidor. Una vez completado, el servidor se ejecutará localmente en el puerto 8080.

Terminal output when running project

Para exponer esto a Internet, puede utilizar ngrok. En tu terminal ejecuta ngrok http 8080. Se genera una URL pública que reenvía las llamadas a tu máquina local.

ngrok terminal output

Ahora que su servidor está disponible en Internet, puede realizar llamadas a él, para probar su servidor, puede utilizar la aplicación aplicación de prueba. Descargue el proyecto o clónelo con su terminal usando git clone git@github.com:nexmo-community/swiftui-two-factor-app.git.

Una vez descargado, abre el proyecto en Xcode. En el archivo VerifyModel.swift sustituya la cadena BASE_URL con la URL de reenvío de ngrok, a continuación, construir y ejecutar (CMD + R). ¡Puede introducir su número de teléfono, y recibirá un texto que puede introducir para verificar su número de teléfono!

Test app screenshots

¿Y ahora qué?

Puede encontrar el proyecto completo en GitHub. Hay más cosas que puedes hacer con la Verify API, como cambiar los tiempos de los eventos del flujo de trabajo o utilizarla para autorizar pagos. Más información en developer.nexmo.com.

Compartir:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiVonage Antiguo miembro del equipo

Abdul es desarrollador de Vonage. Ha trabajado en productos de consumo como ingeniero de iOS. En su tiempo libre, le gusta andar en bicicleta, escuchar música y asesorar a aquellos que están comenzando su viaje en la tecnología.