Requisiti di configurazione e suggerimenti per la risoluzione dei problemi per Xamarin Android con MSAL.NET

Quando si usa Xamarin Android con Microsoft Authentication Library per .NET (MSAL.NET) è necessario apportare diverse modifiche alla configurazione. Le sezioni seguenti descrivono le modifiche necessarie, seguite da una sezione Risoluzione dei problemi per evitare alcuni dei problemi più comuni.

Impostare l'attività padre

In Xamarin Android impostare l'attività padre in modo che il token venga restituito dopo l'interazione:

var authResult = AcquireTokenInteractive(scopes)
 .WithParentActivityOrWindow(parentActivity)
 .ExecuteAsync();

In MSAL.NET 4.2 e versioni successive è anche possibile impostare questa funzionalità a livello di PublicClientApplication. A tale scopo, usare un callback:

// Requires MSAL.NET 4.2 or later
var pca = PublicClientApplicationBuilder
  .Create("<your-client-id-here>")
  .WithParentActivityOrWindow(() => parentActivity)
  .Build();

Se si usa CurrentActivityPlugin, il PublicClientApplication codice del generatore dovrebbe essere simile al frammento di codice seguente:

// Requires MSAL.NET 4.2 or later
var pca = PublicClientApplicationBuilder
  .Create("<your-client-id-here>")
  .WithParentActivityOrWindow(() => CrossCurrentActivity.Current)
  .Build();

Assicurarsi che il controllo torni a MSAL

Quando termina la parte interattiva del flusso di autenticazione, restituire il controllo a MSAL eseguendo l'override di Activity.MetodoOnActivityResult() .

Nell'override chiamare MSAL. AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs() metodo per restituire il controllo a MSAL alla fine della parte interattiva del flusso di autenticazione.

protected override void OnActivityResult(int requestCode,
                                         Result resultCode,
                                         Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);

    // Return control to MSAL
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode,
                                                                            resultCode,
                                                                            data);
}

Aggiornare il manifesto Android per il supporto di System WebView

Per supportare System WebView, il file AndroidManifest.xml deve contenere i valori seguenti:

<activity android:name="microsoft.identity.client.BrowserTabActivity" android:configChanges="orientation|screenSize" android:exported="true">
  <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="msal{Client Id}" android:host="auth" />
  </intent-filter>
</activity>

Il android:scheme valore viene creato dall'URI di reindirizzamento configurato nel portale dell'applicazione. Ad esempio, se l'URI di reindirizzamento è msal00001111-aaaa-2222-bbbb-3333cccc4444://auth, la android:scheme voce nel manifesto sarà simile all'esempio seguente:

<data android:scheme="msal00001111-aaaa-2222-bbbb-3333cccc4444" android:host="auth" />

In alternativa, creare l'attività nel codice anziché modificare manualmente AndroidManifest.xml. Per creare l'attività nel codice, creare prima di tutto una classe che includa l'attributo Activity e l'attributo IntentFilter .

Di seguito è riportato un esempio di una classe che rappresenta i valori del file XML:

  [Activity(Exported = true)]
  [IntentFilter(new[] { Intent.ActionView },
        Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault },
        DataHost = "auth",
        DataScheme = "msal{client_id}")]
  public class MsalActivity : BrowserTabActivity
  {
  }

Usare System WebView nell'autenticazione negoziata

Per usare System WebView come fallback per l'autenticazione interattiva quando è stata configurata l'applicazione per l'uso dell'autenticazione negoziata e il dispositivo non dispone di un broker installato, abilitare MSAL per acquisire la risposta di autenticazione usando l'URI di reindirizzamento del broker. MSAL tenterà di eseguire l'autenticazione usando il WebView di sistema predefinito nel dispositivo quando rileva che il broker non è disponibile. L'uso di questa impostazione predefinita avrà esito negativo perché l'URI di reindirizzamento è configurato per l'uso di un broker e System WebView non sa come usarlo per tornare a MSAL. Per risolvere questo problema, creare un filtro finalità usando l'URI di reindirizzamento broker configurato in precedenza. Aggiungere il filtro finalità modificando il manifesto dell'applicazione come nell'esempio seguente:

<!--Intent filter to capture System WebView or Authenticator calling back to our app after sign-in-->
<activity
      android:name="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="Enter_the_Package_Name"
              android:path="/Enter_the_Signature_Hash" />
    </intent-filter>
</activity>

Sostituire il nome del pacchetto registrato nel portale di Azure per il android:host= valore . Sostituire l'hash della chiave registrato nel portale di Azure per il android:path= valore . L'hash della firma non deve essere codificato con URL. Assicurarsi che venga visualizzata una barra iniziale (/) all'inizio dell'hash della firma.

Manifesto Xamarin.Forms 4.3.x

Xamarin.Forms 4.3.x genera codice che imposta l'attributo package su com.companyname.{appName} in AndroidManifest.xml. Se si usa DataScheme come msal{client_id}, è possibile modificare il valore in modo che corrisponda al valore dello spazio dei MainActivity.cs nomi.

Supporto di Android 11

Per usare il browser di sistema e l'autenticazione negoziata in Android 11, devi prima dichiarare questi pacchetti, in modo che siano visibili all'app. Le app destinate ad Android 10 (API 29) e versioni precedenti possono eseguire query sul sistema operativo per un elenco di pacchetti disponibili nel dispositivo in qualsiasi momento. Per supportare la privacy e la sicurezza, Android 11 riduce la visibilità dei pacchetti del pacchetto a un elenco predefinito di pacchetti del sistema operativo e ai pacchetti specificati nel file AndroidManifest.xml dell'app.

