Condividi tramite


Esercitazione: Aggiungere l'accesso all'app Android usando l'autenticazione nativa

Questa esercitazione illustra come accedere e disconnettere un utente con passcode monouso tramite posta elettronica o nome utente e password nell'app per dispositivi mobili Android usando 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

Accesso di un utente

Per accedere a un utente usando il passcode monouso, raccogliere il messaggio di posta elettronica e inviare un messaggio di posta elettronica contenente un passcode monouso per consentire all'utente di verificare il proprio messaggio di posta elettronica. Quando l'utente immette un passcode monouso valido, l'app gli consente di accedere.

Per accedere a un utente usando il nome utente (indirizzo di posta elettronica) e la password, raccogliere l'indirizzo di posta elettronica e la password dall'utente. 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.
    • Inviare nuovamente il passcode monouso (scelta consigliata) 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:

     CoroutineScope(Dispatchers.Main).launch {
         val parameters = NativeAuthSignInParameters(username = email)
         // Assign 'password' param if you sign in with username (email) and password
         // parameters.password = password
         val actionResult: SignInResult = authClient.signIn(parameters)
    
         if (actionResult is SignInResult.CodeRequired) {
             val nextState = actionResult.nextState
             val submitCodeActionResult = nextState.submitCode(
                 code = code
             )
             if (submitCodeActionResult is SignInResult.Complete) {
                 // Handle sign in success
                 val accountState = submitCodeActionResult.resultValue
    
                 val getAccessTokenParameters = NativeAuthGetAccessTokenParameters()
                 val accessTokenResult = accountState.getAccessToken(getAccessTokenParameters)
    
                 if (accessTokenResult is GetAccessTokenResult.Complete) {
                     val accessToken = accessTokenResult.resultValue.accessToken
                     val idToken = accountState.getIdToken()
                 }
             }
         }
     }
    

    Se l'utente non deve inviare un passcode, ad esempio quando un utente accede con posta elettronica e password, usare il frammento di codice seguente:

    CoroutineScope(Dispatchers.Main).launch {
        val parameters = NativeAuthSignInParameters(username = email)
        parameters.password = password
        val actionResult: SignInResult = authClient.signIn(parameters)
    
        if (actionResult is SignInResult.Complete) -> {
            // Handle sign in success
            val accountState = actionResult.resultValue
    
            val getAccessTokenParameters = NativeAuthGetAccessTokenParameters()
            val accessTokenResult = accountState.getAccessToken(getAccessTokenParameters)
    
            if (accessTokenResult is GetAccessTokenResult.Complete) {
                val accessToken = accessTokenResult.resultValue.accessToken
                val idToken = accountState.getIdToken()
            }
        }
    }
    
    • Per avviare il flusso di accesso, usare il metodo signIn(parameters) dell'SDK.
    • Istanza della classe NativeAuthSignInParameters contenente il username che corrisponde all'indirizzo di posta elettronica raccolto dall'utente.
    • Se il metodo di accesso è nome utente (indirizzo di posta elettronica) e password, il parametro password del metodo è la password che si raccoglie dall'utente.
    • Nello scenario più comune, il signIn(parameters) restituisce un risultato, SignInResult.CodeRequired, che indica che l'SDK prevede che l'app invii il passcode monouso di posta elettronica inviato all'indirizzo di posta elettronica dell'utente.
    • L'oggetto SignInResult.CodeRequired contiene un nuovo riferimento di stato, che è possibile recuperare tramite actionResult.nextState.
    • Il nuovo stato consente di accedere a due nuovi metodi:
      • submitCode() invia l’e-mail passcode monouso che l'app acquisisce dall'utente.
      • resendCode() invia nuovamente l’e-mail passcode monouso se l'utente non riceve il codice.

Gestire gli errori di accesso

Durante l'accesso, non tutte le azioni hanno esito positivo. Ad esempio, l'utente potrebbe tentare di accedere con un indirizzo di posta elettronica che non esiste o inviare un codice non valido.

Gestire gli errori di avvio dell'accesso

Per gestire gli errori nel metodo signIn(parameters), usare il frammento di codice seguente:

 val parameters = NativeAuthSignInParameters(username = email)
 // Assign 'password' param if you sign in with username (email) and password
 // parameters.password = password
val actionResult: SignInResult = authClient.signIn(parameters)

