Blazor WASM 项目在每次启动项目时强制进行身份验证。

huangapple go评论71阅读模式
英文:

Blazor WASM project forces to authenticate every time the project is started

问题

I have made the requested translation for the provided text. Here is the translated part:

我已经为您提供了提供的文本的翻译。以下是翻译好的部分:

我已经拥有一个 Blazor WASM 和一个 ASP.NET Core Web API 设置,用于与 Azure Active Directory 进行身份验证(根据文档进行设置,还有其他情景,因为在我的情况下这两个是独立的项目)。

WASM 项目以及通过访问令牌访问的 API 上的身份验证都运行得很好,但是每次启动项目时都必须进行登录过程(使用多重因素身份验证时会变得相当麻烦)。

为了避免这个问题,我已经将以下行添加到 WASM 项目的 Program.cs 中:

builder.Services.AddMsalAuthentication(options =>
{
    // 在此处进行 MSAL 设置配置

    if (builder.HostEnvironment.IsEnvironment("Development"))
        options.ProviderOptions.Cache.CacheLocation = "localStorage";
});

很好,现在我不需要每次都登录了,但不幸的是,API 上的授权将会失败:

信息:Microsoft.AspNetCore.Authorization.DefaultAuthorizationService2
授权失败。未满足这些要求:
DenyAnonymousAuthorizationRequirement:需要经过身份验证的用户。

是否可能解决这个问题?在生产环境中,用户每次访问站点时都会被迫进行登录吗?令牌不应该在一定时间内有效吗?

编辑
一些额外信息。HttpClient 配置了一个 CustomAuthorizationMessageHandler,如下所示:

Program.cs

builder.Services.AddHttpClient("MyAPI", client =>
    client.BaseAddress = new Uri("https://localhost:7124"))
        .AddHttpMessageHandler<CustomAuthorizationMessageHandler>();

CustomAuthorizationMessageHandler.cs

public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
    public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
        NavigationManager navigation)
        : base(provider, navigation)
    {
        ConfigureHandler(
            authorizedUrls: new[] { "https://localhost:7124" },
            scopes: new[] { "api://<<some id>>/API.Access" });
    }
}

[1]: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/hosted-with-azure-active-directory?view=aspnetcore-7.0
[2]: https://learn.microsoft.com/en-us/aspnet/core/blazor/security/webassembly/additional-scenarios?view=aspnetcore-7.0

If you have any more questions or need further assistance, please feel free to ask.

英文:

I have a Blazor WASM and a ASP.NET Core Web API setup to work with Azure Active Directory for Authentication (setup according to the docs with additional scenarios since in my case the two are separate projects).

Authentication on the WASM project as well as API via accessed toke works quite fine, however the login procedure has to be done every time the projects are started (with MFA this becomse quite a hassle).

To avoid this I have added the following line to Program.cs of the WASM project:

builder.Services.AddMsalAuthentication(options =&gt;
{
    // MSAL setup config with AAD here

    if(builder.HostEnvironment.IsEnvironment(&quot;Development&quot;))
        options.ProviderOptions.Cache.CacheLocation = &quot;localStorage&quot;;
});

Cool, now I don't need to login everytime anymore, however unfortunately with this the Authorization on the API will fail:

> info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService2
Authorization failed. These requirements were not met:
DenyAnonymousAuthorizationRequirement: Requires an authenticated user.

Is it possible to solve this issue? Will users in production be forced to login every time they access the site as well? Shouldn't a token be valid for a certain amount of time?

Edit
Some additional Info. The HttpClient is configured with a CustomAuthorizationMessageHandler as follows:

Program.cs

builder.Services.AddHttpClient(&quot;MyAPI&quot;, client =&gt;
        client.BaseAddress = new Uri(&quot;https://localhost:7124&quot;))
            .AddHttpMessageHandler&lt;CustomAuthorizationMessageHandler&gt;();

CustomAuthorizationMessageHandler.cs

public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
    public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
        NavigationManager navigation)
        : base(provider, navigation)
    {
        ConfigureHandler(
            authorizedUrls: new[] { &quot;https://localhost:7124&quot; },
            scopes: new[] { &quot;api://&lt;&lt;some id&gt;&gt;/API.Access&quot; });
    }
}

答案1

得分: 1

我在我的配置中进行了测试,使用了您的配置 `options.ProviderOptions.Cache.CacheLocation = "localStorage";`,这使我不需要重新登录,我尝试调用了受 Azure AD 保护的 Web API,它也正常工作。但是我的应用程序中没有多重身份验证(MFA)。

以下是我关于调用 API 的代码,我担心在出现问题时您可以检查生成的令牌是否正确。

@page "/profile"
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@attribute [Authorize]
@inherits UserProfileBase
@inject IAccessTokenProvider TokenProvider

<h3>用户资料</h3>
<button @onclick="call">
    调用 API
</button>
<div>@result</div>


@code {

    private string result = "暂无数据";

    private async Task call()
    {
        var http = new HttpClient();
        http.BaseAddress = new Uri("https://localhost:7018/WeatherForecast");

        var tokenResult = await TokenProvider.RequestAccessToken(
            new AccessTokenRequestOptions
                {
                    Scopes = new[] { "api://aad_Client_id/Tiny.Read" }
                });

        if (tokenResult.TryGetToken(out var token))
        {
            http.DefaultRequestHeaders.Add("Authorization",
                $"Bearer {token.Value}");
            result = await http.GetStringAsync("https://localhost:7018/WeatherForecast");
        }
    }
}
英文:

I have a test in my side with your configuration options.ProviderOptions.Cache.CacheLocation = &quot;localStorage&quot;; which makes me no need to sign in again, and I tried to call the web api which is protected by Azure AD and it worked as well. But I don't have MFA in my App.

Here's my code about calling API, I'm afraid you can check if the token generated correctly when the issue happened.

@page &quot;/profile&quot;
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
@attribute [Authorize]
@inherits UserProfileBase
@inject IAccessTokenProvider TokenProvider

&lt;h3&gt;User Profile&lt;/h3&gt;
&lt;button @onclick=&quot;call&quot;&gt;
    call api
&lt;/button&gt;
&lt;div&gt;@result&lt;/div&gt;


@code {

    private string result = &quot;no data now&quot;;

    private async Task call()
    {
        var http = new HttpClient();
        http.BaseAddress = new Uri(&quot;https://localhost:7018/WeatherForecast&quot;);

        var tokenResult = await TokenProvider.RequestAccessToken(
            new AccessTokenRequestOptions
                {
                    Scopes = new[] { &quot;api://aad_Client_id/Tiny.Read&quot; }
                });

        if (tokenResult.TryGetToken(out var token))
        {
            http.DefaultRequestHeaders.Add(&quot;Authorization&quot;,
                $&quot;Bearer {token.Value}&quot;);
            result = await http.GetStringAsync(&quot;https://localhost:7018/WeatherForecast&quot;);
        }
    }
}

huangapple
  • 本文由 发表于 2023年2月23日 19:29:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/75544209.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定