Compartilhar via


Tutorial: adicionar inscrição em um aplicativo iOS/macOS usando autenticação nativa

Aplica-se a: Círculo verde com um símbolo de marca de seleção branco. iOS (Swift) Círculo verde com um símbolo de marca de seleção branco. macOS (Swift)

Este tutorial demonstra como inscrever um usuário usando senha de uso único por email ou nome de usuário (email) e senha, e coletar atributos de usuário no seu aplicativo iOS/macOS usando autenticação nativa.

  • Inscrever um usuário usando senha de uso único por email ou nome de usuário (email) e senha.
  • Coletar atributos de usuário durante a inscrição.
  • Identificar erros de inscrição.

Pré-requisitos

Inscrever um usuário

Para inscrever um usuário usando a senha de uso único por email ou o nome de usuário (email) e senha, você coleta um email do usuário e, em seguida, envia um email contendo uma senha de uso único por email para o usuário. O usuário insere uma senha de uso único por email válida para validar seu nome de usuário.

Para inscrever um usuário, você precisa:

  1. Criar uma interface (IU) do usuário para:

    • Coletar um email do usuário. Adicionar validação às suas entradas de dados para garantir que o usuário insira um endereço de email válido.
    • Coletar uma senha se você se inscrever com o nome de usuário (email) e a senha.
    • Coletar uma senha de uso único por email do usuário.
    • Se necessário, coletar atributos de usuário.
    • Reenvie a senha de uso único se não for recebida pelo usuário.
    • Iniciar o fluxo de inscrição.
  2. Em seu aplicativo, adicione um botão, cujo evento de seleção dispara o seguinte trecho de código:

    @IBAction func signUpPressed(_: Any) {
        guard let email = emailTextField.text else {
            resultTextView.text = "Email or password not set"
            return
        }
    
        nativeAuth.signUp(username: email, delegate: self)
    }
    
    • Para inscrever o usuário usando Senha de uso único por email, usamos o método signUp(username:delegate) da biblioteca, que responde de forma assíncrona chamando um dos métodos no objeto delegado repassado, que precisa implementar o protocolo SignUpStartDelegate. A seguinte linha de código inicia o processo de inscrição do usuário:

      nativeAuth.signUp(username: email, delegate: self)
      

      No método signUp(username:delegate), repassamos o endereço de email do usuário do formulário de envio e do delegado (uma classe que implementa o protocolo SignUpStartDelegate).

    • Para inscrever um usuário usando Email com senha, use os seguintes snippets de código:

      @IBAction func signUpPressed(_: Any) {
          guard let email = emailTextField.text, let password = passwordTextField.text else {
              resultTextView.text = "Email or password not set"
              return
          }
      
          nativeAuth.signUp(username: email,password: password,delegate: self)
      }
      

      Usamos o método signUp(username:password:delegate) da biblioteca, que responde de maneira assíncrona chamando um dos métodos no objeto delegado repassado, que precisa implementar o protocolo SignUpStartDelegate. A seguinte linha de código inicia o processo de inscrição do usuário:

      nativeAuth.signUp(username: email, password: password, delegate: self)
      

      No método signUp(username:password:delegate), repassamos o endereço de email do usuário, a respectiva senha e o delegado (uma classe que implementa o protocolo SignUpStartDelegate).

    • Para implementar o protocolo SignUpStartDelegate como uma extensão da classe, use:

      extension ViewController: SignUpStartDelegate {
          func onSignUpStartError(error: MSAL.SignUpStartError) {
              resultTextView.text = "Error signing up: \(error.errorDescription ?? "no description")"
          }
      
          func onSignUpCodeRequired(
              newState: MSAL.SignUpCodeRequiredState,
              sentTo: String,
              channelTargetType: MSAL.MSALNativeAuthChannelType,
              codeLength: Int
          ) {
              resultTextView.text = "Verification code sent to \(sentTo)"
          }
      }
      

      A chamada de signUp(username:password:delegate) ou signUp(username:delegate) resulta em uma chamada dos métodos delegados onSignUpCodeRequired() ou onSignUpStartError(). O onSignUpCodeRequired(newState:sentTo:channelTargetType:codeLength) é chamado para indicar que um código foi enviado para verificar o endereço de email do usuário. Acompanhado de alguns detalhes, como local de envio do código e número de dígitos que ele contém, esse método delegado também tem um parâmetro newState do tipo SignUpCodeRequiredState, que fornece acesso a dois novos métodos:

      • submitCode(code:delegate)
      • resendCode(delegate)

      Para enviar o código fornecido pelo usuário, use:

      newState.submitCode(code: userSuppliedCode, delegate: self)
      
      • Para implementar o protocolo SignUpVerifyCodeDelegate como uma extensão da classe, use:

        extension ViewController: SignUpVerifyCodeDelegate {
            func onSignUpVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignUpCodeRequiredState?) {
                resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
            }
        
            func onSignUpCompleted(newState: SignInAfterSignUpState) {
                resultTextView.text = "Signed up successfully!"
            }
        }
        

        O submitCode(code:delegate) aceita um parâmetro delegado e devemos implementar os métodos necessários no protocolo SignUpVerifyCodeDelegate. No cenário mais comum, recebemos uma chamada de onSignUpCompleted(newState), indicando que o usuário se inscreveu e o fluxo foi concluído.

Coletar atributos de usuário durante a inscrição

Independentemente de você inscrever um usuário usando senha de uso único por email ou nome de usuário (email) e senha, você poderá coletar atributos de usuário antes que a conta de um usuário seja criada. O método signUp(username:attributes:delegate) aceita atributos como um parâmetro.

  1. Para coletar atributos de usuário, use o seguinte snippet de código:

    let attributes = [
        "country": "United States",
        "city": "Redmond"
    ]
    
    nativeAuth.signUp(username: email, attributes: attributes, delegate: self)
    

    O signUp(username:attributes:delegate) ou ignUp(username:password:attributes:delegate) resultam em uma chamada dos métodos delegados onSignUpCodeRequired() ou onSignUpStartError(), ou em uma chamada de onSignUpAttributesInvalid(attributeNames: [String]) se o método estiver implementado no delegado.

  2. Para implementar o protocolo SignUpStartDelegate como uma extensão da nossa classe, use o seguinte snippet de código:

    extension ViewController: SignUpStartDelegate {
        func onSignUpStartError(error: MSAL.SignUpStartError) {
            resultTextView.text = "Error signing up: \(error.errorDescription ?? "no description")"
        }
    
        func onSignUpCodeRequired(
            newState: MSAL.SignUpCodeRequiredState,
            sentTo: String,
            channelTargetType: MSAL.MSALNativeAuthChannelType,
            codeLength: Int
        ) {
            resultTextView.text = "Verification code sent to \(sentTo)"
        }
    
        func onSignUpAttributesInvalid(attributeNames: [String]) {
           resultTextView.text = "Invalid attributes  \(attributeNames)"
        }
    }
    

    Se os atributos forem inválidos, o método onSignUpAttributesInvalid(attributeNames: [String]) será chamado. Nesse caso, a lista de atributos inválidos é exibida ao usuário. Caso contrário, onSignUpCodeRequired(newState:sentTo:channelTargetType:codeLength) é chamado para indicar que um código foi enviado para verificar o endereço de email do usuário. Além de detalhes como o destinatário do código e o número de dígitos do código, esse método delegado tem um parâmetro newState do tipo SignUpCodeRequiredState, o que fornece acesso a dois novos métodos:

    • submitCode(code:delegate)
    • resendCode(delegate)

Atributos de usuário em uma ou mais páginas

Para distribuir os atributos por uma ou mais páginas, precisamos definir os atributos que pretendemos coletar em páginas diferentes como obrigatórios na configuração do gerenciamento de acesso e identidade do cliente (CIAM) de um locatário.

Chamamos signUp(username:password:delegate) sem repassar nenhum atributo. A próxima etapa será chamar newState.submitCode(code: userSuppliedCode, delegate: self) para verificar o email do usuário.

