Condividi tramite


Abilitare l'autenticazione nell'app Swift iOS usando Azure AD B2C

Questo articolo illustra come aggiungere l'autenticazione di Azure Active Directory B2C (Azure AD B2C) all'applicazione per dispositivi mobili iOS Swift. Informazioni su come integrare un'applicazione iOS Swift con Microsoft Authentication Library (MSAL) per iOS.

Usare questo articolo con Configurare l'autenticazione in un'applicazione swift iOS di esempio, sostituendo l'app iOS Swift di esempio con l'app iOS Swift personalizzata. Dopo aver completato le istruzioni in questo articolo, l'applicazione accetterà gli accessi tramite Azure AD B2C.

Prerequisiti

Esaminare i prerequisiti e le istruzioni di integrazione in Configurare l'autenticazione in un'app iOS Swift di esempio usando Azure AD B2C.

Creare un progetto di app iOS Swift

Se non si dispone già di un'applicazione Swift iOS, configurare un nuovo progetto eseguendo questa procedura:

  1. Aprire Xcode e quindi selezionare File>Nuovo>progetto.
  2. Per le app iOS selezionare App iOS> e quindi avanti.
  3. Per Scegliere le opzioni per il nuovo progetto, specificare quanto segue:
    1. Nome prodotto, ad esempio MSALiOS.
    2. Identificatore dell'organizzazione, ad esempio contoso.com.
    3. Per Interfaccia selezionare Storyboard.
    4. Per il ciclo di vita selezionare Delegato app UIKit.
    5. Per lingua selezionare Swift.
  4. Selezionare Avanti.
  5. Selezionare una cartella in cui creare l'app e quindi selezionare Crea.

Passaggio 1: Installare la libreria MSAL

  1. Usare CocoaPods per installare la libreria MSAL. Nella stessa cartella del file con estensione xcodeproj del progetto, se il file podfile non esiste, creare un file vuoto e denominarlo podfile. Aggiungere il codice seguente al file podfile :

    use_frameworks!
    
    target '<your-target-here>' do
       pod 'MSAL'
    end
    
  2. Sostituire <your-target-here> con il nome del progetto , ad esempio MSALiOS. Per altre informazioni, vedere Informazioni di riferimento sulla sintassi podfile.

  3. In una finestra del terminale passare alla cartella contenente il file podfile e quindi eseguire l'installazione del pod per installare la libreria MSAL.

  4. Dopo aver eseguito il pod install comando, viene creato un <file project name.xcworkspace>. Per ricaricare il progetto in Xcode, chiudere Xcode e quindi aprire il <file nome> progetto.xcworkspace .

Passaggio 2: Impostare lo schema dell'URL dell'app

Quando gli utenti eseguono l'autenticazione, Azure AD B2C invia un codice di autorizzazione all'app usando l'URI di reindirizzamento configurato nella registrazione dell'applicazione Azure AD B2C.

Il formato URI di reindirizzamento predefinito di MSAL è msauth.[Your_Bundle_Id]://auth. Un esempio è msauth.com.microsoft.identitysample.MSALiOS://auth, dove msauth.com.microsoft.identitysample.MSALiOS è lo schema URL.

In questo passaggio registrare lo schema URL usando la CFBundleURLSchemes matrice. L'applicazione è in ascolto dello schema URL per il callback da Azure AD B2C.

In Xcode aprire il file Info.plist come file di codice sorgente. <dict> Nella sezione aggiungere il frammento XML seguente:

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>msauth.com.microsoft.identitysample.MSALiOS</string>
        </array>
    </dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>msauthv2</string>
    <string>msauthv3</string>
</array>

Passaggio 3: Aggiungere il codice di autenticazione

Il codice di esempio è costituito da una UIViewController classe. Classe:

  • Definisce la struttura per un'interfaccia utente.
  • Contiene informazioni sul provider di identità di Azure AD B2C. L'app usa queste informazioni per stabilire una relazione di trust con Azure AD B2C.
  • Contiene il codice di autenticazione per autenticare gli utenti, acquisire i token e convalidarli.

Scegliere un UIViewController oggetto in cui gli utenti eseguono l'autenticazione. UIViewControllerNell'oggetto unire il codice con il codice fornito in GitHub.

Passaggio 4: Configurare l'app iOS Swift

Dopo aver aggiunto il codice di autenticazione, configurare l'app iOS Swift con le impostazioni di Azure AD B2C. Le impostazioni del UIViewController provider di identità B2C di Azure AD sono configurate nella classe scelta nella sezione precedente.

