共用方式為


搭配 MSAL.NET 的 Xamarin Android 設定需求和疑難排解秘訣

搭配適用於 .NET 的 Microsoft 驗證程式庫 (MSAL.NET) 使用 Xamarin Android 時,您必須在程式碼中變更幾項設定。 下列各節會說明必要的修改,接著疑難排解一節可協助您避免一些最常見的問題。

注意

MSAL.NET 4.61.0 版和更新版本不支援通用 Windows 平台 (UWP)、Xamarin Android 和 Xamarin iOS。 建議您將 Xamarin 應用程式遷移至 MAUI 等新式架構。 深入瞭解 宣佈即將淘汰適用於 Xamarin 和 UWP 的 MSAL.NET 中的淘汰事件。

設定父代活動

在 Xamarin Android 上,設定父代活動,讓權杖在互動後傳回:

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

在 MSAL.NET 4.2 和更新版本中,您也可以在 PublicClientApplication 層級設定這項功能。 若要設定,請使用回撥:

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

如果您使用 CurrentActivityPluginPublicClientApplication 建立器程式碼看起來應該類似以下程式碼片段:

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

確保該控制項傳回至 MSAL

驗證流程的互動式部分結束時,覆寫 Activity,將控制項傳回至 MSAL。OnActivityResult() 方法。

在覆寫中,呼叫 MSAL.NET 的 AuthenticationContinuationHelperSetAuthenticationContinuationEventArgs() 方法,可在驗證流程的互動式部分結束時,將控制項傳回至 MSAL。

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

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

更新 Android 資訊清單以支援 System WebView

若要支援 System WebView,AndroidManifest.xml 檔案應包含下列值:

<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>

android:scheme 值是以在應用程式入口網站中設定的重新導向 URI 建立。 舉例來說,如果您的重新導向 URI 為 msal00001111-aaaa-2222-bbbb-3333cccc4444://auth,資訊清單中的 android:scheme 項目看起來會像以下範例:

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

或者,以程式碼建立活動,而非手動編輯 AndroidManifest.xml。 若要以程式碼建立活動,請先建立包含 Activity 屬性和 IntentFilter 屬性的類別。

以下是代表 XML 檔案值的類別範例:

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

在代理驗證中使用 System WebView

若要在已將應用程式設定為使用代理驗證,且裝置未安裝訊息代理程式時,將 System WebView 當作互動式驗證的後援,請啟用 MSAL,使用資訊代理程式的重新導向 URI,擷取驗證回應。 MSAL 會在偵測到無法使用訊息代理程式時,嘗試使用裝置上的預設 System WebView 進行驗證。 使用此預設值會失敗,因為重新導向 URI 設定為使用訊息代理程式,而 System WebView 不知道如何使用訊息代理程式傳回至 MSAL。 若要解決此問題,請使用您先前設定的訊息代理程式重新導向 URI,建立「意圖篩選條件」。 修改應用程式的資訊清單,新增意圖篩選條件,如以下範例所示:

<!--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>

android:host= 值取代為您在 Azure 入口網站中註冊的封裝名稱。 將 android:path= 值取代為您在 Azure 入口網站中註冊的索引鍵雜湊。 簽章雜湊不應以 URL 編碼。 確保前置斜線 (/) 顯示於簽章雜湊的開頭。

Xamarin.Forms 4.3.x 資訊清單

Xamarin.Forms 4.3. x 會產生程式碼,在 AndroidManifest.xml 中將 package 屬性設為 com.companyname.{appName}。 如果您將 DataScheme 當作 msal{client_id},可能會想要將值變更為符合 MainActivity.cs 命名空間的值。

Android 11 支援

若要在 Android 11 中使用系統瀏覽器和代理驗證,您必須先宣告這些封裝,讓應用程式可瀏覽。 針對 Android 10 (API 29) 和舊版的應用程式,可以查詢作業系統,取得隨時可在裝置上使用的封裝清單。 為了支援隱私權和安全性,Android 11 將封裝可瀏覽範圍縮減為預設作業系統封裝清單,以及應用程式的 AndroidManifest.xml 檔案中指定的封裝。

若要讓應用程式使用系統瀏覽器和訊息代理程式進行驗證,請將以下區段新增至 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>

以應用程式封裝名稱取代 {Package Name}

您更新的資訊清單現在支援系統瀏覽器和代理驗證,看起來應類似以下範例:

<?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>

使用內嵌 Web 檢視 (選用)

MSAL.NET 預設會使用系統網頁瀏覽器。 此瀏覽器可讓您使用 Web 應用程式和其他應用程式,進行單一登入 (SSO)。 在極少數情況下,您可能會想要讓系統使用內嵌 Web 檢視。

以下程式碼範例會說明如何設定內嵌 Web 檢視:

bool useEmbeddedWebView = !app.IsSystemWebViewAvailable;

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

如需詳細資訊,請參閱為 MSAL.NET 使用網頁瀏覽器 (機器翻譯)Xamarin Android 系統瀏覽器考量 (機器翻譯)

疑難排解

一般提示

  • 將現有 MSAL.NET NuGet 封裝更新為最新版本 MSAL.NET
  • 確認 Xamarin.Forms 為最新版本。
  • 確認 Xamarin.Android.Support.v4 為最新版本。
  • 確保所有 Xamarin.Android.Support 封裝都針對最新版本。
  • 清除或重建應用程式。
  • 在 Visual Studio 中,請嘗試將平行專案組建的最大數目設定為 1。 若要設定,請選取 [選項]>[專案與解決方案]>[建置並執行]>[平行專案組建的最大數目]
  • 如果您是在命令列建置,且您的命令使用 /m,請嘗試從命令中移除此元素。

錯誤:名稱 AuthenticationContinuationHelper 不存在目前的內容中

如果錯誤指出 AuthenticationContinuationHelper 不存在目前的內容中,Visual Studio 可能會不正確更新 Android.csproj* 檔案。 有時 <HintPath> 元素中的檔案路徑會不正確包含 netstandard13,而非 monoandroid90

以下範例包含正確檔案路徑:

<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>

下一步

如需詳細資訊,請參閱使用 Microsoft 身分識別平台的 Xamarin 行動應用程式 (英文) 範例。 下表摘要讀我檔案中的相關資訊。

範例 平台 描述
https://github.com/Azure-Samples/active-directory-xamarin-native-v2 Xamarin.iOS、Android、UWP Xamarin 行動應用程式,示範如何使用 MSAL.NET,以 Microsoft身分識別平台驗證公司或學校和 Microsoft 個人帳戶,並使用產生的權杖存取 Microsoft 圖形 API。
驗證流程圖表