Compartilhar via


Tutorial: Fazer login de usuários no aplicativo móvel iOS (Swift)

Este é o terceiro tutorial da série de tutoriais que orienta você sobre como entrar em usuários usando a ID Externa do Microsoft Entra.

Neste tutorial, você aprenderá a:

  • Conectar o usuário.
  • Desconectar o usuário.

Pré-requisitos

Conectar usuário

Você tem duas opções principais para entrar em usuários usando a MSAL (Biblioteca de Autenticação da Microsoft) para iOS: adquirir tokens de forma interativa ou silenciosa.

  1. Para conectar o usuário interativamente, use o seguinte código:

    acquireTokenInteractively() {
        guard let applicationContext = self.applicationContext else { return }
        guard let webViewParameters = self.webViewParamaters else { return }
    
        updateLogging(text: "Acquiring token interactively...")
    
        let parameters = MSALInteractiveTokenParameters(scopes: Configuration.kScopes, webviewParameters: webViewParameters)
        parameters.promptType = .selectAccount
    
        applicationContext.acquireToken(with: parameters) { (result, error) in
    
            if let error = error {
    
                self.updateLogging(text: "Could not acquire token: \(error)")
                return
            }
    
            guard let result = result else {
    
                self.updateLogging(text: "Could not acquire token: No result returned")
                return
            }
    
            self.accessToken = result.accessToken
            self.updateLogging(text: "Access token is \(self.accessToken)")
            self.updateCurrentAccount(account: result.account)
        }
    }
    

    O código primeiro verifica se o contexto do aplicativo e os parâmetros de exibição da Web estão disponíveis. Em seguida, ele atualiza o log para indicar que está adquirindo o token interativamente. Em seguida, ele configura parâmetros para aquisição interativa de token, especificando os escopos e os parâmetros de exibição da Web. Ele também define o tipo de prompt para selecionar uma conta.

    Posteriormente, ele chama o método acquireToken no contexto do aplicativo com os parâmetros definidos. No manipulador de conclusão, ele verifica se há erros. Se um erro for encontrado, ele atualizará o log com a mensagem de erro. Se tiver êxito, ele recuperará o token de acesso do resultado, atualizará o log com o token e atualizará a conta atual.

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

    let claims = result.account.accountClaims
    let preferredUsername = claims?["preferred_username"] as? String
    

    O código lê declarações da conta acessando a propriedade accountClaims do objeto result.account. Em seguida, recupera o valor da declaração "preferred_username" do dicionário de declarações e a atribui à variável preferredUsername.

  2. Para conectar o usuário silenciosamente, use o seguinte código:

    func acquireTokenSilently() {
        self.loadCurrentAccount { (account) in
    
            guard let currentAccount = account else {
    
                self.updateLogging(text: "No token found, try to acquire a token interactively first")
                return
            }
    
            self.acquireTokenSilently(currentAccount)
        }
    }
    

    O código inicia o processo de aquisição silenciosa de tokens. Ele primeiro tenta carregar a conta atual. Se uma conta atual for encontrada, ela continuará a adquirir o token silenciosamente usando essa conta. Se nenhuma conta atual for encontrada, ela atualizará o log para indicar que nenhum token foi encontrado e sugerirá tentar adquirir um token interativamente primeiro.

    No código acima, estamos chamando duas funções loadCurrentAccount e acquireTokenSilently. A função loadCurrentAccount deve ter o seguinte código:

    func loadCurrentAccount(completion: AccountCompletion? = nil) {
    
        guard let applicationContext = self.applicationContext else { return }
    
        let msalParameters = MSALParameters()
        msalParameters.completionBlockQueue = DispatchQueue.main
    
        // Note that this sample showcases an app that signs in a single account at a time
        applicationContext.getCurrentAccount(with: msalParameters, completionBlock: { (currentAccount, previousAccount, error) in
    
            if let error = error {
                self.updateLogging(text: "Couldn't query current account with error: \(error)")
                return
            }
    
            if let currentAccount = currentAccount {
    
                self.updateCurrentAccount(account: currentAccount)
                self.acquireTokenSilently(currentAccount)
    
                if let completion = completion {
                    completion(self.currentAccount)
                }
    
                return
            }
    
            // If testing with Microsoft's shared device mode, see the account that has been signed out from another app. More details here:
            // https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-ios-shared-devices
            if let previousAccount = previousAccount {
    
                self.updateLogging(text: "The account with username \(String(describing: previousAccount.username)) has been signed out.")
    
            } else {
    
                self.updateLogging(text: "")
            }
    
            self.accessToken = ""
            self.updateCurrentAccount(account: nil)
    
            if let completion = completion {
                completion(nil)
            }
        })
    }
    

    O código usa MSAL para iOS para carregar a conta atual. Ele verifica se há erros e atualiza o registro em log adequadamente. Se uma conta atual for encontrada, ela a atualizará e tentará adquirir tokens silenciosamente. Se existir uma conta anterior, ela registrará a saída em log. Se nenhuma conta for encontrada, ela limpará o token de acesso. Por fim, ele executa um bloco de conclusão, se fornecido.

    A função acquireTokenSilently deve conter o seguinte código:

    func acquireTokenSilently(_ account : MSALAccount) {
        guard let applicationContext = self.applicationContext else { return }
    
        /**
    
         Acquire a token for an existing account silently
    
         - forScopes:           Permissions you want included in the access token received
         in the result in the completionBlock. Not all scopes are
         guaranteed to be included in the access token returned.
         - account:             An account object that we retrieved from the application object before that the
         authentication flow will be locked down to.
         - completionBlock:     The completion block that will be called when the authentication
         flow completes, or encounters an error.
         */
    
        updateLogging(text: "Acquiring token silently...")
    
        let parameters = MSALSilentTokenParameters(scopes: Configuration.kScopes, account: account)
    
        applicationContext.acquireTokenSilent(with: parameters) { (result, error) in
    
            if let error = error {
    
                let nsError = error as NSError
    
                // interactionRequired means we need to ask the user to sign-in. This usually happens
                // when the user's Refresh Token is expired or if the user has changed their password
                // among other possible reasons.
    
                if (nsError.domain == MSALErrorDomain) {
    
                    if (nsError.code == MSALError.interactionRequired.rawValue) {
    
                        DispatchQueue.main.async {
                            self.acquireTokenInteractively()
                        }
                        return
                    }
                }
    
                self.updateLogging(text: "Could not acquire token silently: \(error)")
                return
            }
    
            guard let result = result else {
    
                self.updateLogging(text: "Could not acquire token: No result returned")
                return
            }
    
            self.accessToken = result.accessToken
            self.updateLogging(text: "Refreshed Access token is \(self.accessToken)")
            self.updateSignOutButton(enabled: true)
        }
    }
    
    

    Essa função usa a MSAL para iOS para adquirir silenciosamente um token para uma conta existente. Depois de verificar o applicationContextprocesso de aquisição de token, ele registra o processo de aquisição de token. Usando MSALSilentTokenParameters, ele define os parâmetros necessários. Em seguida, ele tenta adquirir o token silenciosamente. Se houver erros, ele verificará os requisitos de interação do usuário, iniciando um processo interativo, se necessário. Após o sucesso, ele atualiza a propriedade accessToken e registra o token atualizado, concluindo habilitando o botão de saída.