Per informazioni su come configurare l'app iOS Swift, vedere Configurare l'autenticazione in un'app iOS Swift di esempio usando Azure AD B2C.

Passaggio 5: Eseguire e testare l'app per dispositivi mobili

  1. Compilare ed eseguire il progetto con un simulatore di un dispositivo iOS connesso.
  2. Selezionare Accedi e quindi iscriversi o accedere con l'account locale o social network di Azure AD B2C.
  3. Dopo aver eseguito l'autenticazione, verrà visualizzato il nome visualizzato nella barra di spostamento.

Passaggio 6: Personalizzare i blocchi predefiniti del codice

Questa sezione descrive i blocchi predefiniti del codice che consentono l'autenticazione per l'app iOS Swift. Elenca i metodi di UIViewController e illustra come personalizzare il codice.

Passaggio 6.1: Creare un'istanza di un'applicazione client pubblica

Le applicazioni client pubbliche non sono attendibili per mantenere in modo sicuro i segreti dell'applicazione e non hanno segreti client. In viewDidLoad creare un'istanza di MSAL usando un oggetto applicazione client pubblico.

Il frammento di codice Swift seguente illustra come inizializzare MSAL con un MSALPublicClientApplicationConfig oggetto di configurazione.

L'oggetto di configurazione fornisce informazioni sull'ambiente Azure AD B2C. Ad esempio, fornisce l'ID client, l'URI di reindirizzamento e l'autorità per compilare le richieste di autenticazione in Azure AD B2C. Per informazioni sull'oggetto di configurazione, vedere Configurare l'app per dispositivi mobili di esempio.

do {

    let signinPolicyAuthority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)
    let editProfileAuthority = try self.getAuthority(forPolicy: self.kEditProfilePolicy)
    
    let pcaConfig = MSALPublicClientApplicationConfig(clientId: kClientID, redirectUri: kRedirectUri, authority: signinPolicyAuthority)
    pcaConfig.knownAuthorities = [signinPolicyAuthority, editProfileAuthority]
    
    self.applicationContext = try MSALPublicClientApplication(configuration: pcaConfig)
    self.initWebViewParams()
    
    } catch {
        self.updateLoggingText(text: "Unable to create application \(error)")
    }

Il initWebViewParams metodo configura l'esperienza di autenticazione interattiva .

Il frammento di codice Swift seguente inizializza il webViewParameters membro della classe con la visualizzazione Web di sistema. Per altre informazioni, vedere Personalizzare browser e WebViews per iOS/macOS.

func initWebViewParams() {
    self.webViewParameters = MSALWebviewParameters(authPresentationViewController: self)
    self.webViewParameters?.webviewType = .default
}

Passaggio 6.2: Avviare una richiesta di autorizzazione interattiva

Una richiesta di autorizzazione interattiva è un flusso in cui gli utenti vengono richiesti di iscriversi o accedere usando la visualizzazione Web di sistema. Quando gli utenti selezionano il pulsante Accedi , viene chiamato il authorizationButton metodo .

Il authorizationButton metodo prepara l'oggetto MSALInteractiveTokenParameters con dati pertinenti sulla richiesta di autorizzazione. Il acquireToken metodo usa l'oggetto MSALInteractiveTokenParameters per autenticare gli utenti tramite la visualizzazione Web del sistema.

Il frammento di codice seguente illustra come avviare la richiesta di autorizzazione interattiva:

let parameters = MSALInteractiveTokenParameters(scopes: kScopes, webviewParameters: self.webViewParameters!)
parameters.promptType = .selectAccount
parameters.authority = authority

applicationContext.acquireToken(with: parameters) { (result, error) in

// On error code    
guard let result = result else {
    self.updateLoggingText(text: "Could not acquire token: \(error ?? "No error information" as! Error)")
    return
}

// On success code
self.accessToken = result.accessToken
self.updateLoggingText(text: "Access token is \(self.accessToken ?? "Empty")")
}

Dopo aver completato il flusso di autorizzazione, il risultato viene restituito alla chiusura del acquireToken metodo.

Il acquireToken metodo restituisce gli result oggetti e error . Usare questa chiusura per:

  • Aggiornare l'interfaccia utente dell'app per dispositivi mobili con informazioni dopo il completamento dell'autenticazione.
  • Chiamare un servizio API Web con un token di accesso.
  • Gestire gli errori di autenticazione, ad esempio quando un utente annulla il flusso di accesso.

Passaggio 6.3: Chiamare un'API Web

Per chiamare un'API Web di autorizzazione basata su token, l'app necessita di un token di accesso valido. L'app esegue le operazioni seguenti:

  1. Acquisisce un token di accesso con le autorizzazioni necessarie (ambiti) per l'endpoint api Web.
  2. Passa il token di accesso come token di connessione nell'intestazione di autorizzazione della richiesta HTTP usando questo formato:
Authorization: Bearer <access-token>

Quando gli utenti eseguono l'autenticazione interattiva, l'app ottiene un token di accesso nella acquireToken chiusura. Per le chiamate API Web successive, usare il metodo di acquisizione del token invisibile all'utente (acquireTokenSilent), come descritto in questa sezione.

Il acquireTokenSilent metodo esegue le azioni seguenti:

  1. Tenta di recuperare un token di accesso con gli ambiti richiesti dalla cache dei token. Se il token è presente e non è scaduto, il token viene restituito.
  2. Se il token non è presente nella cache dei token o è scaduto, la libreria MSAL tenta di usare il token di aggiornamento per acquisire un nuovo token di accesso.
  3. Se il token di aggiornamento non esiste o è scaduto, viene restituita un'eccezione. In questo caso, è necessario richiedere all'utente di accedere in modo interattivo.

Il frammento di codice seguente illustra come acquisire un token di accesso:

do {

// Get the authority using the sign-in or sign-up user flow
let authority = try self.getAuthority(forPolicy: self.kSignupOrSigninPolicy)

// Get the current account from the application context
guard let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy) else {
    self.updateLoggingText(text: "There is no account available!")
    return
}

// Configure the acquire token silent parameters
let parameters = MSALSilentTokenParameters(scopes: kScopes, account:thisAccount)
parameters.authority = authority
parameters.loginHint = "username"

// Acquire token silent
self.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) {
                
                // Start an interactive authorization code
                // Notice we supply the account here. This ensures we acquire token for the same account
                // as we originally authenticated.
                
                ...
            }
        }
        
        self.updateLoggingText(text: "Could not acquire token: \(error)")
        return
    }
    
    guard let result = result else {
        
        self.updateLoggingText(text: "Could not acquire token: No result returned")
        return
    }
    
    // On success, set the access token to the accessToken class member. 
    // The callGraphAPI method uses the access token to call a web API  
    self.accessToken = result.accessToken
    ...
}
} catch {
self.updateLoggingText(text: "Unable to construct parameters before calling acquire token \(error)")
}

Il callGraphAPI metodo recupera il token di accesso e chiama l'API Web, come illustrato di seguito:

@objc func callGraphAPI(_ sender: UIButton) {
    guard let accessToken = self.accessToken else {
        self.updateLoggingText(text: "Operation failed because could not find an access token!")
        return
    }
    
    let sessionConfig = URLSessionConfiguration.default
    sessionConfig.timeoutIntervalForRequest = 30
    let url = URL(string: self.kGraphURI)
    var request = URLRequest(url: url!)
    request.setValue("Bearer \(accessToken)", forHTTPHeaderField: "Authorization")
    let urlSession = URLSession(configuration: sessionConfig, delegate: self, delegateQueue: OperationQueue.main)
    
    self.updateLoggingText(text: "Calling the API....")
    
    urlSession.dataTask(with: request) { data, response, error in
        guard let validData = data else {
            self.updateLoggingText(text: "Could not call API: \(error ?? "No error information" as! Error)")
            return
        }
        
        let result = try? JSONSerialization.jsonObject(with: validData, options: [])
        
        guard let validResult = result as? [String: Any] else {
            self.updateLoggingText(text: "Nothing returned from API")
            return
        }
        
        self.updateLoggingText(text: "API response: \(validResult.debugDescription)")
        }.resume()
}

Passaggio 6.4: Disconnettersi dagli utenti

La disconnessione con MSAL rimuove tutte le informazioni note sugli utenti dall'applicazione. Usare il metodo di disconnesso per disconnettere gli utenti e aggiornare l'interfaccia utente. Ad esempio, è possibile nascondere gli elementi dell'interfaccia utente protetti, nascondere il pulsante di disconnessione o visualizzare il pulsante di accesso.

Il frammento di codice seguente illustra come disconnettere gli utenti:

@objc func signoutButton(_ sender: UIButton) {
do {
    
    
    let thisAccount = try self.getAccountByPolicy(withAccounts: applicationContext.allAccounts(), policy: kSignupOrSigninPolicy)
    
    if let accountToRemove = thisAccount {
        try applicationContext.remove(accountToRemove)
    } else {
        self.updateLoggingText(text: "There is no account to signing out!")
    }
    
    ...
    
} catch  {
    self.updateLoggingText(text: "Received error signing out: \(error)")
}
}

Passaggi successivi

Viene illustrato come: