Udostępnij za pośrednictwem


Samouczek: logowanie użytkowników w aplikacji mobilnej systemu iOS (Swift)

Jest to trzeci samouczek z serii samouczków, który przeprowadzi Cię przez proces logowania użytkowników przy użyciu identyfikatora Entra firmy Microsoft.

Przed rozpoczęciem użyj selektora Wybierz typ najemcy znajdującego się w górnej części tej strony, aby wybrać typ najemcy. Microsoft Entra ID oferuje dwie konfiguracje dzierżawy: pracowników i zewnętrzna. Konfiguracja dzierżawy zasobów pracowniczych obejmuje pracowników, aplikacje wewnętrzne i inne zasoby organizacyjne. Zewnętrzny dzierżawca jest przeznaczony dla aplikacji skierowanych do klientów.

W tym samouczku:

  • Zaloguj się użytkownik.
  • Wyloguj użytkownika.
  • Tworzenie interfejsu użytkownika aplikacji

Warunki wstępne

Logowanie użytkownika

Istnieją dwie główne opcje logowania użytkowników przy użyciu biblioteki Microsoft Authentication Library (MSAL) dla systemu iOS: uzyskiwanie tokenów interaktywnie lub dyskretnie.

  1. Aby interaktywnie zalogować się użytkownika, użyj następującego kodu:

    func acquireTokenInteractively() {
    
        guard let applicationContext = self.applicationContext else { return }
        guard let webViewParameters = self.webViewParameters else { return }
    
        // #1
        let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: webViewParameters)
        parameters.promptType = .selectAccount
    
        // #2
        applicationContext.acquireToken(with: parameters) { (result, error) in
    
            // #3
            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
            }
    
            // #4
            self.accessToken = result.accessToken
            self.updateLogging(text: "Access token is \(self.accessToken)")
            self.updateCurrentAccount(account: result.account)
            self.getContentWithToken()
        }
    }
    

    Właściwość promptType elementu MSALInteractiveTokenParameters konfiguruje zachowanie uwierzytelniania i monitu o wyrażenie zgody. Obsługiwane są następujące wartości:

    • .promptIfNecessary (wartość domyślna) — użytkownik jest monitowany tylko w razie potrzeby. Doświadczenie logowania jednokrotnego (SSO) jest określane przez obecność plików cookie w interfejsie przeglądarki oraz rodzaj konta. Jeśli wielu użytkowników jest zalogowanych, zostanie wyświetlony proces wyboru konta. Jest to domyślne zachowanie.
    • .selectAccount — jeśli żaden użytkownik nie zostanie określony, w widoku internetowym uwierzytelniania zostanie wyświetlona lista aktualnie zalogowanych kont dla użytkownika do wyboru.
    • .login — wymaga uwierzytelnienia użytkownika w widoku internetowym. Tylko jedno konto może być zalogowane naraz, jeśli określisz tę wartość.
    • .consent — wymaga od użytkownika wyrażenia zgody na bieżący zestaw zakresów żądania.
  2. Aby zalogować użytkownika w trybie dyskretnym, użyj następującego kodu:

    
        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.
             */
    
            let parameters = MSALSilentTokenParameters(scopes: 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)
                self.getContentWithToken()
            }
        }
    

    Metoda acquireTokenSilently próbuje w sposób dyskretny uzyskać token dostępu dla istniejącego konta MSAL. Używa applicationContext do żądania tokenu z określonymi zakresami. Jeśli wystąpi błąd, sprawdza, czy jest wymagana interakcja użytkownika, a jeśli tak, inicjuje pozyskiwanie tokenu interakcyjnego. Po powodzeniu aktualizuje token dostępu, rejestruje wynik, włącza przycisk wylogowywanie i pobiera zawartość przy użyciu tokenu.

Obsługa wywołania zwrotnego logowania (tylko system iOS)

Otwórz plik AppDelegate.swift. Aby obsłużyć wywołanie zwrotne po zalogowaniu, dodaj MSALPublicClientApplication.handleMSALResponse do klasy appDelegate w następujący sposób:

// Inside AppDelegate...
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

        return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String)
}

Jeśli używasz środowiska Xcode 11, należy umieścić wywołanie zwrotne biblioteki MSAL w SceneDelegate.swift. Jeśli dla zgodności ze starszymi wersjami iOS obsługiwane są zarówno UISceneDelegate, jak i UIApplicationDelegate, wywołanie zwrotne MSAL musi zostać umieszczone w obu plikach.

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {

        guard let urlContext = URLContexts.first else {
            return
        }

        let url = urlContext.url
        let sourceApp = urlContext.options.sourceApplication

        MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: sourceApp)
    }

