Xamarin Forms Android通过Intune部署后MSAL库认证失败问题咨询
开发信息
- 技术栈:Xamarin Forms移动应用,基于Visual Studio 2019、C#、.NET 5开发
- 认证方案:使用MSAL 4.35.0版本对接Azure AD实现身份认证,采用Microsoft Authenticator代理认证流
问题现象
所有功能在Android模拟器运行正常,通过Intune Company Portal部署到真机后认证环节失败,报错如下:
认证错误 [Android broker] 代理重定向URI不正确,应为msauth://com.xxxxxx.xxxxxxx/xxxxxxxxxxxxxx,访问相关文档可获取更多详情
已核对Azure门户配置的重定向URI和报错提示的URI不匹配,代码库所有位置都用的是Azure门户指定的回调URI,不清楚报错的URI从哪里读取。已查阅官方文档、下载GitHub示例项目、修改Android Manifest文件均未解决,无排查思路。
相关代码与配置
核心认证代码
public static IPublicClientApplication PCA; // OAuthSettings类存储传入PublicClientApplicationBuilder的参数值 var builder = PublicClientApplicationBuilder .Create(OAuthSettings.ApplicationId) .WithTenantId(OAuthSettings.TenantId) .WithBroker() .WithRedirectUri(OAuthSettings.RedirectUri); PCA = builder.Build(); try { var accounts = await PCA.GetAccountsAsync(); var silentAuthResult = await PCA .AcquireTokenSilent(new string[] { "api://xxxxxxxxxxxxxx/.default" }, accounts.FirstOrDefault()) .ExecuteAsync(); AccessToken = new JwtSecurityToken(silentAuthResult.AccessToken); // 其余代码省略 } catch (MsalUiRequiredException msalEx) { var windowLocatorService = DependencyService.Get<IParentWindowLocatorService>(); // 触发用户登录 var interactiveRequest = PCA.AcquireTokenInteractive(new string[] { "api://xxxxxxxxxxxxxxxxxxx/.default" }); // Android/iOS通用逻辑 AuthUIParent = windowLocatorService?.GetCurrentParentWindow(); if (AuthUIParent != null) { interactiveRequest = interactiveRequest .WithParentActivityOrWindow(AuthUIParent); } // var interactiveAuthResult = await interactiveRequest.ExecuteAsync(); AccessToken = new JwtSecurityToken(interactiveAuthResult.AccessToken); }
Android Manifest配置
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="1.0" package="com.gpdgroup.GPDMobileAppTest" android:installLocation="auto" android:versionCode="7"> <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <application android:label="mycompany.Android" android:theme="@style/MainTheme" android:usesCleartextTraffic="true" android:icon="@mipmap/icon" android:roundIcon="@mipmap/icon"> <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="msal{clientID}" 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.mycompany.myapp" android:path="/{base64 hash}" /> </intent-filter> </activity> </application> <!-- 修复Android 30版本认证问题所需配置 --> <queries> <package android:name="com.azure.authenticator" /> <package android:name="com.mycompany.myapp" /> <package android:name="com.microsoft.windowsintune.companyportal" /> <!-- API 30版本需要配置确保应用能检测到不支持自定义标签页的浏览器 --> <intent> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="https" /> </intent> <!-- API 30版本需要配置确保应用能检测到支持自定义标签页的浏览器 --> <intent> <action android:name="android.support.customtabs.action.CustomTabsService" /> </intent> </queries> </manifest>
Azure门户配置

MSAL配置文件
Android项目Resources/raw目录下的msal_default_config.json配置:
{ "client_id": "xxxxxxxxxxxxxxxxxxxxx", "redirect_uri": "msauth://com.mycompany.myapp/{base64 url encoded signature hash}", "broker_redirect_uri_registered": true, "account_mode" : "SINGLE", "authorities": [ { "type": "AAD", "audience": { "type": "AzureADandPersonalMicrosoftAccount", "tenant_id": "xxxxxxxxxxxxxxxxxx" } } ] }
MsalActivity自定义类
[Activity] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault }, DataHost = "auth", DataScheme = "msal{clientID}")] public class MsalActivity : BrowserTabActivity { }
解决方案
问题核心原因是Intune部署时会对APK做重签名,你本地开发用的签名哈希和Intune重签名后的签名哈希不一致,MSAL运行时会自动读取当前APK的签名哈希生成重定向URI,和你Azure门户配置的本地签名哈希对应的URI不匹配,所以报错。
修复步骤:
- 提取Intune重签名后的APK的签名哈希:将Intune分发的APK下载到本地后,用命令
keytool -list -printcert -jarfile 你的安装包路径.apk获取SHA1值,去掉SHA1值里的所有冒号,转成二进制后做URL安全的Base64编码。 - 把新的签名哈希对应的重定向URI(格式为
msauth://<你的应用包名>/<URL编码后的Base64签名哈希>)添加到Azure AD应用注册的重定向URI列表中。 - 同步更新Android Manifest中msauth scheme对应intent-filter的path值、msal_default_config.json里的redirect_uri值、OAuthSettings类里的RedirectUri值,确保四处配置完全一致。
- 删除冗余的自定义MsalActivity类:你已经在Manifest里配置了BrowserTabActivity的intent-filter,重复声明MsalActivity可能会导致认证回调被拦截异常。
内容的提问来源于stack exchange,提问作者Ryan Wilson
相关产品推荐
相关产品推荐

