Delen via


Zelfstudie: Gebruikers aanmelden in de mobiele iOS-app (Swift)

Dit is de derde zelfstudie in de reeks zelfstudies die u begeleidt bij het aanmelden van gebruikers met behulp van Microsoft Entra ID.

Voordat u begint, gebruikt u de Kies een tenanttype selector bovenaan deze pagina om het tenanttype te selecteren. Microsoft Entra ID biedt twee tenantconfiguraties, werknemers en externe. Een tenantconfiguratie voor werknemers is bedoeld voor uw werknemers, interne apps en andere organisatieresources. Een externe tenant is bedoeld voor uw klantgerichte apps.

In deze zelfstudie gaat u het volgende doen:

  • Gebruiker aanmelden.
  • Gebruiker afmelden
  • De gebruikersinterface van uw app maken

Voorwaarden

Gebruiker aanmelden

U hebt twee belangrijke opties voor het aanmelden van gebruikers met behulp van Microsoft Authentication Library (MSAL) voor iOS: tokens interactief of op de achtergrond verkrijgen.

  1. Gebruik de volgende code om de gebruiker interactief aan te melden:

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

    De eigenschap promptType van MSALInteractiveTokenParameters configureert het gedrag van de verificatie- en toestemmingsprompt. De volgende waarden worden ondersteund:

    • .promptIfNecessary (standaard): de gebruiker wordt alleen gevraagd indien nodig. De SSO-ervaring wordt bepaald door de aanwezigheid van cookies in de webweergave en het accounttype. Als meerdere gebruikers zijn aangemeld, wordt de accountselectieervaring weergegeven. Dit is het standaardgedrag.
    • .selectAccount: als er geen gebruiker is opgegeven, geeft de verificatiewebweergave een lijst weer met momenteel aangemelde accounts waaruit de gebruiker kan kiezen.
    • .login: vereist dat de gebruiker zich verifieert in de webweergave. Er kan slechts één account tegelijk worden aangemeld als u deze waarde opgeeft.
    • .consent - De gebruiker moet toestemming geven voor de huidige set scopes voor het verzoek.
  2. Gebruik de volgende code om de gebruiker stil aan te melden:

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

    De methode acquireTokenSilently probeert op de achtergrond een toegangstoken voor een bestaand MSAL-account te verkrijgen. Het gebruikt de applicationContext om het token met gespecificeerde reikwijdten aan te vragen. Als er een fout optreedt, wordt gecontroleerd of gebruikersinteractie is vereist en, als dat het geval is, wordt een interactieve tokenverwerving gestart. Wanneer het is gelukt, wordt het toegangstoken bijgewerkt, wordt het resultaat vastgelegd, wordt de afmeldingsknop ingeschakeld en wordt inhoud opgehaald met behulp van het token.

De aanmeldaanroep verwerken (alleen iOS)

Open het bestand AppDelegate.swift. Als u de callback na aanmelding wilt afhandelen, voegt u MSALPublicClientApplication.handleMSALResponse toe aan de appDelegate-klasse als volgt:

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

Als u Xcode 11gebruikt, moet u in plaats daarvan MSAL-callback plaatsen in de SceneDelegate.swift-. Als u zowel UISceneDelegate als UIApplicationDelegate ondersteunt voor compatibiliteit met oudere iOS, moet MSAL-callback in beide bestanden worden geplaatst.

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

Gebruiker afmelden

Belangrijk

Als u zich afmeldt met MSAL, worden alle bekende informatie over een gebruiker uit de toepassing verwijderd en wordt een actieve sessie op het apparaat verwijderd wanneer dit is toegestaan door de apparaatconfiguratie. U kunt de gebruiker ook afmelden in de browser.

Als u afmeldingsmogelijkheid wilt toevoegen, voegt u de volgende code toe in de ViewController-klasse.

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

        }
    }

De gebruikersinterface van uw app maken

Maak nu een gebruikersinterface met een knop om de Microsoft Graph API aan te roepen, een andere om u af te melden en een tekstweergave om uitvoer weer te geven door de volgende code toe te voegen aan de ViewController-klasse:

iOS-gebruikersinterface

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

macOS-gebruikersinterface


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

Vervang vervolgens in de klasse ViewController de viewDidLoad() methode door:

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

Volgende stappen

Dit is de derde zelfstudie in de reeks zelfstudies die u begeleidt bij het aanmelden van gebruikers met behulp van Microsoft Entra ID.

Voordat u begint, gebruikt u de Kies een tenanttype selector bovenaan deze pagina om het tenanttype te selecteren. Microsoft Entra ID biedt twee tenantconfiguraties, werknemers en externe. Een tenantconfiguratie voor werknemers is bedoeld voor uw werknemers, interne apps en andere organisatieresources. Een externe tenant is bedoeld voor uw klantgerichte apps.

In deze zelfstudie gaat u het volgende doen:

  • Gebruiker aanmelden.
  • Gebruiker afmelden

Voorwaarden

Gebruiker aanmelden

U hebt twee belangrijke opties voor het aanmelden van gebruikers met behulp van Microsoft Authentication Library (MSAL) voor iOS: tokens interactief of op de achtergrond verkrijgen.

  1. Gebruik de volgende code om de gebruiker interactief aan te melden:

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

    De code controleert eerst of de parameters voor de toepassingscontext en webweergave beschikbaar zijn. Vervolgens wordt de logboekregistratie bijgewerkt om aan te geven dat het token interactief wordt opgehaald. Vervolgens worden parameters ingesteld voor interactieve tokenverwerving, waarbij de toepassingsbereiken en webweergaveparameters worden opgegeven. Het stelt ook het prompttype in om een account te selecteren.

    Daarna wordt de acquireToken methode aangeroepen voor de toepassingscontext met de gedefinieerde parameters. In de voltooiingshandler wordt gecontroleerd op eventuele fouten. Als er een fout optreedt, wordt de logboekregistratie bijgewerkt met het foutbericht. Als dit lukt, wordt het toegangstoken opgehaald uit het resultaat, wordt de logboekregistratie bijgewerkt met het token en wordt het huidige account bijgewerkt.

    Zodra uw app een toegangstoken heeft verkregen, kunt u de claims ophalen die zijn gekoppeld aan het huidige account. Gebruik hiervoor het volgende codefragment:

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

    De code haalt claims op uit het account door toegang te krijgen tot de eigenschap accountClaims van het result.account-object. Vervolgens wordt de waarde van de claim 'preferred_username' opgehaald uit de claimwoordenlijst en wordt deze toegewezen aan de variabele preferredUsername.

  2. Gebruik de volgende code om de gebruiker stil aan te melden:

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

    De code initieert het proces van het verkrijgen van tokens stilletjes. Eerst wordt geprobeerd het huidige account te laden. Als er een huidig account wordt gevonden, wordt het token stilzwijgend verkregen met behulp van dat account. Als er geen huidig account wordt gevonden, wordt de logboekregistratie bijgewerkt om aan te geven dat er geen token wordt gevonden en wordt voorgesteld om eerst interactief een token te verkrijgen.

    In code hierboven roepen we twee functies aan, loadCurrentAccount en acquireTokenSilently. De functie loadCurrentAccount moet de volgende code hebben:

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

    De code gebruikt MSAL voor iOS om het huidige account te laden. Het controleert op fouten en werkt de logboekregistratie dienovereenkomstig bij. Als er een huidig account wordt gevonden, werkt het dit bij en probeert het stilletjes tokens te verkrijgen. Als er een eerder account bestaat, wordt de afmelding in een logboek opgeslagen. Als er geen accounts worden gevonden, wordt het toegangstoken gewist. Ten slotte voert het een voltooiingsblok uit, indien dit is opgegeven.

    De functie acquireTokenSilently moet de volgende code bevatten:

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

    Deze functie gebruikt MSAL voor iOS om op de achtergrond een token te verkrijgen voor een bestaand account. Nadat je de applicationContext hebt gecontroleerd, wordt het proces van tokenverwerving gelogd. Met behulp van MSALSilentTokenParametersworden de benodigde parameters gedefinieerd. Vervolgens wordt geprobeerd het token op stille wijze te verkrijgen. Als er fouten zijn, wordt gecontroleerd op vereisten voor gebruikersinteractie, waardoor zo nodig een interactief proces wordt gestart. Als dit is gelukt, wordt de eigenschap accessToken bijgewerkt en wordt het vernieuwde token geregistreerd. Dit wordt afgesloten door de knop Afmelden in te schakelen.

Gebruiker afmelden

Als u een gebruiker wilt afmelden bij uw iOS-app (Swift) met MSAL voor iOS, gebruikt u de volgende code:

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

        }
    }

De code verifieert het bestaan van de applicationContext, currentAccounten webViewParameters. Vervolgens wordt het afmeldingsproces in een logboek opgeslagen. De code verwijdert alle tokens uit de cache voor het opgegeven account. Afhankelijk van de huidige apparaatmodus wordt bepaald of u zich wilt afmelden bij de browser. Na voltooiing wordt de logboektekst dienovereenkomstig bijgewerkt. Als er een fout optreedt tijdens het afmeldingsproces, wordt het foutbericht in een logboek opgeslagen. Wanneer het afmelden is voltooid, wordt het toegangstoken bijgewerkt naar een lege tekenreeks en wordt het huidige account gewist.

Volgende stappen