Compartilhar via


Tutorial: Adicionar entrada e saída no aplicativo iOS/macOS usando autenticação nativa

Aplica-se a: Círculo branco com um símbolo X cinza. Locatários da força de trabalho Círculo verde com um símbolo de marca de seleção branco. Inquilinos externos (saiba mais)

Este tutorial demonstra como entrar e sair de um usuário com senha única de e-mail ou nome de usuário e senha em seu aplicativo iOS/macOS usando autenticação nativa.

Neste tutorial, você aprenderá a:

  • Inicie a sessão de um utilizador utilizando um código de acesso único por e-mail ou nome de utilizador (e-mail) e palavra-passe.
  • Termine a sessão do utilizador.
  • Tratar erro de início de sessão

Pré-requisitos

Iniciar sessão do utilizador

Para iniciar sessão de um utilizador usando o fluxo de código de uso único do Email, capture o e-mail e envie um e-mail contendo um código de uso único para o utilizador verificar o seu e-mail. Quando o usuário insere uma senha única válida, o aplicativo faz login.

Para iniciar sessão de um utilizador utilizando o fluxo Email com palavra-passe, capture o e-mail e a palavra-passe. Se o nome de utilizador e a palavra-passe forem válidos, a aplicação inicia sessão no utilizador.

Para fazer login de um utilizador, tem de:

  1. Crie uma interface do usuário (UI) para:

    • Colete um e-mail do usuário. Adicione validação às suas entradas para garantir que o usuário insira um endereço de e-mail válido.
    • Recolha uma palavra-passe se iniciar sessão com o nome de utilizador (e-mail) e a palavra-passe.
    • Recolha um código de uso único por e-mail do utilizador se iniciar sessão com um código de uso único por e-mail.
    • Adicione um botão para permitir que o utilizador reenvie um código de acesso único se iniciar sessão com um código único por e-mail.
  2. Na interface do utilizador, adicione um botão, cujo evento de seleção inicia um início de sessão, 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 autenticar um utilizador usando o fluxo de código de uso único por e-mail , usamos o seguinte trecho de código:

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

    O método signIn(parameters:delegate), que responde de forma assíncrona chamando um dos métodos no objeto delegado passado, deve implementar o protocolo SignInStartDelegate. Passamos uma instância de MSALNativeAuthSignInParameters que contém o endereço de e-mail fornecido pelo utilizador no formulário de envio de e-mail, e definimos self como delegado.

    Para entrar em um usuário usando Email com senha fluxo, usamos o seguinte trecho 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 e-mail que o usuário nos forneceu e sua senha, juntamente com o objeto delegado que está em conformidade com o protocolo SignInStartDelegate. Para este exemplo, passamos self.

  3. Para implementar o protocolo SignInStartDelegate quando você usa o fluxo de senha única de e-mail , use o seguinte trecho 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 delegar 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 e-mail do usuário. Juntamente com alguns detalhes de onde o código foi enviado e quantos dígitos ele contém, este método delegado também tem um parâmetro newState do tipo SignInCodeRequiredState, que nos dá acesso aos dois novos métodos a seguir:

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

    Use submitCode(code:delegate) para enviar a senha única que o usuário fornece no formulário de senha única, use o seguinte trecho de código:

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

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

    Para implementar SignInVerifyCodeDelegate protocolo como uma extensão para sua classe, use o seguinte trecho 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 para onSignInCompleted(result) indicando que o usuário entrou. 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 para 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 ao utilizar o fluxo de senha com o Email, use o seguinte trecho 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 para onSignInCompleted(result) indicando que o usuário entrou. 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 para 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)"
        }
    }
    
    

Lidar com erros de início de sessão

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

  1. Para manipular erros no método signIn(parameters:delegate), use o seguinte trecho 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 e-mail incorreto, o manipulador de erros incluirá uma referência a um SignInCodeRequiredState que pode ser usado para enviar um código atualizado. Em nossa implementação anterior de SignInVerifyCodeDelegate protocolo, simplesmente exibimos o erro quando manipulamos a função de delegação onSignInVerifyCodeError(error:newState).

Ler reivindicações do 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 trecho de código:

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

A chave que utiliza para aceder ao valor da declaração é o nome que especifica ao adicionar o atributo de utilizador como uma declaração de token.

Saiba como adicionar atributos internos e personalizados como declarações de token no artigo Adicionar atributos de usuário a declarações de token.

Terminar sessão do utilizador

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

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

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

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

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

    func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
        resultTextView.text = "Signed in successfully"
    
        accountResult = result
    }
    
  5. Adicione um botão Terminar Sessão e use o seguinte código para terminar a sessão do utilizador:

    @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 êxito todas as etapas necessárias para sair de um usuário em seu aplicativo. Crie e execute seu aplicativo. Se tudo estiver bem, você deve ser capaz de selecionar o botão de saída para sair com êxito.

Configurar provedor de declarações personalizado

Se você quiser adicionar declarações 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.