无法在 .NET 8 maui blazor 混合应用程序中对 Microsoft Entra id 进行身份验证

问题描述 投票:0回答:1

我有一个现有的 Blazor 服务器应用程序,可以很好地连接到 Microsoft Entra id 和 Azure SQL 数据库。客户希望为患者创建一个移动应用程序。 blazor 服务器应用程序仅供客户端管理员使用。

我尝试创建一个 .NET 8 MAUI Blazor 混合应用程序(我使用 Jetbrains Rider,因为这是我可以让 Android 和 iOS 模拟器在我的 Mac 上运行的唯一方法)。我几乎遵循了我能找到的所有教程,但没有运气。我什至问过ChatGPT,它给了我很多有用的信息,但仍然不知道该怎么做。

只有一种解决方案打开了 Microsoft 登录屏幕并让我输入密码和身份验证码,但它没有进行身份验证。我也没有收到任何错误。该项目的链接如下。

https://github.com/VladislavAntonyuk/MauiSamples/tree/main/Auth

我尝试了很多不同的解决方案,但我在这里不知所措。我也只有大约 3 个月的时间来构建这个移动应用程序(Android 和 iOS)。

有人可以帮忙吗?我可以给出我所拥有的代码,但它有很多不同的“解决方案”,因此我不会在这里列出任何代码。

authentication blazor maui .net-8.0 hybrid
1个回答
0
投票

更新:这是我从 ChatGPT 获得的一个解决方案,但仍然不起作用,我知道我说过我不会发布代码,因为有很多“解决方案”。这似乎是最深思熟虑的,但仍然存在类似的问题。 “.WithParentActivityOrWindow(MauiApplication.CurrentActivity)//将MainActivity调整为您的实际主要活动”这一行给我带来了问题。它显示“无法解析符号‘CurrentActivity’”(在 Rider IDE 中)。 ChatGPT 最初说使用“MainActivity.CurrentActivity”,但给出了相同的错误。

AuthenticationService.cs

namespace MauiApp7;

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

public class AuthenticationService
{
    private readonly IPublicClientApplication _publicClientApplication;

    public AuthenticationService(IPublicClientApplication publicClientApplication)
    {
        _publicClientApplication = publicClientApplication;
    }
    
    public string UserDisplayName { get; private set; }

    // Method to update user display name
    public async Task UpdateUserDisplayName()
    {
        try
        {
            var accounts = await _publicClientApplication.GetAccountsAsync();
            var firstAccount = accounts.FirstOrDefault();
            if (firstAccount != null)
            {
                // Retrieve user info from the account or any other source
                UserDisplayName = firstAccount.Username; // For example, use username
            }
        }
        catch (MsalException ex)
        {
            // Handle exception
        }
    }

    public async Task<AuthenticationResult?> SignInInteractively(CancellationToken cancellationToken)
    {
        try
        {
            var result = await _publicClientApplication.AcquireTokenInteractive(Constants.Scopes)
                .ExecuteAsync(cancellationToken);

            return result;
        }
        catch (MsalException ex)
        {
            // Handle exception
            return null;
        }
    }

    public async Task<AuthenticationResult?> AcquireTokenSilent(CancellationToken cancellationToken)
    {
        try
        {
            var accounts = await _publicClientApplication.GetAccountsAsync();
            var firstAccount = accounts.FirstOrDefault();
            if (firstAccount == null)
            {
                return null;
            }

            var result = await _publicClientApplication.AcquireTokenSilent(Constants.Scopes, firstAccount)
                .ExecuteAsync(cancellationToken);

            return result;
        }
        catch (MsalUiRequiredException)
        {
            // Silent token acquisition failed, user interaction required
            return null;
        }
        catch (MsalException ex)
        {
            // Handle specific MSAL exceptions if needed
            Console.WriteLine($"MSAL Exception: {ex.Message}");
            return null;
        }
        catch (Exception ex)
        {
            // Handle other exceptions
            Console.WriteLine($"Exception: {ex.Message}");
            return null;
        }
    }

    public async Task SignOutAsync(CancellationToken cancellationToken)
    {
        try
        {
            var accounts = await _publicClientApplication.GetAccountsAsync();
            foreach (var account in accounts)
            {
                await _publicClientApplication.RemoveAsync(account);
            }
        }
        catch (MsalException ex)
        {
            // Handle exception
        }
    }
}

home.razor 页面

@page "/"

@using Microsoft.Identity.Client
@inject IPublicClientApplication PublicClientApp
@inject AuthenticationService AuthenticationService

<AuthorizeView>
    <Authorized>
        <p>Hello, @AuthenticationService.UserDisplayName!</p>
        <button @onclick="SignOut">Sign out</button>
    </Authorized>
    <NotAuthorized>
        <button @onclick="SignIn">Sign in</button>
    </NotAuthorized>
</AuthorizeView>

@code {
    private async Task SignIn()
    {
        var result = await AuthenticationService.SignInInteractively(CancellationToken.None);
        if (result != null)
        {
            await AuthenticationService.UpdateUserDisplayName();
            // Optionally, you can navigate to a different page after sign-in
        }
    }

    private async Task SignOut()
    {
        await AuthenticationService.SignOutAsync(CancellationToken.None);
        // Optionally, you can navigate to a different page after sign-out
    }
}

Constants.cs

    public class Constants
{
    // Define your scopes here
    public static readonly string[] Scopes = { "user.read" };
}

App.xaml.cs 文件

public partial class App : Application
{
    public App()
    {
        InitializeComponent();

        MainPage = new MainPage();
    }
    
    public static AzureAdConfig AzureAdConfiguration { get; } = new AzureAdConfig
    {
        ClientId = "<clientId>",
        TenantId = "<tenantId>",
        RedirectUri = "msal<clientId>://auth",
        Scopes = new string[] { "user.read" }
    };
}

MauiProgram.cs

    using Microsoft.Extensions.Logging;

using Microsoft.AspNetCore.Components.WebView.Maui;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui;
using Microsoft.Maui.Controls.Hosting;
using Microsoft.Maui.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Identity.Client;

namespace MauiApp7;

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            .UseMauiApp<App>()
            .ConfigureFonts(fonts => { fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular"); });

        builder.Services.AddMauiBlazorWebView();

#if DEBUG
        builder.Services.AddBlazorWebViewDeveloperTools();
        builder.Logging.AddDebug();
#endif

        // Add authentication service directly within CreateMauiApp
        builder.Services.AddSingleton<IPublicClientApplication>(provider =>
        {
            var config = new AzureAdConfig
            {
                // Load configuration from appsettings.json or any other configuration source
                ClientId = "<clientId>",
                TenantId = "<tenantId>",
                RedirectUri = "msal<clientId>://auth",
                Scopes = new[] { "user.read" }
            };
            return PublicClientApplicationBuilder
                .Create(config.ClientId)
                .WithRedirectUri(config.RedirectUri)
                .WithAuthority(AzureCloudInstance.AzurePublic, config.TenantId)
                // Specify the current Activity
                .WithParentActivityOrWindow(MauiApplication.CurrentActivity) // Adjust MainActivity to your actual main activity
                .Build();
        });
        
        builder.Services.AddScoped<AuthenticationService>();
        
        return builder.Build();
    }
}

AzureAdConfig.cs

public class AzureAdConfig
{
    public string ClientId { get; set; }
    public string TenantId { get; set; }
    public string RedirectUri { get; set; }
    public string[] Scopes { get; set; }
}
© www.soinside.com 2019 - 2024. All rights reserved.