使用 Azure Active Directory 访问 Azure Function 时,Blazor 客户端出现 CORS 错误

Chr*_*ens 5 azure-active-directory blazor azure-function-app blazor-client-side

我已经尝试部署 Blazor PWA 2 天了,到目前为止没有任何成功,如果有人知道我\xe2\x80\x99m 做错了什么,我将非常感激。\n你好\n我可以解决我的大部分问题我自己的问题,但我现在陷入了使用 AAD 的 CORS 问题。

\n

这是我的项目设置:

\n
    \n
  • Blazor WebAssembly 客户端托管在静态网站存储上(有效\ngreat),Net 5
  • \n
  • 连接到 Azure Sql Server 数据库的 AzureFunctions(与 Blazor 中的匿名身份验证配合\n效果很好)
  • \n
  • 我想使用 Azure Active Directory 对用户进行身份验证。\n(保护 blazor 应用程序和功能)
  • \n
\n

因此,我\xe2\x80\x99ve创建了一个应用程序注册,将我的静态网站地址添加为SPA uri并取消选中两者隐式。\n在我的blazor客户端program.cs中,我\xe2\x80\x99ve添加了以下代码来连接至 AAD:

\n
builder.Services.AddMsalAuthentication(options =>\n{\n    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication); //contains clientId, Authority\n    options.ProviderOptions.DefaultAccessTokenScopes.Add("https://graph.microsoft.com/User.Read");\n    options.ProviderOptions.LoginMode = "redirect";\n});\n
Run Code Online (Sandbox Code Playgroud)\n

这也很好用,我可以登录,授权查看按预期工作。

\n

问题是,当我尝试使用 Azure Active Directory\xc2\xbb 使用 \xc2\xabLogin 验证 Azure 功能时,\n我尝试使用快速配置和高级配置(使用 clientId、tenantId),但是当我

\n

可以从源“https://login.windows.net/tenantid/oauth2/authorize ...(从“https://myfunctionstorage.azurewebsites.net/api/client/list”重定向)获取数据:/ /*****9.web.core.windows.net' 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明响应满足您的需求,请将请求模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。

\n

我当然在 Azure Functions 配置上为我的 Blazor 客户端地址启用了 CORS,但问题似乎与登录 Windows uri 相关...

\n

另外,如果我在应用程序注册中启用令牌 id 隐式流并在浏览器中访问登录 url,则它工作得很好。

\n

到目前为止我能找到的所有示例都是关于 msal 1.0 和使用隐式流而不是 SPA 的应用程序注册,因此它没有帮助......

\n

感谢您的时间和帮助。

\n

更新:\n我\xe2\x80\x99从昨天开始做了更多的研究,我认为它可能与我的HTTPClient有关,目前我使用基本的(只有一个基本地址)。

\n

但我\xe2\x80\x99在一些示例中看到,当使用AAD使用客户端时,它需要更多参数,例如:

\n
builder.Services.AddHttpClient("companiesAPI", cl => { cl.BaseAddress = new Uri("https://localhost:5001/api/"); }) .AddHttpMessageHandler(sp => { var handler = sp.GetService<AuthorizationMessageHandler>() .ConfigureHandler( authorizedUrls: new[] { "https://localhost:5001" }, scopes: new[] { "companyApi" } ); return handler; });\n
Run Code Online (Sandbox Code Playgroud)\n

需要 AuthorizationMessageHandler 吗?\n我还看到一些需要使用 \xc2\xabuse_impersonation\xc2\xbb 范围的参考。

\n

使用 msal2/SPA 应用程序注册时是否也需要进行这些更改(在 HttpClient 和 use_impersonation 范围上)?

\n

谢谢

\n

Jim*_* Xu 2

如果要在 Blazor WebAssembly 客户端中调用 Azure AD 投影的 Azure 函数,请参阅以下步骤 如果要在 Angular 应用程序中调用 Azure AD 投影的 Azure 函数,请参阅以下代码

  • 创建 Azure AD 应用程序以保护功能

    1. 注册 Azure AD 应用程序。完成此操作后,请复制 应用程序(客户端)ID目录(租户)ID

    2. 配置重定向 URI。选择Web并输入<app-url>/.auth/login/aad/callback

    3. 启用隐式授权流程

    4. 定义 API 范围并复制它 在此输入图像描述

    5. 创建客户端机密。

  • 在应用服务应用中启用 Azure Active Directory

  • 在 Azure Function 中配置 CORS 策略 在此输入图像描述

  • 创建客户端AD应用程序来访问功能

    1. 注册申请
    2. 启用 隐式授权流程
    3. 配置API权限。让您的客户端应用程序有权访问函数
  • 代码

  1. 创建自定义AuthorizationMessageHandler
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
    public CustomAuthorizationMessageHandler(IAccessTokenProvider provider, 
        NavigationManager navigationManager)
        : base(provider, navigationManager)
    {
        ConfigureHandler(
            authorizedUrls: new[] { "<your function app url>" },
            scopes: new[] { "<the function app  API scope your define>" });
    }
}
Run Code Online (Sandbox Code Playgroud)
  1. 在 中添加以下代码Program.cs
 public static async Task Main(string[] args)
        {
            var builder = WebAssemblyHostBuilder.CreateDefault(args);
            builder.RootComponents.Add<App>("app");
             // register CustomAuthorizationMessageHandler 
            builder.Services.AddScoped<CustomAuthorizationMessageHandler>();
            // configure httpclient
            // call the following code please add packageMicrosoft.Extensions.Http 3.1.0
            builder.Services.AddHttpClient("ServerAPI", client =>
              client.BaseAddress = new Uri("<your function app url>"))
                    .AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
            // register the httpclient
            builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
             .CreateClient("ServerAPI"));
            // configure Azure AD auth
            builder.Services.AddMsalAuthentication(options =>
            {
                builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
                options.ProviderOptions.DefaultAccessTokenScopes.Add("<the function app  API scope your define>");


            });

            await builder.Build().RunAsync();
        }
Run Code Online (Sandbox Code Playgroud)
  1. 调用API
@page "/fetchdata"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject HttpClient Http

<h1>Call Azure Function</h1>

<p>This component demonstrates fetching data from the server.</p>

<p>Result: @forecasts</p>

<button class="btn btn-primary" @onclick="CallFun">Call Function</button>

@code {
    private string forecasts;

    protected async Task CallFun()
    {
        forecasts = await Http.GetStringAsync("api/http");
    }


}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述