在 Xamarin 應用程式上使用 Microsoft Authenticator 或 Intune 公司入口網站
在 Android 和 iOS 上,Microsoft Authenticator 和 Android 專屬的 Microsoft Intune 公司入口網站等訊息代理程式可啟用:
- 單一登入 (SSO):使用者不必登入每個應用程式。
- 裝置識別:訊息代理程式會存取裝置憑證。 當此憑證加入工作場所時,會在裝置上加以建立。
- 應用程式識別驗證:當應用程式呼叫訊息代理程式時,會傳遞其重新導向 URL。 訊息代理程式會驗證 URL。
若要啟用上述其中一項功能,請在呼叫 PublicClientApplicationBuilder.CreateApplication
方法時使用 WithBroker()
參數。 .WithBroker()
參數預設設定為 True。
在適用於 .NET 的 Microsoft 驗證程式庫 (MSAL.NET) 中,代理驗證的設定方式會隨平台而異:
注意
MSAL.NET 版本 4.61.0 和更新版本不支援通用 Windows 平台 (UWP)、Xamarin Android 和 Xamarin iOS。 建議您將 Xamarin 應用程式移轉至 MAUI 等新式架構。 深入瞭解 宣佈即將淘汰適用於 Xamarin 和 UWP 的 MSAL.NET 中的淘汰事件。
iOS 的代理驗證
使用下列步驟,讓 Xamarin iOS 應用程式可與 Microsoft Authenticator 應用程式通訊。 如果您鎖定使用 iOS 13,請考慮閱讀 Apple 的重大 API 變更。
步驟 1:啟用訊息代理程式支援
您必須為 PublicClientApplication
的個別執行個體啟用訊息代理程式支援。 系統預設會停用這項支援。 當您透過 PublicClientApplicationBuilder
建立 PublicClientApplication
時,請使用 WithBroker()
參數,如下列範例所示。 WithBroker()
參數預設設定為 True。
var app = PublicClientApplicationBuilder
.Create(ClientId)
.WithBroker()
.WithReplyUri(redirectUriOnIos) // $"msauth.{Bundle.Id}://auth" (see step 6 below)
.Build();
步驟 2:啟用鑰匙圈存取
若要啟用鑰匙圈存取,您的應用程式必須有鑰匙圈存取群組。 在建立應用程式時,可使用 WithIosKeychainSecurityGroup()
API 來設定鑰匙圈存取群組:
var builder = PublicClientApplicationBuilder
.Create(ClientId)
.WithIosKeychainSecurityGroup("com.microsoft.adalcache")
.Build();
如需詳細資訊,請參閱啟用鑰匙圈存取。
步驟 3:更新 AppDelegate 以處理回呼
當 MSAL.NET 呼叫訊息代理程式時,訊息代理程式會透過 AppDelegate
類別的 OpenUrl
方法,回頭呼叫您的應用程式。 因為 MSAL 會等候訊息代理程式的回應,所以應用程式必須合作來回頭呼叫 MSAL.NET。 若要啟用這項合作,請更新 AppDelegate.cs 檔案以覆寫下列方法。
public override bool OpenUrl(UIApplication app, NSUrl url,
string sourceApplication,
NSObject annotation)
{
if (AuthenticationContinuationHelper.IsBrokerResponse(sourceApplication))
{
AuthenticationContinuationHelper.SetBrokerContinuationEventArgs(url);
return true;
}
else if (!AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url))
{
return false;
}
return true;
}
每次啟動應用程式時,就會叫用這個方法。 趁此機會,便可處理來自訊息代理程式的回應,並完成 MSAL.NET 所啟動的驗證程序。
步驟 4:設定 UIViewController()
仍是在 AppDelegate.cs 檔案中,請設定物件視窗。 通常不需要為 Xamarin iOS 設定物件視窗,但要有物件視窗才能在訊息代理程式中傳送和接收回應。
若要設定物件視窗:
在 AppDelegate.cs 檔案中,將
App.RootViewController
設定為新的UIViewController()
。 如此指派可確保對訊息代理程式的呼叫包含UIViewController
。 如果未正確指派此設定,您可能會收到此錯誤:"uiviewcontroller_required_for_ios_broker":"UIViewController is null, so MSAL.NET cannot invoke the iOS broker. See https://aka.ms/msal-net-ios-broker"
在
AcquireTokenInteractive
呼叫上使用.WithParentActivityOrWindow(App.RootViewController)
,然後傳入欲使用物件視窗的參考。在 App.cs 中:
public static object RootViewController { get; set; }
在 AppDelegate.cs 中:
LoadApplication(new App()); App.RootViewController = new UIViewController();
在
AcquireToken
呼叫中:result = await app.AcquireTokenInteractive(scopes) .WithParentActivityOrWindow(App.RootViewController) .ExecuteAsync();
步驟 5︰註冊 URL 配置
MSAL.NET 使用 URL 叫用訊息代理程式,然後將訊息代理程式回應傳回給應用程式。 若要完成來回行程,請在 Info.plist 檔案中為應用程式註冊 URL 配置。
CFBundleURLSchemes
名稱必須納入 msauth.
來作為前置詞。 在前置詞後面加上 CFBundleURLName
。
在 URL 配置中,BundleId
會唯一識別應用程式:$"msauth.(BundleId)"
。 因此,如果 BundleId
是 com.yourcompany.xforms
,則 URL 配置是 msauth.com.yourcompany.xforms
。
注意
此 URL 配置會成為重新導向 URI 的一部分,並可在收到來自訊息代理程式的回應時,唯一識別您的應用程式。
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLName</key>
<string>com.yourcompany.xforms</string>
<key>CFBundleURLSchemes</key>
<array>
<string>msauth.com.yourcompany.xforms</string>
</array>
</dict>
</array>
步驟 6:將訊息代理程式識別碼新增至 LSApplicationQueriesSchemes 區段
MSAL 會使用 –canOpenURL:
檢查裝置上是否已安裝訊息代理程式。 在 iOS 9 中,Apple 會鎖定應用程式可以查詢的配置。
將 msauthv2
新增至 Info.plist 檔案的 LSApplicationQueriesSchemes
區段,如下列範例所示:
<key>LSApplicationQueriesSchemes</key>
<array>
<string>msauthv2</string>
<string>msauthv3</string>
</array>
步驟 7:將重新導向 URI 新增至應用程式註冊
提示
本文中的步驟可能會依據您開始的入口網站而稍有不同。
在使用訊息代理程式時,重新導向 URI 會有額外需求。 重新導向 URI 的格式必須如下:
$"msauth.{BundleId}://auth"
以下是範例:
public static string redirectUriOnIos = "msauth.com.yourcompany.XForms://auth";
請注意,重新導向 URI 會符合您在 Info.plist 檔案中所包含的 CFBundleURLSchemes
名稱。
將重新導向 URI 新增至應用程式的註冊。 若要產生格式正確的重新導向 URI,請使用 應用程式註冊 從套件組合識別碼產生代理重新導向 URI。
若要產生重新導向 URI:
以至少 雲端應用程式系統管理員 的身分登入 Microsoft Entra 系統管理中心。
瀏覽至 [身分識別] > [應用程式] > [應用程式註冊]。
搜尋並選取應用程式。
選取 [驗證]>[新增平台]>[iOS/macOS]
輸入您的套件組合識別碼,然後選取 [設定]。
複製所產生並出現在 [重新導向 URI] 文字方塊中的重新導向 URI,以供納入到程式碼中:
選取 [完成] 以完成重新導向 URI 的產生作業。
Android 的代理驗證
步驟 1:啟用訊息代理程式支援
訊息代理程式支援會以每一 PublicClientApplication
為基礎來啟用。 此項目預設為停用。 在透過 PublicClientApplicationBuilder
建立 IPublicClientApplication
時,請使用 WithBroker()
參數 (預設會設定為 true)。
var app = PublicClientApplicationBuilder
.Create(ClientId)
.WithBroker()
.WithRedirectUri(redirectUriOnAndroid) // See step #4
.Build();
步驟 2:更新主要活動以處理回呼
當 MSAL.NET 呼叫訊息代理程式時,訊息代理程式會接著使用 OnActivityResult()
方法回頭呼叫應用程式。 由於 MSAL 會等候來自訊息代理程式的回應,因此應用程式需要將結果路由至 MSAL.NET。
請藉由覆寫 OnActivityResult()
方法,將結果路由至 SetAuthenticationContinuationEventArgs(int requestCode, Result resultCode, Intent data)
方法,如下所示:
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}
每次訊息代理程式應用程式啟動時,就會叫用這個方法,並趁此機會處理來自訊息代理程式的回應,以及完成 MSAL.NET 所啟動的驗證程序。
步驟 3:設定活動
若要啟用代理驗證,請設定活動讓 MSAL 可以在訊息代理程式中傳送和接收回應。 若要這樣做,請將活動 (通常是 MainActivity
) 提供給 WithParentActivityOrWindow(object parent)
父物件。
例如,在 AcquireTokenInteractive()
的呼叫中:
result = await app.AcquireTokenInteractive(scopes)
.WithParentActivityOrWindow((Activity)context))
.ExecuteAsync();
步驟 4:將重新導向 URI 新增至應用程式註冊
MSAL 會使用 URL 來叫用訊息代理程式,然後返回應用程式。 若要完成該來回行程,請為您的應用程式註冊 重新導向 URI。
應用程式的重新導向 URI 格式取決於用來簽署 APK 的憑證。 例如:
msauth://com.microsoft.xforms.testApp/hgbUYHVBYUTvuvT&Y6tr554365466=
URI 的最後一個部分 hgbUYHVBYUTvuvT&Y6tr554365466=
是用來簽署 APK 的 Base64 編碼版簽章。 在 Visual Studio 中開發應用程式時,如果您要在不使用特定憑證來簽署 APK 的情況下,對程式碼進行偵錯,Visual Studio 會為您簽署該 APK 以供您進行偵錯。 當 Visual Studio 以此方式為您簽署 APK 時,其會為 APK 建置所在的機器提供唯一的簽章。 因此,每次您在不同的機器上建置應用程式時,都必須更新應用程式程式碼中的重新導向 URI 和應用程式的註冊,才能向 MSAL 進行驗證。
在進行偵錯時,您可能會遇到 MSAL 例外狀況 (或記錄訊息),內容指出所提供的重新導向 URI 不正確。 例外狀況或記錄訊息也會指出您應該搭配目前要進行偵錯的機器來使用的重新導向 URI。 只要您在程式碼中更新重新導向 URI,並將提供的重新導向 URI 新增至應用程式的註冊,您就可以使用所提供的重新導向 URI 繼續開發您的應用程式。
準備好完成程式碼之後,請更新程式碼中的重新導向 URI,以及應用程式的註冊,以使用您用來簽署 APK 的憑證簽章。
實際上,這表示您應該考慮為開發小組的每個成員新增重新導向 URI,以及為 APK 的生產簽署版本新增重新導向 URI。
您可以自行計算簽章,方法與 MSAL 的做法類似:
private string GetRedirectUriForBroker()
{
string packageName = Application.Context.PackageName;
string signatureDigest = this.GetCurrentSignatureForPackage(packageName);
if (!string.IsNullOrEmpty(signatureDigest))
{
return string.Format(CultureInfo.InvariantCulture, "{0}://{1}/{2}", RedirectUriScheme,
packageName.ToLowerInvariant(), signatureDigest);
}
return string.Empty;
}
private string GetCurrentSignatureForPackage(string packageName)
{
Android.Content.PM.Signature signature = null;
if (Build.VERSION.SdkInt >= BuildVersionCodes.Tiramisu)
{
var packageInfo = Application.Context.PackageManager.GetPackageInfo(packageName, PackageManager.PackageInfoFlags.Of((long)PackageInfoFlags.SigningCertificates));
if (packageInfo.SigningInfo != null)
{
var signatures = packageInfo.SigningInfo.GetApkContentsSigners();
if (signatures != null && signatures.Length > 0)
signature = signatures[0];
}
}
else
{
#pragma warning disable CS0618 // Type or member is obsolete
var packageInfo = Application.Context.PackageManager.GetPackageInfo(packageName, PackageInfoFlags.Signatures);
if (packageInfo != null && packageInfo.Signatures != null && packageInfo.Signatures.Count > 0)
signature = packageInfo.Signatures[0];
#pragma warning restore CS0618 // Type or member is obsolete
}
if (signature != null)
{
// First available signature. Applications can be signed with multiple signatures.
// The order of Signatures is not guaranteed.
var md = MessageDigest.GetInstance("SHA");
md.Update(signature.ToByteArray());
return Convert.ToBase64String(md.Digest(), Base64FormattingOptions.None);
// Server side needs to register all other tags. ADAL will
// send one of them.
}
}
您也可以選擇使用 keytool 並搭配下列命令來取得套件的簽章:
- Windows:
keytool.exe -list -v -keystore "%LocalAppData%\Xamarin\Mono for Android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
- macOS:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
步驟 5 (選用):回復為系統瀏覽器
如果將 MSAL 設定為使用訊息代理程式,卻未安裝訊息代理程式,MSAL 便會回復為使用 Web 檢視 (瀏覽器)。 MSAL 會嘗試使用裝置上的預設系統瀏覽器進行驗證,但最終會失敗,原因是重新導向 URI 是針對訊息代理程式所設定的,但系統瀏覽器不知道如何用它來瀏覽回到 MSAL。 若要避免失敗,您可以使用步驟 4 中所用的訊息代理程式重新導向 URI 來設定意圖篩選條件。
修改應用程式的資訊清單以新增意圖篩選條件:
<!-- NOTE the SLASH (required) that prefixes the signature value in the path attribute.
The signature value is the Base64-encoded signature discussed above. -->
<intent-filter>
<data android:scheme="msauth"
android:host="Package Name"
android:path="/Package Signature"/>
例如,如果您的重新導向 URI 是 msauth://com.microsoft.xforms.testApp/hgbUYHVBYUTvuvT&Y6tr554365466=
,則資訊清單看起來應該會類似下列 XML 程式碼片段。
android:path
值中的簽章前面必須有正斜線 (/
)。
<!-- NOTE the SLASH (required) that prefixes the signature value in the path attribute.
The signature value is the Base64-encoded signature discussed above. -->
<intent-filter>
<data android:scheme="msauth"
android:host="com.microsoft.xforms.testApp"
android:path="/hgbUYHVBYUTvuvT&Y6tr554365466="/>
如需如何設定應用程式來支援系統瀏覽器和 Android 11 的詳細資訊,請參閱更新 Android 資訊清單以支援系統瀏覽器。
或者,您也可以將 MSAL 設定為回復到內嵌瀏覽器,便能不依賴重新導向 URI 了:
.WithUseEmbeddedWebUi(true)
Android 代理驗證的疑難排解秘訣
以下是在 Android 上實作代理驗證時如何避免問題的一些秘訣:
重新導向 URI - 將重新導向 URI 新增至您的應用程式註冊。 重新導向 URI 遺失或不正確是開發人員常會遇到的問題。
訊息代理程式版本 - 安裝訊息代理程式應用程式的最小必要版本。 以下兩個應用程式中的任一個都可用於在 Android 上進行代理驗證。
- Intune 公司入口網站 (5.0.4689.0 版或更新版本)
- Microsoft Authenticator (6.2001.0140 版或更新版本)。
訊息代理程式優先順序 - 如果安裝了多個訊息代理程式,MSAL 會與裝置上所安裝的第一個訊息代理程式通訊。
範例:如果您先安裝 Microsoft Authenticator 再安裝 Intune 公司入口網站,則只會在 Microsoft Authenticator 上進行代理驗證。
記錄 - 如果您遇到代理驗證問題,則檢視訊息代理程式的記錄可能有助於診斷原因。
取得 Microsoft Authenticator 記錄:
- 選取應用程式右上角的 [功能表] 按鈕。
- 選取 [傳送意見反應]>[遇到問題嗎?]。
- 在 [您嘗試執行的作業是什麼?] 底下,選取某個選項並新增描述。
- 若要傳送記錄,請選取應用程式右上角的箭號。
傳送記錄之後,對話方塊會顯示事件識別碼。 記下事件識別碼,並在要求協助時納入。
取得 Intune 公司入口網站記錄:
- 選取應用程式左上角的 [功能表] 按鈕。
- 選取 [說明]>[電子郵件支援]。
- 若要傳送記錄,請選取 [僅上傳記錄]。
傳送記錄之後,對話方塊會顯示事件識別碼。 記下事件識別碼,並在要求協助時納入。