Wyloguj użytkownika

Ważny

Wylogowywanie przy użyciu biblioteki MSAL usuwa wszystkie znane informacje o użytkowniku z aplikacji, a także usuwa aktywną sesję na urządzeniu, jeśli jest to dozwolone przez konfigurację urządzenia. Możesz również opcjonalnie wylogować użytkownika z przeglądarki.

Aby dodać możliwość wylogowywania, dodaj następujący kod w klasie ViewController.

@objc func signOut(_ sender: AnyObject) {

        guard let applicationContext = self.applicationContext else { return }

        guard let account = self.currentAccount else { return }

        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: self.webViewParameters!)
            signoutParameters.signoutFromBrowser = false // set this to true if you also want to signout from browser or webview

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

        }
    }

Tworzenie interfejsu użytkownika aplikacji

Teraz utwórz interfejs użytkownika zawierający przycisk wywołujący interfejs API programu Microsoft Graph, inny do wylogowania i widok tekstowy, aby wyświetlić dane wyjściowe, dodając następujący kod do klasy ViewController:

Interfejs użytkownika systemu iOS

var loggingText: UITextView!
var signOutButton: UIButton!
var callGraphButton: UIButton!
var usernameLabel: UILabel!

func initUI() {

    usernameLabel = UILabel()
    usernameLabel.translatesAutoresizingMaskIntoConstraints = false
    usernameLabel.text = ""
    usernameLabel.textColor = .darkGray
    usernameLabel.textAlignment = .right

    self.view.addSubview(usernameLabel)

    usernameLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 50.0).isActive = true
    usernameLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10.0).isActive = true
    usernameLabel.widthAnchor.constraint(equalToConstant: 300.0).isActive = true
    usernameLabel.heightAnchor.constraint(equalToConstant: 50.0).isActive = true

    // Add call Graph button
    callGraphButton  = UIButton()
    callGraphButton.translatesAutoresizingMaskIntoConstraints = false
    callGraphButton.setTitle("Call Microsoft Graph API", for: .normal)
    callGraphButton.setTitleColor(.blue, for: .normal)
    callGraphButton.addTarget(self, action: #selector(callGraphAPI(_:)), for: .touchUpInside)
    self.view.addSubview(callGraphButton)

    callGraphButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    callGraphButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 120.0).isActive = true
    callGraphButton.widthAnchor.constraint(equalToConstant: 300.0).isActive = true
    callGraphButton.heightAnchor.constraint(equalToConstant: 50.0).isActive = true

    // Add sign out button
    signOutButton = UIButton()
    signOutButton.translatesAutoresizingMaskIntoConstraints = false
    signOutButton.setTitle("Sign Out", for: .normal)
    signOutButton.setTitleColor(.blue, for: .normal)
    signOutButton.setTitleColor(.gray, for: .disabled)
    signOutButton.addTarget(self, action: #selector(signOut(_:)), for: .touchUpInside)
    self.view.addSubview(signOutButton)

    signOutButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    signOutButton.topAnchor.constraint(equalTo: callGraphButton.bottomAnchor, constant: 10.0).isActive = true
    signOutButton.widthAnchor.constraint(equalToConstant: 150.0).isActive = true
    signOutButton.heightAnchor.constraint(equalToConstant: 50.0).isActive = true

    let deviceModeButton = UIButton()
    deviceModeButton.translatesAutoresizingMaskIntoConstraints = false
    deviceModeButton.setTitle("Get device info", for: .normal);
    deviceModeButton.setTitleColor(.blue, for: .normal);
    deviceModeButton.addTarget(self, action: #selector(getDeviceMode(_:)), for: .touchUpInside)
    self.view.addSubview(deviceModeButton)

    deviceModeButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    deviceModeButton.topAnchor.constraint(equalTo: signOutButton.bottomAnchor, constant: 10.0).isActive = true
    deviceModeButton.widthAnchor.constraint(equalToConstant: 150.0).isActive = true
    deviceModeButton.heightAnchor.constraint(equalToConstant: 50.0).isActive = true

    // Add logging textfield
    loggingText = UITextView()
    loggingText.isUserInteractionEnabled = false
    loggingText.translatesAutoresizingMaskIntoConstraints = false

    self.view.addSubview(loggingText)

    loggingText.topAnchor.constraint(equalTo: deviceModeButton.bottomAnchor, constant: 10.0).isActive = true
    loggingText.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 10.0).isActive = true
    loggingText.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -10.0).isActive = true
    loggingText.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 10.0).isActive = true
}

