Condividi tramite


Esercitazione: Aggiungere l'accesso e la disconnessione nell'app iOS/macOS usando l'autenticazione nativa

Si applica aCerchio verde con un segno di spunta bianco. iOS (Swift) Cerchio verde con un segno di spunta bianco. macOS (Swift)

Questa esercitazione illustra come consentire l'accesso e la disconnessione di un utente usando il passcode monouso tramite posta elettronica o username e password nell'app iOS/macOS utiizzando l'autenticazione nativa.

In questa esercitazione apprenderai a:

  • Far accedere un utente usando il passcode monouso o il nome utente (e-mail) e la password.
  • Disconnettere un utente.
  • Gestire gli errori di accesso

Prerequisiti

Consentire l'accesso degli utenti

Per consentire l'accesso a un utente usando il flusso Passcode monouso tramite posta elettronica, acquisire l'indirizzo di posta elettronica e inviare un messaggio contenente un passcode monouso per permettere all'utente di verificare il proprio indirizzo. Quando l'utente immette un passcode monouso valido, l'app gli consente di accedere.

Per far accedere un utente usando il flusso di posta elettronica con password, acquisire il messaggio di posta elettronica e la password. Se il nome utente e la password sono validi, l'app consente all'utente di accedere.

Per far accedere un utente, è necessario:

  1. Creare un'interfaccia utente (IU) per:

    • Acquisire un’e-mail dall'utente. Aggiungere la convalida agli input per accertarsi che l'utente immetta un indirizzo di posta elettronica valido.
    • Acquisire una password se si effettua l'iscrizione con il nome utente (e-mail) e la password.
    • Raccogliere un passcode monouso tramite posta elettronica dall'utente se si accede con passcode monouso tramite posta elettronica.
    • Aggiungere un pulsante per consentire all'utente di inviare nuovamente il passcode monouso se si accede con passcode monouso tramite posta elettronica.
  2. Nell'interfaccia utente aggiungere un pulsante, la cui selezione avvia un accesso, come illustrato nel frammento di codice seguente:

        @IBAction func signInPressed(_: Any) {
        guard let email = emailTextField.text else {
            resultTextView.text = "email not set"
            return
        }
    
        nativeAuth.signIn(username: email, delegate: self)
    }
    

    Per far accedere un utente usando il flusso di passcode monouso tramite posta elettronica, viene usato il frammento di codice seguente:

    nativeAuth.signIn(username: email, delegate: self)
    

    Il metodo signIn(username:delegate), che risponde in modo asincrono chiamando uno dei metodi sull'oggetto delegato passato, deve implementare il protocollo SignInStartDelegate. Si passa l'indirizzo di posta elettronica che l'utente fornisce nel modulo di invio dell'indirizzo e si passa self come delegato.

    Per far accedere un utente usando il flusso di posta elettronica con password, viene usato il frammento di codice seguente:

    nativeAuth.signIn(username: email, password: password, delegate: self)
    

    Nel metodo signIn(username:password:delegate) si passa l'indirizzo e-mail fornito dall'utente, la password e l'oggetto delegato conforme al protocollo SignInStartDelegate. Per questo esempio, si passa self.

  3. Per implementare il protocollo SignInStartDelegate quando si usa il flusso di passcode monouso tramite posta elettronica, usare il frammento di codice seguente:

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCodeRequired(
            newState: MSAL.SignInCodeRequiredState,
            sentTo: String,
            channelTargetType: MSAL.MSALNativeAuthChannelType,
            codeLength: Int
        ) {
            resultTextView.text = "Verification code sent to \(sentTo)"
        }
    }
    

    La chiamata a signIn(username:delegate) implica una chiamata a metodi delegati. Nello scenario più comune viene chiamato onSignInCodeRequired(newState:sentTo:channelTargetType:codeLength) per indicare che è stato inviato un codice per verificare l'indirizzo di posta elettronica dell'utente. Oltre ad alcuni dettagli sul destinatario del codice e sul numero di cifre che lo compongono, questo metodo delegato ha anche un parametro newState di tipo SignInCodeRequiredState, che consente di accedere ai due nuovi metodi seguenti:

    • submitCode(code:delegate)
    • resendCode(delegate)

    Usare submitCode(code:delegate) per inviare il passcode monouso fornito dall'utente nell'apposito modulo, usare il frammento di codice seguente:

    newState.submitCode(code: userSuppliedCode, delegate: self)
    

    submitCode(code:delegate) accetta il passcode monouso e il parametro delegato. Dopo aver inviato il codice, è necessario verificare il passcode monouso implementando il protocollo SignInVerifyCodeDelegate.

    Per implementare il protocollo SignInVerifyCodeDelegate come estensione della propria classe, usare il frammento di codice seguente:

    extension ViewController: SignInVerifyCodeDelegate {
        func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
            resultTextView.text = "Signed in successfully."
            result.getAccessToken(delegate: self)
        }
    }
    

    Nello scenario più comune si riceve una chiamata a onSignInCompleted(result), che indica che all'utente è stato consentito di accedere. Il risultato può essere usato per recuperare l'oggetto access token.

    getAccessToken(delegate) accetta un parametro delegato e occorre implementare i metodi richiesti nel protocollo CredentialsDelegate.

    Nello scenario più comune viene ricevuta una chiamata a onAccessTokenRetrieveCompleted(result) che indica che l'utente ha ottenuto un oggetto access token.

    extension ViewController: CredentialsDelegate {
        func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) {
            resultTextView.text = "Error retrieving access token"
        }
    
        func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) {
            resultTextView.text = "Signed in. Access Token: \(result.accessToken)"
        }
    }
    
    
  4. Per implementare il protocollo SignInStartDelegate quando si usa il flusso di posta elettronica con password, usare il frammento di codice seguente:

    extension ViewController: SignInStartDelegate {
        func onSignInStartError(error: MSAL.SignInStartError) {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    
        func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
            // User successfully signed in
        }
    }
    

    Nello scenario più comune si riceve una chiamata a onSignInCompleted(result), che indica che all'utente è stato consentito di accedere. Il risultato può essere usato per recuperare l'oggetto access token.

    getAccessToken(delegate) accetta un parametro delegato e occorre implementare i metodi richiesti nel protocollo CredentialsDelegate.

    Nello scenario più comune viene ricevuta una chiamata a onAccessTokenRetrieveCompleted(result) che indica che l'utente ha ottenuto un oggetto access token.

    extension ViewController: CredentialsDelegate {
        func onAccessTokenRetrieveError(error: MSAL.RetrieveAccessTokenError) {
            resultTextView.text = "Error retrieving access token"
        }
    
        func onAccessTokenRetrieveCompleted(result: MSALNativeAuthTokenResult) {
            resultTextView.text = "Signed in. Access Token: \(result.accessToken)"
        }
    }
    
    

Gestire gli errori di accesso

Durante l'accesso non tutte le azioni vengono completate correttamente. Ad esempio, l'utente potrebbe provare a eseguire l'accesso con un indirizzo di posta elettronica non esistente oppure inviare un codice non valido.

  1. Per gestire gli errori nel metodo signIn(username) o signIn(username, password), usare il frammento di codice seguente:

    func onSignInStartError(error: MSAL.SignInStartError) {
        if error.isUserNotFound || error.isInvalidUsername {
            resultTextView.text = "Invalid username"
        } else {
            resultTextView.text = "Error signing in: \(error.errorDescription ?? "no description")"
        }
    }
    
  2. Per gestire gli errori nel metodo submitCode(), usare il frammento di codice seguente:

    func onSignInVerifyCodeError(error: MSAL.VerifyCodeError, newState: MSAL.SignInCodeRequiredState?) {
        if error.isInvalidCode {
            // Inform the user that the submitted code was incorrect and ask for a new code to be supplied
            let userSuppliedCode = retrieveNewCode()
            newState?.submitCode(code: userSuppliedCode, delegate: self)
        } else {
            resultTextView.text = "Error verifying code: \(error.errorDescription ?? "no description")"
        }
    }
    

    Se l'utente immette un codice di verifica di posta elettronica non corretto, il gestore degli errori include un riferimento a SignInCodeRequiredState che può essere usato per inviare un codice aggiornato. Nell'implementazione precedente del protocollo SignInVerifyCodeDelegate l'errore veniva semplicemente visualizzato durante la gestione della funzione di delegato onSignInVerifyCodeError(error:newState).

Leggere le attestazioni del token ID

Quando l'app ha acquisito un token ID, è possibile recuperare le attestazioni associate all'account corrente. Per completare questa operazione, usare il frammento di codice seguente:

func onSignInCompleted(result: MSAL.MSALNativeAuthUserAccountResult) {
   let claims = result.account.accountClaims
   let preferredUsername = claims?["preferred_username"] as? String
}

La chiave usata per accedere al valore dell'attestazione è il nome specificato quando si aggiunge l'attributo utente come attestazione token.

Informazioni su come aggiungere attributi predefiniti e personalizzati come attestazioni token nell'articolo Aggiungere attributi utente alle attestazioni token.

SignOutUser

Per disconnettere un utente, usare il riferimento a MSALNativeAuthUserAccountResult ricevuto nel callback onSignInCompleted oppure usare getNativeAuthUserAccount() per ottenere qualsiasi account connesso dalla cache e archiviare un riferimento nella variabile membro accountResult.

  1. Configurare il gruppo di keychain per il progetto come descritto qui.

  2. Aggiungere una nuova variabile membro alla classe ViewController: var accountResult: MSALNativeAuthUserAccountResult?.

  3. Aggiornare viewDidLoad per recuperare eventuali account memorizzati nella cache aggiungendo questa riga dopo la corretta inizializzazione di nativeAuth: accountResult = nativeAuth.getNativeAuthUserAccount().

  4. Aggiornare il gestore signInCompleted per archiviare il risultato dell'account:

    func onSignInCompleted(result: MSALNativeAuthUserAccountResult) {
        resultTextView.text = "Signed in successfully"
    
        accountResult = result
    }
    
  5. Aggiungere un pulsante Disconnetti e usare il codice seguente per disconnettere l'utente:

    @IBAction func signOutPressed(_: Any) {
        guard let accountResult = accountResult else {
            print("Not currently signed in")
            return
        }
    
        accountResult.signOut()
    
        self.accountResult = nil
    
        resultTextView.text = "Signed out"
    }
    

Sono stati completati tutti i passaggi necessari per disconnettere un utente nell'app. Compilare ed eseguire l'applicazione. Se tutto va bene, si dovrebbe riuscire a selezionare il pulsante Disconnetti per una corretta disconnessione.

Configurare un provider di attestazioni personalizzato

Se si desidera aggiungere attestazioni da un sistema esterno al token rilasciato all'app, usare un provider di attestazioni personalizzato. Un provider di attestazioni personalizzato è costituito da un'estensione di autenticazione personalizzata che chiama un'API REST per recuperare le attestazioni da sistemi esterni.

Seguire la procedura descritta in Configurare un provider di attestazioni personalizzato per aggiungere attestazioni da un sistema esterno ai token di sicurezza.