Compartilhar via


Tutorial: adicionar o recurso de entrar e sair no 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)

Esse tutorial demonstra como realizar a entrada e saída de um usuário usando uma senha de uso único por email ou um nome de usuário e senha no seu aplicativo iOS/macOS usando autenticação nativa.

Neste tutorial, você aprenderá a:

  • Conecte um usuário usando senha única por email ou nome de usuário (email) e senha.
  • Desconecte um usuário.
  • Como lidar com erros de entrada

Pré-requisitos

Conectar usuário

Para conectar um usuário com o fluxo de senha de uso único por email, capture o email e envie um email contendo uma senha de uso único para o usuário verificar o respectivo email. Quando o usuário insere uma senha de uso único válida, o aplicativo o conecta.

Para que um usuário entre usando o fluxo de Email com senha, capture o email e a senha. Se o nome de usuário e a senha forem válidos, o aplicativo conectará o usuário.

Para conectar um usuário, você precisa:

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

    • Coletar um email do usuário. Adicionar validação à interface do usuário para garantir que o usuário insira um endereço de email válido.
    • Colete uma senha se você entrar com o nome de usuário (email) e a senha.
    • Colete uma senha de uso único por email do usuário se você usar a senha de uso único por email para entrada.
    • Se você entrar com a senha única por email, adicione um botão para permitir que o usuário reenvie a senha única.
  2. Na interface do usuário, adicione um botão, cujo evento de seleção inicia uma entrada, conforme mostrado no seguinte trecho de código:

        @IBAction func signInPressed(_: Any) {
        guard let email = emailTextField.text else {
            resultTextView.text = "email not set"
            return
        }
    
        let parameters = MSALNativeAuthSignInParameters(username: email)
        nativeAuth.signIn(parameters: parameters, delegate: self)
    }
    

    Para que um usuário entre usando o fluxo de Senha única por email, usamos o seguinte snippet de código:

    nativeAuth.signIn(parameters: parameters, delegate: self)
    

    O método signIn(parameters:delegate), que responde de maneira assíncrona chamando um dos métodos no objeto delegado repassado, precisa implementar o protocolo SignInStartDelegate. Transmitimos uma instância de MSALNativeAuthSignInParameters que contém o endereço de email que o usuário fornece no formulário de envio de email e transmitimos self como o delegado.

    Para que um usuário entre usando o fluxo de Email com senha, usamos o seguinte snippet de código:

    let parameters = MSALNativeAuthSignInParameters(username: email)
    parameters.password = password
    nativeAuth.signIn(parameters: parameters, delegate: self)
    

    No método signIn(parameters:delegate), você passa uma instância de MSALNativeAuthSignInParameters que contém o endereço de email que o usuário nos forneceu e sua senha, juntamente com o objeto delegado que está em conformidade com o protocolo SignInStartDelegate. Para esse exemplo, vamos repassar self.

  3. Para implementar o protocolo SignInStartDelegate quando você usar o fluxo de Senha única por email, use o seguinte snippet de código:

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCodeRequired(
            newState: MSAL.SignInCodeRequiredState,
            sentTo: String,
            channelTargetType: MSAL.MSALNativeAuthChannelType,
            codeLength: Int
        ) {
            resultTextView.text = "Verification code sent to \(sentTo)"
        }
    }
    

    O signIn(parameters:delegate) resulta em uma chamada para delegação dos métodos. No cenário mais comum, onSignInCodeRequired(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 SignInCodeRequiredState, que nos dá acesso aos dois novos seguintes métodos:

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

    Para usar submitCode(code:delegate) ao enviar a senha de uso único que o usuário fornecer no formulário de senha de uso único, use o seguinte trecho de código:

    newState.submitCode(code: userSuppliedCode, delegate: self)
    

    O submitCode(code:delegate) aceita a senha de uso único e o parâmetro delegado. Depois de enviar o código, você precisa verificar a senha de uso único implementando o protocolo SignInVerifyCodeDelegate.

    Para implementar o protocolo SignInVerifyCodeDelegate como uma extensão da classe, use o seguinte snippet de código:

    extension ViewController: SignInVerifyCodeDelegate {
        func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
            resultTextView.text = "Signed in successfully."
            let parameters = MSALNativeAuthGetAccessTokenParameters()
            result.getAccessToken(parameters: parameters, delegate: self)
        }
    }
    

    No cenário mais comum, recebemos uma chamada a onSignInCompleted(result), indicando que o usuário se conectou. O resultado pode ser usado para recuperar o access token.

    O getAccessToken(parameters:delegate) aceita uma instância MSALNativeAuthGetAccessTokenParameters e um parâmetro delegado e devemos implementar os métodos necessários no protocolo CredentialsDelegate.

    No cenário mais comum, recebemos uma chamada a onAccessTokenRetrieveCompleted(result), indicando que o usuário obteve um access token.

    extension ViewController: CredentialsDelegate {
        func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) {
            resultTextView.text = "Error retrieving access token"
        }
    
        func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) {
            resultTextView.text = "Signed in. Access Token: \(result.accessToken)"
        }
    }
    
    
  4. Para implementar o protocolo SignInStartDelegate quando você usar o fluxo de Email com senha, use o seguinte snippet de código:

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
            // User successfully signed in
        }
    }
    

    No cenário mais comum, recebemos uma chamada a onSignInCompleted(result), indicando que o usuário se conectou. O resultado pode ser usado para recuperar o access token.

    O getAccessToken(parameters:delegate) aceita uma instância MSALNativeAuthGetAccessTokenParameters e um parâmetro delegado e devemos implementar os métodos necessários no protocolo CredentialsDelegate.

    No cenário mais comum, recebemos uma chamada a onAccessTokenRetrieveCompleted(result), indicando que o usuário obteve um access token.

    extension ViewController: CredentialsDelegate {
        func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) {
            resultTextView.text = "Error retrieving access token"
        }
    
        func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) {
            resultTextView.text = "Signed in. Access Token: \(result.accessToken)"
        }
    }
    
    

Como lidar com erros de entrada

Durante a entrada, nem todas as ações são bem-sucedidas. Por exemplo, o usuário pode tentar se conectar com um endereço de email que não existe ou enviar um código inválido.

  1. Para lidar com erros no método signIn(parameters:delegate), use o seguinte snippet de código:

    func onSignInStartError(error: MSAL.SignInStartError) {
        if error.isUserNotFound || error.isInvalidUsername {
            resultTextView.text = "Invalid username"
        } else {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    }
    
  2. Para lidar com erros no método submitCode(), use o seguinte trecho de código:

    func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
        if error.isInvalidCode {
            // Inform the user that the submitted code was incorrect and ask for a new code to be supplied
            let userSuppliedCode = retrieveNewCode()
            newState?.submitCode(code: userSuppliedCode, delegate: self)
        } else {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    }
    

    Se o usuário inserir um código de verificação de email incorreto, o manipulador de erros incluirá uma referência a um SignInCodeRequiredState que poderá ser usado para enviar um código atualizado. Em nossa implementação anterior do protocolo SignInVerifyCodeDelegate, simplesmente exibimos o erro quando tratamos a função delegado onSignInVerifyCodeError(error:newState).

Ler declarações de token de ID

Depois que seu aplicativo adquirir um token de ID, você poderá recuperar as declarações associadas à conta atual. Para fazer isso, use o seguinte snippet de código:

func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
   let claims = result.account.accountClaims
   let preferredUsername = claims?["preferred_username"] as? String
}

A chave que você usa para acessar o valor da declaração é o nome que você especifica ao adicionar o atributo de usuário como uma declaração de token.

Saiba como adicionar atributos integrados e personalizados como declarações de token conferindo o artigo Adicionar atributos de usuário às declarações de token.

Desconectar usuário

Para desconectar um usuário, use a referência ao MSALNativeAuthUserAccountResult que você recebeu no retorno de chamada onSignInCompleted ou use getNativeAuthUserAccount() para obter do cache qualquer conta conectada e armazenar uma referência na variável de membro accountResult.

  1. Configure o grupo de conjuntos de chaves para seu projeto, conforme descrito aqui.

  2. Adicione uma nova variável de membro à classe ViewController: var accountResult: MSALNativeAuthUserAccountResult?.

  3. Atualize viewDidLoad para recuperar qualquer conta armazenada em cache adicionando esta linha depois de nativeAuth ser inicializado com sucesso: accountResult = nativeAuth.getNativeAuthUserAccount().

  4. Atualize o manipulador signInCompleted para armazenar o resultado da conta:

    func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
        resultTextView.text = "Signed in successfully"
    
        accountResult = result
    }
    
  5. Adicione um botão Sair e use o seguinte código para desconectar do usuário:

    @IBAction func signOutPressed(_: Any) {
        guard let accountResult = accountResult else {
            print("Not currently signed in")
            return
        }
    
        accountResult.signOut()
    
        self.accountResult = nil
    
        resultTextView.text = "Signed out"
    }
    

Você concluiu com sucesso todas as etapas necessárias para desconectar um usuário no seu aplicativo. Compile e execute seu aplicativo. Se tudo estiver certo, você poderá selecionar o botão Sair para se desconectar com sucesso.

Configurar provedor de declarações personalizado

Se você quiser adicionar declarações a partir de um sistema externo ao token emitido para seu aplicativo, use um provedor de declarações personalizado. Um provedor de declarações personalizado é composto por uma extensão de autenticação personalizada que chama uma API REST externa para buscar declarações de sistemas externos.

Siga as etapas em Configurar um provedor de declarações personalizado para adicionar declarações de um sistema externo aos seus tokens de segurança.