Implementamos o protocolo SignUpVerifyCodeDelegate como uma extensão da nossa classe como antes, mas desta vez precisamos implementar o método onSignUpAttributesRequired(attributes:newState) opcional além dos métodos obrigatórios:

extension ViewController: SignUpVerifyCodeDelegate {
    func onSignUpAttributesRequired(newState: SignUpAttributesRequiredState) {
        resultTextView.text = "Attributes required"
    }

    func onSignUpVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignUpCodeRequiredState?) {
        resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
    }

    func onSignUpCompleted(newState: SignInAfterSignUpState) {
        resultTextView.text = "Signed up successfully!"
    }
}

Esse método de delegado tem um parâmetro newState do tipo SignUpAttributesRequiredState, que nos dá acesso a um novo método:

  • submitAttributes(attributes:delegate)

Para enviar os atributos que o usuário nos forneceu, use o seguinte snippet de código:

let attributes = [
    "country": "United States",
    "city": "Redmond"
]

newState.submitAttributes(attributes: attributes, delegate: self)

Também vamos implementar o protocolo SignUpAttributesRequiredDelegate como uma extensão da nossa classe:

extension ViewController: SignUpAttributesRequiredDelegate {
    func onSignUpAttributesRequiredError(error: AttributesRequiredError) {
        resultTextView.text = "Error submitting attributes: \(error.errorDescription ?? "no description")"
    }

    func onSignUpAttributesRequired(attributes: [MSALNativeAuthRequiredAttribute], newState: SignUpAttributesRequiredState) {
        resultTextView.text = "Attributes required"
    }

    func onSignUpAttributesInvalid(attributeNames: [String], newState: SignUpAttributesRequiredState) {
        resultTextView.text = "Attributes invalid"
    }

    func onSignUpCompleted(newState: SignInAfterSignUpState) {
        resultTextView.text = "Signed up successfully!"
    }
}

Quando o usuário não fornece todos os atributos necessários ou os atributos são inválidos, esses métodos de delegado são chamados:

  • onSignUpAttributesInvalid: indica que um ou mais atributos que foram enviados falharam na validação da entrada de dados. Esse erro contém um parâmetro attributeNames, que é uma lista de todos os atributos que foram enviados pelo desenvolvedor e falharam na validação de entrada.
  • onSignUpAttributesRequired: indica que o servidor requer que um ou mais atributos sejam enviados antes de a conta de usuário poder ser criada. Isso acontece quando um ou mais atributos são definidos como obrigatórios na configuração do locatário. Esse resultado contém o parâmetro de atributos, que é uma lista de objetos MSALNativeAuthRequiredAttribute que descreve detalhes sobre os atributos de usuário requeridos pela API.

Ambos os métodos de delegado contêm uma referência ao novo estado. Vamos usar o parâmetro newState para chamar submitAttributes(attributes:delegate) novamente com os novos atributos.

Manipular erros de inscrição

Durante a inscrição, nem todas as ações são bem-sucedidas. Por exemplo, o usuário pode tentar se inscrever com um endereço de email que já está em uso ou enviar um código inválido.

Em nossa implementação anterior do protocolo SignUpStartDelegate, simplesmente exibimos o erro quando tratamos a função delegada onSignUpStartError(error).

Para aprimorar a experiência do usuário gerenciando o tipo de erro específico, use o seguinte trecho de código:

func onSignUpStartError(error: MSAL.SignUpStartError) {
    if error.isUserAlreadyExists {
        resultTextView.text = "Unable to sign up: User already exists"
    } else if error.isInvalidPassword {
        resultTextView.text = "Unable to sign up: The password is invalid"
    } else if error.isInvalidUsername {
        resultTextView.text = "Unable to sign up: The username is invalid"
    } else {
        resultTextView.text = "Unexpected error signing up: \(error.errorDescription ?? "no description")"
    }
}

Opcional: entrar após um fluxo de inscrição

Após um fluxo de inscrição bem-sucedido, você pode conectar um usuário sem iniciar um fluxo de entrada. Saiba mais no artigo Tutorial: conectar o usuário automaticamente após a inscrição em um aplicativo iOS/macOS.

Próxima etapa