https://a.storyblok.com/f/270183/36948/cfa78b1be3/blog_2fa_swift-vapor_1200x600.png

Como adicionar a autenticação de dois fatores com Swift e Vapor

Publicado em November 24, 2020

Tempo de leitura: 4 minutos

Introdução

A autenticação de dois fatores (2FA) consiste em usar dois elementos diferentes para verificar sua identidade. Normalmente, algo que você sabe, como uma senha, combinado com um código de verificação proveniente de um dispositivo físico, como um celular.

Este tutorial abordará como implementar um sistema de token de verificação usando a Verify API e o Vapor. Ao concluir, você poderá testar o sistema com um aplicativo SwiftUI.

Pré-requisitos

  • Xcode 12 e Swift 5 ou versão posterior.

  • Vapor 4.0 instalado no seu computador.

  • ngrok para expor seu computador local à internet.

Criar um projeto de vapor

Você pode criar um projeto Vapor usando o comando “novo projeto” vapor new SwiftVerify -n no seu terminal. Assim que o comando for concluído, mude para a pasta que foi criada para você usando cd SwiftVerify. Agora você pode abrir o projeto no Xcode usando vapor xcode.

Assim que o Xcode for aberto, ele começará a baixar as dependências das quais o Vapor depende, usando o Swift Package Manager (SPM). Para visualizar as dependências, você pode abrir o Package.swift arquivo.

Criar as estruturas do modelo

Uma grande vantagem de usar o Vapor é que você pode contar com a segurança de tipos da linguagem Swift. É possível modelar entradas e saídas do seu servidor usando estruturas que estejam em conformidade com o Codable protocolo; o Vapor possui um protocolo chamado Content para isso.

Comece criando uma estrutura chamada Vonage para abrigar todo o código do modelo. Crie um novo arquivo na pasta Sources > App chamado VonageClient.swift. No novo arquivo, crie a Vonage estrutura:

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

A estrutura é inicializada com a chave e o segredo da API da sua conta da API da Vonage e os armazena como propriedades locais para uso posterior. Você criará dois endpoints da API neste tutorial: um para solicitar um código de verificação e outro para verificar se o código estava correto. Crie mais duas estruturas dentro da Vonage estrutura para isso:

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

Essas estruturas têm uma dupla finalidade: utilizar os dados de entrada no servidor e seus dados de saída. As propriedades obrigatórias e aquelas sem valor padrão, por exemplo, number são RequestVerificationBody são fornecidas quando você faz uma solicitação ao servidor.

O inicializador personalizado recebe a versão da estrutura contida na solicitação enviada ao servidor, a complementa com as propriedades restantes e, em seguida, a utiliza para fazer uma chamada às APIs da Vonage. As APIs da Vonage esperam campos em “snake case”, portanto, as estruturas possuem a CodingKeys enum para mapear os nomes de suas propriedades para seus equivalentes em snake case.

Criar uma solicitação de verificação

Você precisa fazer uma chamada à Verify API para criar uma solicitação de verificação. O endpoint que você deve chamar para criar uma solicitação de verificação é /verify. Crie uma função na Vonage struct para fazer isso:

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

A função recebe o corpo da solicitação enviada ao seu servidor e um Client. API do Vapor para API de Cliente permite que você faça chamadas HTTP externas. Antes que a solicitação POST seja enviada, o corpo é codificado com uma RequestVerificationBody . A função retorna um EventLoopFuture , que é um tipo genérico que faz referência a um valor que ainda não está disponível; no seu caso, a resposta da solicitação POST.

O próximo passo é definir a rota, que é o ponto final no seu servidor que chamará a função acima. Abra routes.swift, crie uma instância da estrutura Vonage e defina a nova rota:

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

Substituir API_KEY e API_SECRET pelas suas credenciais do painel da API da Vonage. Em um ambiente de produção, você pode usar a API de Ambiente para evitar a exposição de suas credenciais.

Quando o /request endpoint no seu servidor receber uma solicitação, ele decodificará o corpo dessa solicitação em uma RequestVerificationBody estrutura e, em seguida, usá-lo para chamar a função que você criou anteriormente. Por padrão, , o fluxo de trabalho 1 é usado; você pode adicionar uma propriedade ao RequestVerificationBody, com uma chave de codificação mapeada para workflow_id para alterar isso.

O resultado da chamada terá uma status ; quando for 0, significa que a ação foi bem-sucedida. Também incluirá um request_id; é isso que é usado para verificar se o código é válido.

Verifique o código

Verificar se o código é válido é um processo muito semelhante. Adicione uma função à Vonage estrutura para chamar a Verify API, desta vez fazendo uma solicitação POST para /verify/check com uma 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)
    }
}

Em seguida, adicione a rota em 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)
}

Da mesma forma que na rota de solicitação anterior, o resultado da chamada terá uma status propriedade com valor 0, o que significa sucesso.

Teste seu servidor

Agora que suas rotas estão definidas, você pode compilar e executar (CMD + R) seu servidor. Assim que estiver pronto, seu servidor estará em execução localmente na porta 8080.

Terminal output when running project

Para disponibilizar isso na internet, você pode usar o ngrok. No terminal, execute ngrok http 8080. Será gerada uma URL pública que redireciona as chamadas para sua máquina local.

ngrok terminal output

Agora que seu servidor está disponível na internet, você pode fazer chamadas para ele; para testá-lo, você pode usar o aplicativo de teste. Baixe o projeto ou clone-o pelo terminal usando git clone git@github.com:nexmo-community/swiftui-two-factor-app.git.

Depois de baixado, abra o projeto no Xcode. No VerifyModel.swift arquivo, substitua a BASE_URL string pela URL de redirecionamento do ngrok e, em seguida, compile e execute (CMD + R). Você pode inserir seu número de telefone e receberá uma mensagem de texto com um código que poderá ser inserido para confirmar seu número!

Test app screenshots

E agora?

Você pode encontrar o projeto concluído no GitHub. Há muito mais que você pode fazer com a Verify API, como alterar os intervalos de tempo dos eventos do fluxo de trabalho ou usá-la para autorizar pagamentos. Saiba mais em developer.nexmo.com.

Compartilhar:

https://a.storyblok.com/f/270183/400x400/19c02db2d3/abdul-ajetunmobi.png
Abdul AjetunmobiEx-funcionário da Vonage

Abdul é um Developer Advocate da Vonage. Ele tem experiência profissional na área de produtos de consumo como engenheiro de iOS. Em seu tempo livre, ele gosta de andar de bicicleta, ouvir música e orientar quem está dando os primeiros passos na área de tecnologia