在 Android 上使用 .NET MAUI 中的 Web Authenticator 进行 Google 登录的正确方法

Pre*_*ius 5 maui webauthenticator

我已在此处关注 .NET Maui 的 Web 身份验证器的官方文档。它解释了如何有效地执行操作,但他们错过了一些有关回调 URL 的关键信息。根据文章,URL 应该是 myapp://。我认为它可能是类似 thisapp:// 的东西。

myapp:// 的问题是 WebAuthenticatorActivity 不喜欢这样。使用 myapp:// 作为回调 URL 时出现以下错误:

您必须子类化WebAuthenticatorCallbackActivity并为其创建一个与您的callbackUrl.

在底部我将发布代码。

我还查看了 Dan Siegal 的帮助程序库和他在 MAUI 网络身份验证器上的视频,但他无法让该应用程序在视频中运行。我还在GitHub 上查看了他的示例,他使用“myapp”作为回调 URL。仅使用“myapp”的问题是,当您为 Web 身份验证器指定回调 URL 时, Uri类不喜欢它。这是我得到的错误:

无效 URI:无法确定 URI 的格式。

所以基本上我不能使用“myapp://”或“myapp”并决定将两者结合起来。对于回调 URL,我使用“myapp://”,对于 WebAuthenticatorActivity,我使用“myapp”。这确实有效,但仍然存在一个问题。在 Google 控制台上,它需要重定向 URL。我尝试过“myapp://”或“myapp”,但它不允许这样做:

在此输入图像描述

在网上搜索后,我发现一篇文章提到我应该使用:https://mysite/signin-google。我已根据文档并使用 Dan Siegal 的库正确设置了 API。

因此,如果我在 Google 控制台上使用“myapp://”作为 Web 身份验证器的回调 URL,使用“myapp”作为 WebAuthenticatorActivity 和 https://mysite/signin-google,那么一切都会正常工作,直到 Google 尝试重定向从浏览器返回我的应用程序。这是我得到的错误:

无法找到此 mysite 页面。未找到该网址的网页:https://mysite/signin-google

归结为:

我应该使用什么值:

  1. Web认证器的回调URL
  2. WebAuthenticator 活动
  3. Google 控制台重定向 URL

这是我的代码:

文件MauiProgram.cs

using CommunityToolkit.Maui;
using FertilizerFarm.Helpers;
using FertilizerFarm.Services;
using FertilizerFarm.View;
using Refit;
using Telerik.Maui.Controls.Compatibility;

namespace FertilizerFarm;
public static class Constants
{

    public const string BaseUrl = "https://mysite/mobileauth/";
    public const string CallbackScheme = "myapp://";
}
public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
             .UseTelerik()
            .UseMauiApp<App>()
            .UseMauiCommunityToolkit()
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
                fonts.AddFont("telerikfontexamples.ttf", "TelerikFontExamples");
            });
        builder.Services.AddSingleton<IConnectivity>(Connectivity.Current)
        .AddSingleton(WebAuthenticator.Default)
        .AddSingleton(SecureStorage.Default)
        .AddRefitClient<IUserProfileService>()
        .AddSingleton<AuthService>()
        .AddSingleton<JWTService>()
        .AddTransient<LoginViewModel>()
        .AddTransient<Login>()

        return builder.Build();
    }
    public static IServiceCollection AddRefitClient<T>(this IServiceCollection services)
      where T : class
    {
        services.AddSingleton(sp =>
        {
            var settings = new RefitSettings
            {
                AuthorizationHeaderValueGetter = () => sp.GetRequiredService<ISecureStorage>().GetAsync("access_token")
            };
            return RestService.For<T>(Constants.BaseUrl, settings);
        });
        return services;
    }
}
Run Code Online (Sandbox Code Playgroud)

文件WebAuthenticatorCallbackActivity.cs

using Android.App;
using Android.Content;
using Android.Content.PM;

namespace FertilizerFarm;

[Activity(NoHistory = true, LaunchMode = LaunchMode.SingleTop, Exported = true)]
[IntentFilter(new[] { Intent.ActionView },
                  Categories = new[] { Intent.CategoryDefault, Intent.CategoryBrowsable },
                  DataScheme = CALLBACK_SCHEME)]
public class WebAuthenticatorActivity : Microsoft.Maui.Authentication.WebAuthenticatorCallbackActivity
{
    const string CALLBACK_SCHEME = "myapp";
}
Run Code Online (Sandbox Code Playgroud)

文件LoginViewModel.cs

[RelayCommand]
    async Task SocialLogin()
    {
        try
        {
            var result = await _webAuthenticator.AuthenticateAsync(new WebAuthenticatorOptions
            {
                CallbackUrl = new Uri($"{Constants.CallbackScheme}"),
                Url = new Uri(Constants.BaseUrl + "google")
            });

            await _storage.SetAsync("access_token", result.AccessToken);

            using var response = await _userProfile.GetProfileClaims();
            if (response.IsSuccessStatusCode)
            {
                Claims.Clear();
                var claims = response.Content.Select(x => $"{x.Key}: {x.Value}");
                foreach (var claim in claims)
                    Claims.Add(claim);
            }
        }
        catch (Exception ex)
        {
        }
    }
Run Code Online (Sandbox Code Playgroud)

小智 1

myapp:// 是App与API之间的回调

Google 不了解该应用程序,仅与 API 进行通信

Google 需要一个重定向 URL 才能找到返回 API 的路径

这应该类似于 https://localhost:{PORT}/signin-google

这些页面帮助我解决了这个问题:

https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins?view=aspnetcore-6.0

https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/communication/authentication?tabs=ios