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

Hinzufügen der Zwei-Faktor-Authentifizierung mit Swift und Vapor

Zuletzt aktualisiert am November 24, 2020

Lesedauer: 4 Minuten

Einführung

Bei der Zwei-Faktoren-Authentifizierung (2FA) verwenden Sie zwei verschiedene Dinge, um Ihre Identität zu verifizieren. Normalerweise etwas, das Sie kennen, wie ein Passwort, gepaart mit einem Verifizierungscode von einem physischen Gerät wie einem Telefon.

In diesem Tutorial erfahren Sie, wie Sie ein Verifizierungs-Token-System mit der Vonage Verify API und Vapor implementieren. Im Anschluss können Sie das System mit einer SwiftUI-Anwendung testen.

Voraussetzungen

  • Xcode 12 und Swift 5 oder höher.

  • Vapor 4.0 auf Ihrem Rechner installiert ist.

  • ngrok um Ihren lokalen Rechner dem Internet auszusetzen.

Vonage API-Konto

Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.

Ein Vapor-Projekt erstellen

Sie können ein Vapor-Projekt erstellen, indem Sie den Befehl new project vapor new SwiftVerify -n in Ihrem Terminal erstellen. Sobald der Befehl beendet ist, wechseln Sie in den Ordner, den er für Sie erstellt hat, mit cd SwiftVerify. Nun können Sie das Projekt in Xcode öffnen mit vapor xcode.

Sobald Xcode geöffnet ist, werden die Abhängigkeiten, auf die Vapor angewiesen ist, mit dem Swift Package Manager (SPM) heruntergeladen. Um die Abhängigkeiten zu sehen, können Sie die Package.swift Datei öffnen.

Erstellen Sie die Modellstrukturen

Ein großer Vorteil der Verwendung von Vapor ist, dass Sie sich auf die Typsicherheit der Swift-Sprache stützen können. Sie können Eingaben und Ausgaben für Ihren Server mit Structs modellieren, die mit dem Codable Protokoll entsprechen; Vapor hat ein Protokoll namens Content für diese Zwecke.

Beginnen Sie mit der Erstellung einer Struktur namens Vonage um den gesamten Modellcode aufzunehmen. Erstellen Sie eine neue Datei unter Quellen > App mit dem Namen VonageClient.swift. In der neuen Datei erstellen Sie die 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
    }
}

Die Struktur wird mit dem API-Schlüssel und dem Geheimnis Ihres Vonage API-Kontos initialisiert und speichert sie als lokale Eigenschaften zur späteren Verwendung. In diesem Tutorial werden Sie zwei API-Endpunkte erstellen, einen, um einen Verifizierungscode anzufordern, und einen, um zu überprüfen, ob der Code korrekt war. Erstellen Sie dazu zwei weitere Structs innerhalb der Vonage struct für diese Zwecke:

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

Diese Strukturen haben einen doppelten Zweck: Sie dienen der Eingabe in den Server und seiner Ausgabe. Die nicht-optionalen Eigenschaften und die Eigenschaften ohne Standardwert, zum Beispiel, number auf RequestVerificationBody werden bereitgestellt, wenn Sie eine Anfrage an den Server stellen.

Der benutzerdefinierte Initialisierer nimmt die Version der Struktur aus der Anfrage an den Server auf, reichert sie mit den übrigen Eigenschaften an und verwendet sie dann, um einen Aufruf an die Vonage-APIs zu tätigen. Die Vonage APIs erwarten Felder in snake case, daher haben die structs das CodingKeys enum, um die Eigenschaftsnamen auf ihre Entsprechung in Snake Case abzubilden.

Verifizierungsanfrage erstellen

Sie müssen die Verify API aufrufen, um eine Verifizierungsanfrage zu erstellen. Der Endpunkt, den Sie zum Erstellen einer Verifizierungsanfrage aufrufen müssen, lautet /verify. Erstellen Sie eine Funktion in der Vonage Struktur, um dies zu tun:

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

Die Funktion nimmt den Körper der Anfrage, die an Ihren Server gestellt wird, und eine Client. Vapor's Klient-API ermöglicht es Ihnen, externe HTTP-Aufrufe zu tätigen. Bevor die Post-Anfrage gesendet wird, wird der Body mit einer angereicherten RequestVerificationBody Struktur kodiert. Die Funktion gibt einen EventLoopFuture zurück, bei dem es sich um einen generischen Typ handelt, der auf einen Wert verweist, der noch nicht verfügbar ist, in Ihrem Fall die Antwort der Post-Anfrage.

Der nächste Schritt ist die Definition der Route, d. h. des Endpunkts auf Ihrem Server, der die obige Funktion aufruft. Öffnen Sie routes.swift, erstellen Sie eine Instanz der Vonage-Struktur und definieren Sie die neue 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)
    }
}

Ersetzen Sie API_KEY und API_SECRET durch Ihre Anmeldedaten aus dem Vonage API Dashboard. In einer Produktionsumgebung können Sie die Vapor Umgebungs-API verwenden, um zu vermeiden, dass Sie Ihre Anmeldeinformationen preisgeben.

Wenn der /request Endpunkt auf Ihrem Server eine Anfrage erhält, dekodiert er den Körper dieser Anfrage in eine RequestVerificationBody struct dekodiert und dann verwendet, um die zuvor erstellte Funktion aufzurufen. Standardmäßig Arbeitsablauf 1 verwendet wird, können Sie eine Eigenschaft zum RequestVerificationBodymit einem Kodierungsschlüssel hinzufügen, der auf workflow_id um dies zu ändern.

Das Ergebnis des Aufrufs hat eine status Eigenschaft; wenn diese 0 ist, bedeutet dies, dass die Aktion erfolgreich war. Außerdem enthält es eine request_identhalten; damit wird geprüft, ob der Code gültig ist.

Prüfen Sie den Code

Die Überprüfung, ob der Code gültig ist, ist ein sehr ähnlicher Prozess. Fügen Sie eine Funktion zu der Vonage Struktur eine Funktion hinzu, um die Verify API aufzurufen, wobei dieses Mal eine Post-Anfrage an /verify/check mit einer 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)
    }
}

Fügen Sie dann die Route in 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)
}

Ähnlich wie bei der früheren Anfrageroute hat das Ergebnis des Aufrufs eine status Eigenschaft, wobei 0 Erfolg bedeutet.

Testen Sie Ihren Server

Nun, da Ihre Routen definiert sind, können Sie Ihren Server erstellen und ausführen (CMD + R). Nach Fertigstellung wird Ihr Server lokal an Port 8080 ausgeführt.

Terminal output when running project

Um dies dem Internet zugänglich zu machen, können Sie ngrok verwenden. Führen Sie in Ihrem Terminal ngrok http 8080. Es wird eine öffentliche URL generiert, die Anrufe an Ihren lokalen Rechner weiterleitet.

ngrok terminal output

Nun, da Ihr Server im Internet verfügbar ist, können Sie ihn anrufen. Um Ihren Server zu testen, können Sie die Testanwendung. Entweder laden Sie das Projekt herunter oder klonen Sie es mit Ihrem Terminal mit git clone git@github.com:nexmo-community/swiftui-two-factor-app.git.

Nach dem Herunterladen öffnen Sie das Projekt in Xcode. In der VerifyModel.swift Datei ersetzen Sie die BASE_URL durch die Weiterleitungs-URL von ngrok, dann erstellen und ausführen (CMD + R). Sie können Ihre Telefonnummer eingeben, und es wird ein Text empfangen, den Sie eingeben können, um Ihre Telefonnummer zu verifizieren!

Test app screenshots

Wie geht es weiter?

Sie finden das fertige Projekt auf GitHub. Mit der Verify API können Sie noch mehr tun, z. B. die Zeitpunkte von Workflow-Ereignissen ändern oder Zahlungen damit autorisieren. Erfahren Sie mehr auf developer.nexmo.com.

Teilen Sie:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiVonage Ehemaliges Teammitglied

Abdul ist ein Developer Advocate für Vonage. Er hat einen Hintergrund als iOS-Ingenieur im Bereich Verbraucherprodukte. In seiner Freizeit fährt er gerne Rad, hört Musik und berät diejenigen, die gerade ihre Reise in die Technologiebranche beginnen.