func platformViewDidLoadSetup() {

    NotificationCenter.default.addObserver(self,
                        selector: #selector(appCameToForeGround(notification:)),
                        name: UIApplication.willEnterForegroundNotification,
                        object: nil)

}

@objc func appCameToForeGround(notification: Notification) {
    self.loadCurrentAccount()
}

Interfejs użytkownika systemu macOS


var callGraphButton: NSButton!
var loggingText: NSTextView!
var signOutButton: NSButton!

var usernameLabel: NSTextField!

func initUI() {

    usernameLabel = NSTextField()
    usernameLabel.translatesAutoresizingMaskIntoConstraints = false
    usernameLabel.stringValue = ""
    usernameLabel.isEditable = false
    usernameLabel.isBezeled = false
    self.view.addSubview(usernameLabel)

    usernameLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 30.0).isActive = true
    usernameLabel.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10.0).isActive = true

    // Add call Graph button
    callGraphButton  = NSButton()
    callGraphButton.translatesAutoresizingMaskIntoConstraints = false
    callGraphButton.title = "Call Microsoft Graph API"
    callGraphButton.target = self
    callGraphButton.action = #selector(callGraphAPI(_:))
    callGraphButton.bezelStyle = .rounded
    self.view.addSubview(callGraphButton)

    callGraphButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    callGraphButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 50.0).isActive = true
    callGraphButton.heightAnchor.constraint(equalToConstant: 34.0).isActive = true

    // Add sign out button
    signOutButton = NSButton()
    signOutButton.translatesAutoresizingMaskIntoConstraints = false
    signOutButton.title = "Sign Out"
    signOutButton.target = self
    signOutButton.action = #selector(signOut(_:))
    signOutButton.bezelStyle = .texturedRounded
    self.view.addSubview(signOutButton)

    signOutButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    signOutButton.topAnchor.constraint(equalTo: callGraphButton.bottomAnchor, constant: 10.0).isActive = true
    signOutButton.heightAnchor.constraint(equalToConstant: 34.0).isActive = true
    signOutButton.isEnabled = false

    // Add logging textfield
    loggingText = NSTextView()
    loggingText.translatesAutoresizingMaskIntoConstraints = false

    self.view.addSubview(loggingText)

    loggingText.topAnchor.constraint(equalTo: signOutButton.bottomAnchor, constant: 10.0).isActive = true
    loggingText.leftAnchor.constraint(equalTo: self.view.leftAnchor, constant: 10.0).isActive = true
    loggingText.rightAnchor.constraint(equalTo: self.view.rightAnchor, constant: -10.0).isActive = true
    loggingText.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -10.0).isActive = true
    loggingText.widthAnchor.constraint(equalToConstant: 500.0).isActive = true
    loggingText.heightAnchor.constraint(equalToConstant: 300.0).isActive = true
}

func platformViewDidLoadSetup() {}

Następnie w klasie ViewController zastąp metodę viewDidLoad():

    override func viewDidLoad() {

        super.viewDidLoad()

        initUI()

        do {
            try self.initMSAL()
        } catch let error {
            self.updateLogging(text: "Unable to create Application Context \(error)")
        }

        self.loadCurrentAccount()
        self.platformViewDidLoadSetup()
    }

Następne kroki

Jest to trzeci samouczek z serii samouczków, który przeprowadzi Cię przez proces logowania użytkowników przy użyciu identyfikatora Entra firmy Microsoft.

Przed rozpoczęciem użyj selektora Wybierz typ najemcy na górze tej strony, aby wybrać typ najemcy. Identyfikator Entra Microsoft udostępnia dwa ustawienia dzierżawy, pracownicy i zewnętrzni. Konfiguracja struktury pracowniczej dotyczy pracowników, aplikacji wewnętrznych i innych zasobów organizacji. Zewnętrzny najemca przeznaczony jest dla aplikacji dla klientów.

W tym samouczku:

  • Zaloguj się użytkownik.
  • Wyloguj użytkownika.

Warunki wstępne

Logowanie użytkownika