Desconectar usuário

Para desconectar um usuário do aplicativo iOS (Swift) usando a MSAL para iOS, use o seguinte código:

   @IBAction func signOut(_ sender: UIButton) {
        
        guard let applicationContext = self.applicationContext else { return }
        
        guard let account = self.currentAccount else { return }
        
        guard let webViewParamaters = self.webViewParamaters else { return }
        
        updateLogging(text: "Signing out...")
        
        do {
            
            /**
             Removes all tokens from the cache for this application for the provided account
             
             - account:    The account to remove from the cache
             */
            
            let signoutParameters = MSALSignoutParameters(webviewParameters: webViewParamaters)
            
            // If testing with Microsoft's shared device mode, trigger signout from browser. More details here:
            // https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-ios-shared-devices
            
            if (self.currentDeviceMode == .shared) {
                signoutParameters.signoutFromBrowser = true
            } else {
                signoutParameters.signoutFromBrowser = false
            }
            
            applicationContext.signout(with: account, signoutParameters: signoutParameters, completionBlock: {(success, error) in
                
                if let error = error {
                    self.updateLogging(text: "Couldn't sign out account with error: \(error)")
                    return
                }
                
                self.updateLogging(text: "Sign out completed successfully")
                self.accessToken = ""
                self.updateCurrentAccount(account: nil)
            })
            
        }
    }

O código verifica a existência do applicationContext, currentAccount e webViewParamaters. Em seguida, ele registra o processo de saída. O código remove todos os tokens do cache para a conta fornecida. Dependendo do modo de dispositivo atual, ele determina se deseja sair do navegador. Após a conclusão, ele atualiza o texto de log adequadamente. Se ocorrer um erro durante o processo de saída, ele registrará a mensagem de erro em log. Após a saída bem-sucedida, ele atualiza o token de acesso para uma cadeia de caracteres vazia e limpa a conta atual.

Próximas etapas

Tutorial: Chamar uma API Web protegida no aplicativo iOS (Swift).