Abilitare l'autenticazione nella propria app Android usando Azure AD B2C
Questo articolo illustra come aggiungere l'autenticazione di Azure Active Directory B2C (Azure AD B2C) alla propria applicazione per dispositivi mobili Android.
Usare questo articolo con Configurare l'autenticazione in un'app Android di esempio usando Azure AD B2C, sostituendo l'app Android di esempio con la propria app Android. 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 Android di esempio usando Azure AD B2C.
Creare un progetto di app Android
Se non si ha già un'applicazione Android, configurare un nuovo progetto eseguendo le operazioni seguenti:
- In Android Studio selezionare Start a new Android Studio project (Avvia un nuovo progetto Android Studio).
- Selezionare Attività di base e quindi avanti.
- Assegnare un nome all'applicazione.
- Salvare il nome del pacchetto. Verrà immesso più avanti nella portale di Azure.
- Modificare il linguaggio da Kotlin a Java.
- Impostare Il livello API minimo su API 19 o versione successiva e quindi selezionare Fine.
- Nella visualizzazione progetto scegliere Progetto nell'elenco a discesa per visualizzare i file di progetto di origine e non di origine, aprire app/build.gradle e quindi impostare targetSdkVersion su 28.
Passaggio 1: Installare le dipendenze
Nella finestra del progetto Android Studio passare ad app>build.gradle e quindi aggiungere quanto segue:
apply plugin: 'com.android.application'
allprojects {
repositories {
mavenCentral()
google()
mavenLocal()
maven {
url 'https://pkgs.dev.azure.com/MicrosoftDeviceSDK/DuoSDK-Public/_packaging/Duo-SDK-Feed/maven/v1'
}
maven {
name "vsts-maven-adal-android"
url "https://identitydivision.pkgs.visualstudio.com/_packaging/AndroidADAL/maven/v1"
credentials {
username System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_USERNAME") : project.findProperty("vstsUsername")
password System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") != null ? System.getenv("ENV_VSTS_MVN_ANDROIDADAL_ACCESSTOKEN") : project.findProperty("vstsMavenAccessToken")
}
}
jcenter()
}
}
dependencies{
implementation 'com.microsoft.identity.client:msal:2.+'
}
packagingOptions{
exclude("META-INF/jersey-module-version")
}
Passaggio 2: Aggiungere i componenti di autenticazione
Il codice di esempio è costituito dai componenti seguenti. Aggiungere questi componenti dall'app Android di esempio alla propria app.
Componente | Type | Origine | Descrizione |
---|---|---|---|
B2CUser | Classe | Java Kotlin | Rappresenta un utente B2C. Questa classe consente agli utenti di accedere con più criteri. |
B2CModeFragment | Classe Fragment | Java Kotlin | Un frammento rappresenta una parte modulare dell'accesso con l'interfaccia utente di Azure AD B2C all'interno dell'attività principale. Questo frammento contiene la maggior parte del codice di autenticazione. |
fragment_b2c_mode.xml | Layout frammento | Java Kotlin | Definisce la struttura per un'interfaccia utente per il componente frammento B2CModeFragment. |
B2CConfiguration | Classe | Java Kotlin | Un file di configurazione contiene informazioni sul provider di identità di Azure AD B2C. L'app per dispositivi mobili usa queste informazioni per stabilire una relazione di trust con Azure AD B2C, consentire l'accesso e l'uscita degli utenti, acquisire i token e convalidarli. Per altre impostazioni di configurazione, vedere il file auth_config_b2c.json. |
auth_config_b2c.json | File JSON | Java Kotlin | Un file di configurazione contiene informazioni sul provider di identità di Azure AD B2C. L'app per dispositivi mobili usa queste informazioni per stabilire una relazione di trust con Azure AD B2C, consentire l'accesso e l'uscita degli utenti, acquisire i token e convalidarli. Per altre impostazioni di configurazione, vedere la classe B2CConfiguration. |
Passaggio 3: Configurare l'app Android
Dopo aver aggiunto i componenti di autenticazione, configurare l'app Android con le impostazioni di Azure AD B2C. Le impostazioni del provider di identità di Azure AD B2C vengono configurate nella classe auth_config_b2c.json file e B2CConfiguration.
Per indicazioni, vedere Configurare l'app per dispositivi mobili di esempio.
Passaggio 4: Impostare l'URI di reindirizzamento
Configurare la posizione in cui l'applicazione è in ascolto della risposta del token di Azure AD B2C.
Generare un nuovo hash della firma di sviluppo. Ciò cambierà per ogni ambiente di sviluppo.
Per Windows:
keytool -exportcert -alias androiddebugkey -keystore %HOMEPATH%\.android\debug.keystore | openssl sha1 -binary | openssl base64
Per iOS:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
Per un ambiente di produzione, usare il comando seguente:
keytool -exportcert -alias SIGNATURE_ALIAS -keystore PATH_TO_KEYSTORE | openssl sha1 -binary | openssl base64
Per altre informazioni sulla firma delle app, vedi Firmare l'app Android.
Selezionare il AndroidManifest.xml principale>dell'app>src>e quindi aggiungere l'attività seguente
BrowserTabActivity
al corpo dell'applicazione:<!--Intent filter to capture System Browser or Authenticator calling back to our app after sign-in--> <activity android:name="com.microsoft.identity.client.BrowserTabActivity"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="msauth" android:host="Package_Name" android:path="/Signature_Hash" /> </intent-filter> </activity>
Sostituire
Signature_Hash
con l'hash generato.Sostituire
Package_Name
con il nome del pacchetto Android.
Per aggiornare la registrazione dell'app per dispositivi mobili con l'URI di reindirizzamento dell'app, eseguire le operazioni seguenti:
- Accedere al portale di Azure.
- Se si ha accesso a più tenant, selezionare l'icona Impostazioni nel menu in alto per passare al tenant di Azure AD B2C dal menu Directory e sottoscrizioni .
- Cerca e seleziona Azure AD B2C.
- Selezionare Registrazioni app e quindi selezionare l'applicazione registrata nel passaggio 2.3: Registrare l'app per dispositivi mobili.
- Seleziona Autenticazione.
- In Android selezionare Aggiungi URI.
- Immettere il nome del pacchetto e l'hash della firma.
- Seleziona Salva.
L'URI di reindirizzamento e l'attività BrowserTabActivity
dovrebbero essere simili all'esempio seguente:
L'URL di reindirizzamento per Android di esempio è simile al seguente:
msauth://com.azuresamples.msalandroidkotlinapp/1wIqXSqBj7w%2Bh11ZifsnqwgyKrY%3D
Il filtro finalità usa lo stesso modello, come illustrato nel frammento XML seguente:
<activity android:name="com.microsoft.identity.client.BrowserTabActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:host="com.azuresamples.msalandroidkotlinapp"
android:path="/1wIqXSqBj7w+h11ZifsnqwgyKrY="
android:scheme="msauth" />
</intent-filter>
</activity>
Passaggio 5: Personalizzare i blocchi predefiniti del codice
Questa sezione descrive i blocchi predefiniti del codice che abilitano l'autenticazione per l'app Android. La tabella seguente elenca i metodi B2CModeFragment e come personalizzare il codice.
Passaggio 5.1: Creare un'istanza di un'applicazione client pubblica
Le applicazioni client pubbliche non sono attendibili per mantenere i segreti dell'applicazione in modo sicuro e non hanno segreti client. In onCreate o onCreateView creare un'istanza di MSAL usando l'oggetto applicazione client pubblica con più account.
La MultipleAccountPublicClientApplication
classe viene usata per creare app basate su MSAL che consentono l'accesso contemporaneamente a più account. La classe consente l'accesso con più flussi utente di Azure AD B2C o criteri personalizzati. Ad esempio, gli utenti accedono con un flusso utente di iscrizione o di accesso e versioni successive eseguono un flusso utente del profilo di modifica.
Il frammento di codice seguente illustra come avviare la libreria MSAL con il auth_config_b2c.json
file JSON di configurazione.
PublicClientApplication.createMultipleAccountPublicClientApplication(context!!,
R.raw.auth_config_b2c,
object : IMultipleAccountApplicationCreatedListener {
override fun onCreated(application: IMultipleAccountPublicClientApplication) {
// Set the MultipleAccountPublicClientApplication to the class member b2cApp
b2cApp = application
// Load the account (if there is any)
loadAccounts()
}
override fun onError(exception: MsalException) {
// Error handling
displayError(exception)
}
})
Passaggio 5.2: Caricare gli account
Quando l'app si trova in primo piano, l'app carica l'account esistente per determinare se gli utenti hanno eseguito l'accesso. Usare questo metodo per aggiornare l'interfaccia utente con lo stato di autenticazione. Ad esempio, è possibile abilitare o disabilitare il pulsante di disconnessione.
Il frammento di codice seguente illustra come caricare gli account.
private fun loadAccounts() {
if (b2cApp == null) {
return
}
b2cApp!!.getAccounts(object : LoadAccountsCallback {
override fun onTaskCompleted(result: List<IAccount>) {
users = B2CUser.getB2CUsersFromAccountList(result)
updateUI(users)
}
override fun onError(exception: MsalException) {
displayError(exception)
}
})
}
Passaggio 5.3: Avviare una richiesta di autorizzazione interattiva
Una richiesta di autorizzazione interattiva è un flusso in cui agli utenti viene richiesto di iscriversi o eseguire l'accesso. Il initializeUI
metodo configura l'evento runUserFlowButton
click. Quando gli utenti selezionano il pulsante Esegui flusso utente, l'app li porta ad Azure AD B2C per completare il flusso di accesso.
Il runUserFlowButton.setOnClickListener
metodo prepara l'oggetto AcquireTokenParameters
con i dati pertinenti relativi alla richiesta di autorizzazione. Il acquireToken
metodo richiede quindi agli utenti di completare il flusso di iscrizione o di accesso.
Il frammento di codice seguente illustra come avviare la richiesta di autorizzazione interattiva:
val parameters = AcquireTokenParameters.Builder()
.startAuthorizationFromActivity(activity)
.fromAuthority(getAuthorityFromPolicyName(policy_list.getSelectedItem().toString()))
.withScopes(B2CConfiguration.scopes)
.withPrompt(Prompt.LOGIN)
.withCallback(authInteractiveCallback)
.build()
b2cApp!!.acquireToken(parameters)
Passaggio 5.4: Effettuare un callback interattivo della richiesta di autorizzazione
Dopo che gli utenti completano il flusso di autorizzazione, se correttamente o con esito negativo, il risultato viene restituito al getAuthInteractiveCallback()
metodo di callback.
Il metodo di callback passa l'oggetto AuthenticationResult
o un messaggio di errore nell'oggetto MsalException
. Usare questo metodo per:
- Aggiornare l'interfaccia utente dell'app per dispositivi mobili con le informazioni al termine dell'accesso.
- Ricaricare l'oggetto accounts.
- Chiamare un servizio API Web con un token di accesso.
- Gestire gli errori di autenticazione.
Il frammento di codice seguente illustra l'uso del callback di autenticazione interattiva.
private val authInteractiveCallback: AuthenticationCallback
private get() = object : AuthenticationCallback {
override fun onSuccess(authenticationResult: IAuthenticationResult) {
/* Successfully got a token, use it to call a protected resource; web API */
Log.d(TAG, "Successfully authenticated")
/* display result info */
displayResult(authenticationResult)
/* Reload account asynchronously to get the up-to-date list. */
loadAccounts()
}
override fun onError(exception: MsalException) {
val B2C_PASSWORD_CHANGE = "AADB2C90118"
if (exception.message!!.contains(B2C_PASSWORD_CHANGE)) {
txt_log!!.text = """
Users click the 'Forgot Password' link in a sign-up or sign-in user flow.
Your application needs to handle this error code by running a specific user flow that resets the password.
""".trimIndent()
return
}
/* Failed to acquireToken */Log.d(TAG, "Authentication failed: $exception")
displayError(exception)
if (exception is MsalClientException) {
/* Exception inside MSAL, more info inside MsalError.java */
} else if (exception is MsalServiceException) {
/* Exception when communicating with the STS, likely config issue */
}
}
override fun onCancel() {
/* User canceled the authentication */
Log.d(TAG, "User cancelled login.")
}
}
Passaggio 6: Chiamare un'API Web
Per chiamare un'API Web di autorizzazione basata su token, l'app deve avere un token di accesso valido. L'app esegue le operazioni seguenti:
- Acquisisce un token di accesso con le autorizzazioni necessarie (ambiti) per l'endpoint DELL'API Web.
- 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 accedono in modo interattivo, l'app ottiene un token di accesso nel getAuthInteractiveCallback
metodo di callback. Per le chiamate API Web consecutive, usare la procedura di acquisizione invisibile all'utente del token come descritto in questa sezione.
Prima di chiamare un'API Web, chiamare il metodo con gli ambiti appropriati per l'endpoint acquireTokenSilentAsync
dell'API Web. La libreria MSAL esegue le operazioni seguenti:
- Tenta di recuperare un token di accesso con gli ambiti richiesti dalla cache dei token. Se il token è presente, viene restituito il token.
- Se il token non è presente nella cache dei token, MSAL tenta di usare il token di aggiornamento per acquisire un nuovo token.
- Se il token di aggiornamento non esiste o è scaduto, viene restituita un'eccezione. È consigliabile richiedere all'utente di accedere in modo interattivo.
Il frammento di codice seguente illustra come acquisire un token di accesso:
L'evento acquireTokenSilentButton
click del pulsante acquisisce un token di accesso con gli ambiti specificati.
btn_acquireTokenSilently.setOnClickListener(View.OnClickListener {
if (b2cApp == null) {
return@OnClickListener
}
val selectedUser = users!![user_list.getSelectedItemPosition()]
selectedUser.acquireTokenSilentAsync(b2cApp!!,
policy_list.getSelectedItem().toString(),
B2CConfiguration.scopes,
authSilentCallback)
})
Il authSilentCallback
metodo di callback restituisce un token di accesso e chiama un'API Web:
private val authSilentCallback: SilentAuthenticationCallback
private get() = object : SilentAuthenticationCallback {
override fun onSuccess(authenticationResult: IAuthenticationResult) {
Log.d(TAG, "Successfully authenticated")
/* Call your web API here*/
callWebAPI(authenticationResult)
}
override fun onError(exception: MsalException) {
/* Failed to acquireToken */
Log.d(TAG, "Authentication failed: $exception")
displayError(exception)
if (exception is MsalClientException) {
/* Exception inside MSAL, more info inside MsalError.java */
} else if (exception is MsalServiceException) {
/* Exception when communicating with the STS, likely config issue */
} else if (exception is MsalUiRequiredException) {
/* Tokens expired or no session, retry with interactive */
}
}
}
L'esempio seguente illustra come chiamare un'API Web protetta con un token di connessione:
@Throws(java.lang.Exception::class)
private fun callWebAPI(authenticationResult: IAuthenticationResult) {
val accessToken = authenticationResult.accessToken
val thread = Thread {
try {
val url = URL("https://your-app-service.azurewebsites.net/helo")
val conn = url.openConnection() as HttpsURLConnection
conn.setRequestProperty("Accept", "application/json")
// Set the bearer token
conn.setRequestProperty("Authorization", "Bearer $accessToken")
if (conn.responseCode == HttpURLConnection.HTTP_OK) {
val br = BufferedReader(InputStreamReader(conn.inputStream))
var strCurrentLine: String?
while (br.readLine().also { strCurrentLine = it } != null) {
Log.d(TAG, strCurrentLine)
}
}
conn.disconnect()
} catch (e: IOException) {
e.printStackTrace()
} catch (e: Exception) {
e.printStackTrace()
}
}
thread.start()
}
Aggiungere l'autorizzazione per eseguire operazioni di rete
Per eseguire operazioni di rete nell'applicazione, aggiungere l'autorizzazione seguente al manifesto. Per altre informazioni, vedere Connettersi alla rete.
<uses-permission android:name="android.permission.INTERNET"/>
Passaggi successivi
Scopri come: