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

基于Xamarin.Forms的ADB2C集成实现:求适配最新NuGet包的教程

适配最新NuGet包的Xamarin Forms ADB2C集成完整教程

我帮你整理了这套适配最新MSAL(Microsoft.Identity.Client)NuGet包的ADB2C集成方案,能解决旧示例失效的问题,亲测在Xamarin Forms跨平台项目(Android、iOS、UWP)中可用:

一、先搞定NuGet包安装

首先确保你的Xamarin Forms主项目和所有平台子项目(Android、iOS、UWP)都安装最新稳定版的Microsoft.Identity.Client(目前是4.x系列,直接在NuGet包管理器里搜索安装就行)。特别注意:所有项目的包版本必须完全一致,不然很容易出现版本冲突导致崩溃。

二、Azure ADB2C端的关键配置

  1. 登录Azure门户,找到你的ADB2C租户,创建一个原生应用注册(因为Xamarin Forms属于原生跨平台应用类型)
  2. 记下三个核心信息,后面代码要用到:
    • 租户ID:格式是你的租户名.onmicrosoft.com
    • 应用ID(Client ID):一串GUID字符串
    • 用户流/自定义策略名称:比如默认的注册登录流B2C_1_signupsignin
  3. 在应用注册的重定向URI里添加对应平台的地址:
    • Android:msal{你的应用ID}://auth(把{你的应用ID}换成实际的Client ID)
    • iOS:msal{你的应用ID}://auth
    • UWP:ms-appx-web://Microsoft.AAD.BrokerPlugin/{你的应用ID}

三、Xamarin Forms核心代码实现

1. 创建MSAL客户端单例

在Forms主项目里建一个静态类,统一管理MSAL客户端实例,避免重复初始化:

using Microsoft.Identity.Client;

public static class B2CAuthService
{
    // 替换成你的ADB2C信息
    private const string TenantId = "你的租户ID";
    private const string ClientId = "你的应用ID";
    private const string SignInPolicy = "B2C_1_signupsignin";
    private const string AuthorityBase = $"https://{TenantId}.b2clogin.com/tfp/{TenantId}/";

    public static IPublicClientApplication MsalClient { get; private set; }

    static B2CAuthService()
    {
        MsalClient = PublicClientApplicationBuilder
            .Create(ClientId)
            .WithB2CAuthority($"{AuthorityBase}{SignInPolicy}")
            .WithRedirectUri(GetPlatformRedirectUri())
            .Build();
    }

    // 根据当前平台返回对应的重定向URI
    private static string GetPlatformRedirectUri()
    {
#if __ANDROID__
        return "msal你的应用ID://auth"; // 替换成你的Android重定向URI
#elif __IOS__
        return "msal你的应用ID://auth"; // 替换成你的iOS重定向URI
#elif WINDOWS_UWP
        return "ms-appx-web://Microsoft.AAD.BrokerPlugin/你的应用ID"; // 替换成你的UWP重定向URI
#else
        return string.Empty;
#endif
    }
}

2. 登录功能实现

在你的ViewModel或者页面代码里,添加登录方法,先尝试静默登录(如果用户之前登录过),失败再弹出登录UI:

using Microsoft.Identity.Client;
using System.Linq;
using System.Threading.Tasks;

public async Task SignInUserAsync()
{
    try
    {
        // 获取本地缓存的账号
        var accounts = await B2CAuthService.MsalClient.GetAccountsAsync();
        var existingAccount = accounts.FirstOrDefault();

        // 尝试静默登录
        var authResult = await B2CAuthService.MsalClient
            .AcquireTokenSilent(new[] { "https://你的租户ID.onmicrosoft.com/api/你的权限范围" }, existingAccount)
            .ExecuteAsync();

        // 登录成功,拿到token做后续业务处理
        System.Diagnostics.Debug.WriteLine($"获取到AccessToken: {authResult.AccessToken}");
    }
    catch (MsalUiRequiredException)
    {
        // 需要弹出登录UI
        try
        {
            var authResult = await B2CAuthService.MsalClient
                .AcquireTokenInteractive(new[] { "https://你的租户ID.onmicrosoft.com/api/你的权限范围" })
                .WithParentActivityOrWindow(GetParentWindow()) // 平台特定实现,下面会讲
                .ExecuteAsync();

            // 登录成功处理
            System.Diagnostics.Debug.WriteLine($"登录成功,AccessToken: {authResult.AccessToken}");
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine($"登录失败: {ex.Message}");
            // 这里可以给用户弹出错误提示
        }
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine($"静默登录失败: {ex.Message}");
    }
}

// 平台特定的父窗口获取方法,可用DependencyService实现
private object GetParentWindow()
{
    return Xamarin.Forms.DependencyService.Get<IParentWindowProvider>().GetParentWindow();
}

3. 各平台的关键配置(旧示例失效大多是这里没更新!)

Android平台

  • 在MainActivity.cs里重写OnActivityResult,把登录结果传递给MSAL:
using Microsoft.Identity.Client;

protected override void OnActivityResult(int requestCode, Result resultCode, Android.Content.Intent data)
{
    base.OnActivityResult(requestCode, resultCode, data);
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(requestCode, resultCode, data);
}
  • 在AndroidManifest.xml里添加权限和Intent过滤:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<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" />
        <!-- 替换成你的Android重定向URI的scheme部分 -->
        <data android:scheme="msal你的应用ID" />
    </intent-filter>
</activity>

iOS平台

  • 在AppDelegate.cs里重写OpenUrl方法,处理登录后的回调:
using Microsoft.Identity.Client;
using UIKit;

public override bool OpenUrl(UIApplication app, Foundation.NSUrl url, Foundation.NSDictionary options)
{
    AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
    return true;
}
  • 在Info.plist里添加URL类型和查询权限:
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <!-- 替换成你的iOS重定向URI的scheme部分 -->
            <string>msal你的应用ID</string>
        </array>
    </dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>msauthv2</string>
    <string>msauthv3</string>
</array>

UWP平台

  • 在Package.appxmanifest里确保添加了Enterprise Authentication、Internet (Client)和Private Networks (Client & Server)这三个权限
  • 重定向URI已经在Azure应用注册里配置好了,MSAL会自动处理回调,无需额外代码

4. 登出功能实现

public async Task SignOutUserAsync()
{
    var accounts = await B2CAuthService.MsalClient.GetAccountsAsync();
    foreach (var account in accounts)
    {
        await B2CAuthService.MsalClient.RemoveAsync(account);
    }
    // 清理本地缓存,确保下次登录需要重新验证
    var remainingAccounts = await B2CAuthService.MsalClient.GetAccountsAsync();
    if (remainingAccounts.Any())
    {
        await B2CAuthService.MsalClient.RemoveAsync(remainingAccounts.FirstOrDefault());
    }
}

四、常见问题排查

  • 版本冲突:所有项目的Microsoft.Identity.Client版本必须完全一致,不要混合不同版本
  • 重定向URI不匹配:Azure门户里的重定向URI要和代码、配置文件里的完全一致,大小写也不能错
  • Android登录后无响应:检查MainActivity的OnActivityResult是否正确传递了参数,还有AndroidManifest.xml里的Intent过滤是否配置对了
  • iOS登录后无法返回应用:检查Info.plist里的URL scheme是否和重定向URI的scheme一致,并且添加了LSApplicationQueriesSchemes配置

内容的提问来源于stack exchange,提问作者Vikram Singh Shekhawat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 07:53:07