Per consentire all'applicazione di eseguire l'autenticazione usando sia il browser di sistema che il broker, aggiungere la sezione seguente a AndroidManifest.xml:

<!-- Required for API Level 30 to make sure the app can detect browsers and other apps where communication is needed.-->
<!--https://developer.android.com/training/basics/intents/package-visibility-use-cases-->
<queries>
  <package android:name="com.azure.authenticator" />
  <package android:name="{Package Name}" />
  <package android:name="com.microsoft.windowsintune.companyportal" />
  <!-- Required for API Level 30 to make sure the app detect browsers
      (that don't support custom tabs) -->
  <intent>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="https" />
  </intent>
  <!-- Required for API Level 30 to make sure the app can detect browsers that support custom tabs -->
  <!-- https://developers.google.com/web/updates/2020/07/custom-tabs-android-11#detecting_browsers_that_support_custom_tabs -->
  <intent>
    <action android:name="android.support.customtabs.action.CustomTabsService" />
  </intent>
</queries>

Sostituire {Package Name} con il nome del pacchetto dell'applicazione.

Il manifesto aggiornato, che include ora il supporto per il browser di sistema e l'autenticazione negoziata, dovrebbe essere simile a questo esempio:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="com.companyname.XamarinDev">
    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <application android:theme="@android:style/Theme.NoTitleBar">
        <activity android:name="microsoft.identity.client.BrowserTabActivity" android:configChanges="orientation|screenSize">
            <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="msal00001111-aaaa-2222-bbbb-3333cccc4444" android:host="auth" />
            </intent-filter>
            <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="com.companyname.XamarinDev" android:path="/Fc4l/5I4mMvLnF+l+XopDuQ2gEM=" />
            </intent-filter>
        </activity>
    </application>
    <!-- Required for API Level 30 to make sure we can detect browsers and other apps we want to
     be able to talk to.-->
    <!--https://developer.android.com/training/basics/intents/package-visibility-use-cases-->
    <queries>
        <package android:name="com.azure.authenticator" />
        <package android:name="com.companyname.xamarindev" />
        <package android:name="com.microsoft.windowsintune.companyportal" />
        <!-- Required for API Level 30 to make sure we can detect browsers
        (that don't support custom tabs) -->
        <intent>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" />
        </intent>
        <!-- Required for API Level 30 to make sure we can detect browsers that support custom tabs -->
        <!-- https://developers.google.com/web/updates/2020/07/custom-tabs-android-11#detecting_browsers_that_support_custom_tabs -->
        <intent>
            <action android:name="android.support.customtabs.action.CustomTabsService" />
        </intent>
    </queries>
</manifest>

Usare la visualizzazione Web incorporata (facoltativo)

Per impostazione predefinita, MSAL.NET usa il Web browser di sistema. Questo browser consente di ottenere l'accesso Single Sign-On (SSO) usando applicazioni Web e altre app. In alcuni rari casi, è possibile che il sistema usi una visualizzazione Web incorporata.

Questo esempio di codice illustra come configurare una visualizzazione Web incorporata:

bool useEmbeddedWebView = !app.IsSystemWebViewAvailable;

var authResult = AcquireTokenInteractive(scopes)
 .WithParentActivityOrWindow(parentActivity)
 .WithEmbeddedWebView(useEmbeddedWebView)
 .ExecuteAsync();

Per altre informazioni, vedere Usare Web browser per MSAL.NET e considerazioni sul browser di sistema Xamarin Android.

Risoluzione dei problemi

Suggerimenti generali

  • Aggiornare il pacchetto NuGet MSAL.NET esistente alla versione più recente di MSAL.NET.
  • Verificare che Xamarin.Forms sia nella versione più recente.
  • Verificare che Xamarin.Android.Support.v4 sia nella versione più recente.
  • Verificare che tutti i pacchetti Xamarin.Android.Support siano destinati alla versione più recente.
  • Pulire o ricompilare l'applicazione.
  • In Visual Studio provare a impostare il numero massimo di compilazioni di progetti paralleli su 1. A tale scopo, selezionare Opzioni>Progetti e soluzioni>Compila ed esegui>numero massimo di compilazioni di progetti paralleli.
  • Se si esegue la compilazione dalla riga di comando e il comando usa /m, provare a rimuovere questo elemento dal comando .

Errore: il nome AuthenticationContinuationHelper non esiste nel contesto corrente

Se un errore indica che AuthenticationContinuationHelper non esiste nel contesto corrente, Visual Studio potrebbe aver aggiornato in modo non corretto il file Android.csproj* . In alcuni casi il percorso del file nell'elemento <HintPath> contiene netstandard13 erroneamente anziché monoandroid90.

Questo esempio contiene un percorso di file corretto:

<Reference Include="Microsoft.Identity.Client, Version=3.0.4.0, Culture=neutral, PublicKeyToken=0a613f4dd989e8ae,
           processorArchitecture=MSIL">
  <HintPath>..\..\packages\Microsoft.Identity.Client.3.0.4-preview\lib\monoandroid90\Microsoft.Identity.Client.dll</HintPath>
</Reference>

Passaggi successivi

Per altre informazioni, vedere l'esempio di un'applicazione per dispositivi mobili Xamarin che usa Microsoft Identity Platform. Nella tabella seguente vengono riepilogate le informazioni pertinenti nel file README.

Esempio Piattaforma Descrizione
https://github.com/Azure-Samples/active-directory-xamarin-native-v2 Xamarin.iOS, Android, UWP Applicazione per dispositivi mobili Xamarin che illustra come usare MSAL.NET per autenticare gli account aziendali o dell'istituto di istruzione e microsoft personali con Microsoft Identity Platform e accedere all'API Microsoft Graph con il token risultante.
Diagramma del flusso di autenticazione