You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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不匹配,所以报错。
修复步骤:

  1. 提取Intune重签名后的APK的签名哈希:将Intune分发的APK下载到本地后,用命令keytool -list -printcert -jarfile 你的安装包路径.apk获取SHA1值,去掉SHA1值里的所有冒号,转成二进制后做URL安全的Base64编码。
  2. 把新的签名哈希对应的重定向URI(格式为msauth://<你的应用包名>/<URL编码后的Base64签名哈希>)添加到Azure AD应用注册的重定向URI列表中。
  3. 同步更新Android Manifest中msauth scheme对应intent-filter的path值、msal_default_config.json里的redirect_uri值、OAuthSettings类里的RedirectUri值,确保四处配置完全一致。
  4. 删除冗余的自定义MsalActivity类:你已经在Manifest里配置了BrowserTabActivity的intent-filter,重复声明MsalActivity可能会导致认证回调被拦截异常。

内容的提问来源于stack exchange,提问作者Ryan Wilson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 07:09:02