Esercitazione - Accesso degli utenti all'app per dispositivi mobili iOS (Swift)
Questa è la terza esercitazione della serie di esercitazioni relative all'accesso degli utenti usando Microsoft Entra per ID esterno.
In questa esercitazione si apprenderà come:
- Consentire l'accesso all'utente.
- Disconnettere l'utente.
Prerequisiti
Consentire l'accesso degli utenti
Sono disponibili due opzioni principali per consentire l'accesso degli utenti tramite MSAL (Microsoft Authentication Library) per iOS: l'acquisizione di token in modo interattivo o invisibile all'utente.
Per l'accesso dell'utente in modo interattivo, usare il codice seguente:
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) } }
Il codice controlla innanzitutto se sono disponibili i parametri del contesto dell'applicazione e della visualizzazione Web. Successivamente, aggiorna la registrazione per indicare che sta acquisendo il token in modo interattivo. Quindi configura i parametri per l'acquisizione interattiva del token, specificando gli ambiti e i parametri della visualizzazione Web. Inoltre, imposta il tipo di richiesta per selezionare un account.
A questo punto, chiama il metodo
acquireToken
nel contesto dell'applicazione con i parametri definiti. Nel gestore di completamento verifica la presenza di eventuali errori. Se viene rilevato un errore, aggiorna la registrazione con il messaggio di errore. In caso di esito positivo, recupera il token di accesso dal risultato, aggiorna la registrazione con il token e l'account corrente.Quando l'app ha acquisito un token di accesso, è possibile recuperare le attestazioni associate all'account corrente. Per completare questa operazione, usare il frammento di codice seguente:
let claims = result.account.accountClaims let preferredUsername = claims?["preferred_username"] as? String
Il codice legge le attestazioni dall'account accedendo alla proprietà
accountClaims
dell'oggettoresult.account
. Quindi recupera il valore dell'attestazione "preferred_username" dal dizionario delle attestazioni e lo assegna alla variabilepreferredUsername
.Per consentire l'accesso utente in modo invisibile all'utente, usare il codice seguente:
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) } }
Il codice avvia il processo di acquisizione dei token in modo invisibile all'utente. In primo luogo, tenta di caricare l'account corrente. Se trova un account corrente, procede all'acquisizione del token in modo invisibile all'utente tramite questo account. Se non trova alcun account corrente, aggiorna la registrazione per indicare che non è stato trovato alcun token e suggerisce di provare ad acquisire un token in modo interattivo.
Nel codice precedente vengono chiamate due funzioni,
loadCurrentAccount
eacquireTokenSilently
. La funzioneloadCurrentAccount
deve avere il codice seguente: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) } }) }
Il codice si avvale di MSAL per iOS per caricare l'account corrente. Esso verifica la presenza di errori e aggiorna la registrazione di conseguenza. Se trova un account corrente, lo aggiorna e tenta di acquisire i token in modo invisibile all'utente. Se esiste un account precedente, registra la disconnessione. Se non trova alcun account, cancella il token di accesso. Infine, esegue un blocco di completamento, se specificato.
La funzione
acquireTokenSilently
deve contenere il codice seguente: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) } }
Questa funzione si avvale di MSAL per iOS per acquisire un token per un account esistente. Dopo avere verificato
applicationContext
, registra il processo di acquisizione del token. TramiteMSALSilentTokenParameters
, definisce i parametri necessari. Poi tenta di acquisire il token in modo invisibile all'utente. In caso di errori, verifica la presenza di requisiti di interazione dell'utente, se necessario, avviando un processo interattivo. Al termine dell'operazione, aggiorna la proprietàaccessToken
e registra il token aggiornato, infine abilita il pulsante di disconnessione.
SignOutUser
Per disconnettere un utente dall'app iOS (Swift) tramite MSAL per iOS, usare il codice seguente:
@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)
})
}
}
Il codice verifica l'esistenza di applicationContext
, currentAccount
e webViewParamaters
. Successivamente, registra il processo di disconnessione. Il codice rimuove tutti i token dalla cache per l'account specificato. A seconda della modalità del dispositivo corrente, esso determina se disconnettersi dal browser. Al termine, aggiorna il testo di registrazione di conseguenza. Se si verifica un errore durante il processo di disconnessione, il messaggio di errore viene registrato. Al termine dell'operazione di disconnessione, aggiorna il token di accesso su una stringa vuota e cancella l'account corrente.
Passaggi successivi
Esercitazione - Chiamare un'API Web protetta nell'app iOS (Swift).