if (actionResult is SignInResult.CodeRequired) {
    // Next step: submit code
} else if (actionResult is SignInError) {
    // Handle sign in errors
    when {
         actionResult.isUserNotFound() -> {
             // Handle "user not found" error
         }
         actionResult.isAuthNotSupported() -> {
             // Handle "authentication type not support" error
         }
         actionResult.isInvalidCredentials() -> {
             // Handle specific errors
         }
         else -> {
             // Handle other errors
         }
     }
}
  • SignInError indica un risultato di azione non riuscito restituito da signIn(parameters), pertanto il risultato dell'azione non include un riferimento al nuovo stato.
  • Se actionResult is SignUpError, Android SDK fornisce metodi di utilità per consentire di analizzare ulteriormente gli errori specifici:
    • Il metodo isUserNotFound() controlla se l'utente accede con un nome utente (indirizzo di posta elettronica) che non esiste.
    • Il metodo isBrowserRequired() controlla la necessità di un browser (fallback Web), per completare il flusso di autenticazione. Questo scenario si verifica quando l'autenticazione nativa non è sufficiente per completare il flusso di autenticazione. Ad esempio, un amministratore configura l’e-mail e la password come metodo di autenticazione, ma l'app non riesce a inviare la password come tipologia di verifica o semplicemente non la supporta. Usare la procedura descritta in Supportare il fallback Web nell'app Android per gestire lo scenario in cui si verifica.
    • Il metodo isAuthNotSupported() controlla se l'app invia un tipo di verifica non supportato da Microsoft Entra, ovvero un valore del tipo di verifica diverso da oob e password. Altre informazioni sulle tipologie di verifica.
    • Per l'accesso con nome utente (posta elettronica) e password, il metodo isInvalidCredentials() controlla se la combinazione di nome utente e password non è corretta.

Gestire gli errori del codice di invio

Per gestire gli errori nel metodo submitCode(), usare il frammento di codice seguente:

val submitCodeActionResult = nextState.submitCode(
    code = code
)
if (submitCodeActionResult is SignInResult.Complete) {
    // Sign in flow complete, handle success state.
} else if (submitCodeActionResult is SubmitCodeError && submitCodeActionResult.isInvalidCode()) {
    // Handle "invalid code" error
}
  • L'errore SubmitCodeError indica un risultato dell'azione non riuscita restituito da submitCode() e quindi il risultato dell'azione non include un riferimento al nuovo stato.
  • Verifica isInvalidCode() la presenza dell'errore specifico. In questo caso, il riferimento allo stato precedente deve essere usato per ripetere l'azione.

Per recuperare il nuovo passcode monouso tramite posta elettronica, usare il frammento di codice seguente:

val submitCodeActionResult = nextState.submitCode(
    code = code
)
if (submitCodeActionResult is SignInError && submitCodeActionResult.isInvalidCode) {
    // Inform the user that the submitted code was incorrect or invalid, then ask them to input a new email one-time passcode
    val newCode = retrieveNewCode()
    nextState.submitCode(
        code = newCode
    )
}

Sono stati completati tutti i passaggi necessari per accedere correttamente a un utente nell'app. Compilare ed eseguire l'applicazione. Se tutto va bene, dovrebbe essere possibile fornire un messaggio di posta elettronica, ricevere un codice nel messaggio di posta elettronica e usarlo per accedere correttamente all'utente.

Leggere le attestazioni del token ID

Quando l'app ha acquisito un token ID, è possibile recuperare le attestazioni associate all'account corrente. A tale scopo, usare il frammento di codice seguente.

val preferredUsername = accountState.getClaims()?.get("preferred_username")
val city = accountState.getClaims()?.get("City")
val givenName = accountState.getClaims()?.get("given_name")
//custom attribute
val loyaltyNumber = accountState.getClaims()?.get("loyaltyNumber")

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

Per informazioni su come aggiungere attributi predefiniti e personalizzati a come attestazioni di token nell'articolo Aggiungere attributi utente alle attestazioni token.

Disconnessione di un utente

Per disconnettere un utente, è necessario rimuovere l'account attualmente archiviato nella cache.

  1. Creare l'interfaccia utente personalizzata che include:

    • Pulsante di disconnessione selezionato dall'utente per inviare una richiesta di disconnessione.
  2. Per disconnettere un utente, usare il codice seguente:

    private fun performSignOut(accountState: AccountState) {
         CoroutineScope(Dispatchers.Main).launch {
             val accountResult = authClient.getCurrentAccount()
             if (accountResult is GetAccountResult.AccountFound) {
                 val signOutResult = accountResult.resultValue.signOut()
                 if (signOutResult is SignOutResult.Complete) {
                     // Show sign out successful UI
                 }
             }
         }
     }
    

Gestire gli errori di disconnessura

Disconnettersi deve essere privo di errori. Se si verificano errori, esaminare il risultato dell'errore usando il frammento di codice seguente:

val actionResult = accountResult.signOut()
if (actionResult is SignOutResult.Complete) {
    // Show sign out successful UI
} else {
    // Handle errors
}

Assicurarsi di includere le istruzioni di importazione. Android Studio deve includere automaticamente le istruzioni di importazione.

Sono stati completati tutti i passaggi necessari per disconnettere correttamente 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.