搭配 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][PublicClientApplication] 層級設定此功能。 若要設定,請使用回撥:
// Requires MSAL.NET 4.2 or later
var pca = PublicClientApplicationBuilder
.Create("<your-client-id-here>")
.WithParentActivityOrWindow(() => parentActivity)
.Build();
如果您使用 CurrentActivityPlugin,則 [PublicClientApplication
][PublicClientApplication] 建立器程式代碼看起來應該類似下列代碼段:
// Requires MSAL.NET 4.2 or later
var pca = PublicClientApplicationBuilder
.Create("<your-client-id-here>")
.WithParentActivityOrWindow(() => CrossCurrentActivity.Current)
.Build();
確保該控制項傳回至 MSAL
當驗證流程的互動式部分結束時,覆寫 [Activity
][Activity].[OnActivityResult()
] 以將控制權傳回 MSAL[OnActivityResult] 方法。
在覆寫中,呼叫 MSAL.NET 的 AuthenticationContinuationHelper
。SetAuthenticationContinuationEventArgs()
方法,可在驗證流程的互動式部分結束時,將控制項傳回至 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>
下一步
若要嘗試其他範例,請參考行動公用用戶端應用程式。