Istnieją dwie główne opcje logowania użytkowników przy użyciu biblioteki Microsoft Authentication Library (MSAL) dla systemu iOS: uzyskiwanie tokenów interaktywnie lub dyskretnie.

  1. Aby interaktywnie zalogować się użytkownika, użyj następującego kodu:

    acquireTokenInteractively() {
        guard let applicationContext = self.applicationContext else { return }
        guard let webViewParameters = self.webViewParameters 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)
        }
    }
    

    Kod najpierw sprawdza, czy kontekst aplikacji i parametry widoku internetowego są dostępne. Następnie aktualizuje logowanie, aby wskazać, że token jest uzyskiwany interaktywnie. Następnie konfiguruje parametry pozyskiwania tokenu interakcyjnego, określając zakresy i parametry widoku internetowego. Ustawia również rodzaj monitu na wybór konta.

    Następnie wywołuje metodę acquireToken w kontekście aplikacji ze zdefiniowanymi parametrami. W funkcji obsługi zakończenia sprawdza się wszelkie błędy. Jeśli wystąpi błąd, zaktualizuje on rejestrowanie za pomocą komunikatu o błędzie. W przypadku powodzenia pobiera token dostępu z wyniku, aktualizuje rejestrowanie przy użyciu tokenu i aktualizuje bieżące konto.

    Gdy aplikacja uzyska token dostępu, możesz pobrać oświadczenia skojarzone z bieżącym kontem. W tym celu użyj następującego fragmentu kodu:

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

    Kod odczytuje oświadczenia z konta, korzystając z właściwości accountClaims obiektu result.account. Następnie pobiera wartość oświadczenia "preferred_username" ze słownika oświadczeń i przypisuje ją do zmiennej preferredUsername.

  2. Aby zalogować użytkownika w trybie dyskretnym, użyj następującego kodu:

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

    Kod inicjuje proces uzyskiwania tokenów w trybie dyskretnym. Najpierw próbuje załadować bieżące konto. Jeśli zostanie znalezione bieżące konto, przejdzie do uzyskania tokenu w trybie dyskretnym przy użyciu tego konta. Jeśli nie znaleziono bieżącego konta, system zaktualizuje logowanie, aby wskazać, że nie znaleziono tokenu, i sugeruje, aby spróbować zdobyć token w sposób interaktywny najpierw.

    W powyższym kodzie wywołujemy dwie funkcje, loadCurrentAccount i acquireTokenSilently. Funkcja loadCurrentAccount powinna mieć następujący kod:

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

    Kod używa biblioteki MSAL dla systemu iOS do załadowania bieżącego konta. Sprawdza błędy i odpowiednio aktualizuje rejestrowanie. Jeśli zostanie znalezione bieżące konto, aktualizuje je i próbuje uzyskać tokeny w trybie dyskretnym. Jeśli istnieje poprzednie konto, rejestruje wylogowanie. Jeśli nie znaleziono żadnych kont, czyści token dostępu. Na koniec wykonuje blok ukończenia, jeśli zostanie podany.

    Funkcja acquireTokenSilently powinna zawierać następujący kod:

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

    Ta funkcja używa biblioteki MSAL dla systemu iOS do dyskretnego uzyskiwania tokenu dla istniejącego konta. Po zweryfikowaniu applicationContextloguje proces pozyskiwania tokenu. Przy użyciu MSALSilentTokenParametersdefiniuje wymagane parametry. Następnie próbuje uzyskać token w trybie dyskretnym. Jeśli wystąpią błędy, sprawdza wymagania dotyczące interakcji z użytkownikiem, inicjując w razie potrzeby interaktywny proces. Po pomyślnym zakończeniu zaktualizuje właściwość accessToken i zapisze odświeżony token, kończąc przez włączenie przycisku wylogowania.

Wyloguj użytkownika

Aby wylogować użytkownika z aplikacji systemu iOS (Swift) przy użyciu biblioteki MSAL dla systemu iOS, użyj następującego kodu:

   @IBAction func signOut(_ sender: UIButton) {

        guard let applicationContext = self.applicationContext else { return }

        guard let account = self.currentAccount else { return }

        guard let webViewParameters = self.webViewParameters 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: webViewParameters)

            // If testing with Microsoft's shared device mode, trigger signout from browser. More details here:
            // https://docs.microsoft.com/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)
            })

        }
    }

Kod weryfikuje istnienie applicationContext, currentAccounti webViewParameters. Następnie rejestruje proces wylogowywania. Kod usuwa wszystkie tokeny z pamięci podręcznej dla podanego konta. W zależności od bieżącego trybu urządzenia określa, czy wylogować się z przeglądarki. Po zakończeniu aktualizuje odpowiednio tekst rejestrowania. Jeśli podczas procesu wylogowania wystąpi błąd, rejestruje komunikat o błędzie. Po pomyślnym wylogowaniu zmienia token dostępu na pusty ciąg znaków i usuwa dane bieżącego konta.

Następne kroki