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

Comment ajouter l'authentification à deux facteurs avec Swift et Vapor

Publié le November 24, 2020

Temps de lecture : 4 minutes

Introduction

L'authentification à deux facteurs (2FA) consiste à utiliser deux éléments différents pour vérifier votre identité. En général, il s'agit de quelque chose que vous connaissez, comme un mot de passe, associé à un code de vérification provenant d'un appareil physique, comme un téléphone.

Ce tutoriel explique comment mettre en œuvre un système de jetons de vérification avec l'API Verify de Vonage et Vapor. Une fois terminé, vous pouvez tester le système avec une application SwiftUI.

Conditions préalables

  • Xcode 12 et Swift 5 ou supérieur.

  • Vapor 4.0 installé sur votre machine.

  • ngrok pour exposer votre machine locale à l'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.

Créer un projet vapeur

Vous pouvez créer un projet Vapor en utilisant la commande new project vapor new SwiftVerify -n dans votre terminal. Une fois la commande terminée, changez de répertoire dans le dossier qu'elle a créé pour vous à l'aide de la commande cd SwiftVerify. Vous pouvez maintenant ouvrir le projet dans Xcode en utilisant vapor xcode.

Une fois Xcode ouvert, il commencera à télécharger les dépendances sur lesquelles Vapor s'appuie en utilisant le Swift Package Manager (SPM). Pour voir les dépendances, vous pouvez ouvrir le fichier Package.swift fichier.

Créer les structures du modèle

L'un des principaux avantages de l'utilisation de Vapor est que vous pouvez vous appuyer sur la sécurité des types du langage Swift. Vous pouvez modéliser les entrées et les sorties de votre serveur à l'aide de structures conformes au protocole Codable Vapor dispose d'un protocole appelé Content pour cela.

Commencez par créer une structure appelée Vonage pour abriter tout le code du modèle. Créez un nouveau fichier sous Sources > App appelé VonageClient.swift. Dans ce nouveau fichier, créez la 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 structure est initialisée avec la clé API et le secret de votre compte API Vonage et les stocke en tant que propriétés locales pour une utilisation ultérieure. Vous allez créer deux points d'extrémité API dans ce tutoriel, l'un pour demander un code de vérification et l'autre pour vérifier si le code est correct. Créez deux autres structures dans la structure Vonage pour cela :

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

Ces structures ont un double objectif : utiliser l'entrée du serveur et sa sortie. Les propriétés non optionnelles et les propriétés sans valeur par défaut, par exemple, number on RequestVerificationBody sont fournies lorsque vous adressez une requête au serveur.

L'initialisateur personnalisé prend la version de la structure à partir de la demande au serveur, l'enrichit avec les propriétés restantes et l'utilise pour faire un appel aux API de Vonage. Les API de Vonage s'attendent à ce que les champs soient en casse serpent, de sorte que les structures disposent de l'enum CodingKeys pour faire correspondre les noms de leurs propriétés à leur équivalent en snake case.

Créer une demande de vérification

Vous devez faire un appel à l'API Verify pour créer une demande de vérification. Le point de terminaison que vous souhaitez appeler pour créer une demande de vérification est le suivant /verify. Créez une fonction dans la Vonage pour ce faire :

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 fonction prend le corps de la requête adressée à votre serveur et un fichier Client. Vapor API client de Vapor vous permet de faire des appels HTTP externes. Avant l'envoi de la requête post, le corps de la requête est encodé avec une RequestVerificationBody enrichie. La fonction renvoie un EventLoopFuture qui est un type générique faisant référence à une valeur qui n'est pas encore disponible, dans votre cas, la réponse de la requête post.

L'étape suivante consiste à définir la route, qui est le point d'arrivée sur votre serveur qui appellera la fonction ci-dessus. Ouvrez routes.swiftpour créer une instance de la structure Vonage et définir la nouvelle route :

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

Remplacer API_KEY et API_SECRET par vos informations d'identification du tableau de bord de l'API Vonage. Dans un environnement de production, vous pouvez utiliser l'API API d'environnement de Vapor de Vapor pour éviter d'exposer vos informations d'identification.

Lorsque le point d'accès /request sur votre serveur reçoit une requête, il décode le corps de cette requête dans une RequestVerificationBody puis l'utilise pour appeler la fonction que vous avez créée plus tôt. Par défaut, le workflow 1 est utilisé, vous pouvez ajouter une propriété à la structure RequestVerificationBodyavec une clé de codage correspondant à workflow_id pour changer cela.

Le résultat de l'appel aura une propriété status Lorsque celle-ci est égale à 0, cela signifie que l'action a été menée à bien. Il comprendra également une propriété request_id; c'est ce qui est utilisé pour vérifier que le code est valide.

Vérifier le code

La vérification de la validité du code est un processus très similaire. Ajoutez une fonction à la structure Vonage pour appeler l'API Verify, cette fois en effectuant une requête post vers /verify/check avec une 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)
    }
}

Ajoutez ensuite l'itinéraire dans 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)
}

Comme dans le cas de l'itinéraire de requête précédent, le résultat de l'appel aura une propriété status avec 0 signifiant succès.

Testez votre serveur

Maintenant que vos routes sont définies, vous pouvez construire et exécuter (CMD + R) votre serveur. Une fois terminé, votre serveur tournera localement sur le port 8080.

Terminal output when running project

Pour l'exposer à l'internet, vous pouvez utiliser ngrok. Dans votre terminal, lancez ngrok http 8080. Une URL publique est générée, qui redirige les appels vers votre machine locale.

ngrok terminal output

Maintenant que votre serveur est disponible sur Internet, vous pouvez lui adresser des appels. Pour tester votre serveur, vous pouvez utiliser l'application l'application test. Soit vous téléchargez le projet, soit vous le clonez dans votre terminal en utilisant git clone git@github.com:nexmo-community/swiftui-two-factor-app.git.

Une fois téléchargé, ouvrez le projet dans Xcode. Dans le fichier VerifyModel.swift remplacez la chaîne BASE_URL par l'URL de transfert de ngrok, puis compilez et exécutez (CMD + R). Vous pouvez entrer votre numéro de téléphone, et il recevra un texte que vous pourrez saisir pour vérifier votre numéro de téléphone !

Test app screenshots

Quelle est la prochaine étape ?

Vous pouvez trouver le projet terminé sur GitHub. Vous pouvez utiliser l'API Verify à d'autres fins, par exemple pour modifier les horaires des événements du flux de travail ou pour autoriser des paiements. Pour en savoir plus developer.nexmo.com.

Partager:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiVonage Ancien membre de l'équipe

Abdul est défenseur des développeurs chez Vonage. Il a travaillé dans le domaine des produits de consommation en tant qu'ingénieur iOS. Pendant son temps libre, il aime faire du vélo, écouter de la musique et conseiller ceux qui commencent leur parcours dans la technologie.