错误:由于用户挑战而引发 MsalUiRequiredException

Cef*_*Cef 5 token azure-ad-msal microsoft-graph-api asp.net-core-6.0

我正在尝试进行基本的 Microsoft Graph API 调用,但每当我调用该GetAccessTokenForUserAsync()函数来获取令牌时,都会收到此错误。这是一个 ASP.NET Core 6 MVC 应用程序。

程序.cs:

JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

// Add services to the container.
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
        .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
        .AddInMemoryTokenCaches();
Run Code Online (Sandbox Code Playgroud)

应用程序设置.json:

"MicrosoftGraph": {
    "BaseUrl": "https://graph.microsoft.com/v1.0",
    "Scopes": "user.read"
},
Run Code Online (Sandbox Code Playgroud)

控制器:

[AuthorizeForScopes(Scopes = new string[] { "user.read" })]
public class UserManagementController : Controller
{
    ...
    [AuthorizeForScopes(Scopes = new string[] { "user.read" })]
    public async Task<IActionResult> Index()
    {
        try
        {
             var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { "user.read" });
             return View();
        }
        catch(Exception ex)
        {
            return BadRequest("An error occurred loading the user management page.");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试了很多解决方案。错误总是相同的:

由于用户提出质疑,引发了 MsalUiRequiredException。没有帐户或登录提示传递到 AcquireTokenSilent 调用

我只是想让基础工作发挥作用,没什么花哨的。

Tin*_*ang 0

请允许我在这里分享一个例子。

首先,我们添加 ms Identity ui,创建一个名为_LoginPartial.cshtmlinViews/Shared文件夹的部分视图。

@using System.Security.Principal

<ul class="navbar-nav">
@if (User.Identity.IsAuthenticated)
{
        <li class="nav-item">
            <span class="navbar-text text-dark">Hello @User.Identity.Name!</span>
        </li>
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignOut">Sign out</a>
        </li>
}
else
{
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="MicrosoftIdentity" asp-controller="Account" asp-action="SignIn">Sign in</a>
        </li>
}
</ul>
Run Code Online (Sandbox Code Playgroud)

然后将部分视图添加到_Layout.cshtml<partial name="_LoginPartial" />

在此输入图像描述

然后在 中Program.cs,通过以下代码设置 azure ad 身份验证,并app.UseAuthentication();在前面添加app.UseAuthorization();

string[]? initialScopes = builder.Configuration.GetValue<string>("DownstreamApi:Scopes")?.Split(' ');
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
    .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
        .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
        .AddInMemoryTokenCaches();
// Add services to the container.
builder.Services.AddControllersWithViews(options =>
{
    var policy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .Build();
    options.Filters.Add(new AuthorizeFilter(policy));
}).AddMicrosoftIdentityUI(); 
Run Code Online (Sandbox Code Playgroud)

这些需要以下软件包:

<PackageReference Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="6.0.6" />
<PackageReference Include="Microsoft.Identity.Web.MicrosoftGraph" Version="1.25.1" />
<PackageReference Include="Microsoft.Identity.Web.UI" Version="1.25.1" />
Run Code Online (Sandbox Code Playgroud)

然后在 中appsettings.json,添加如下所示的属性:

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "tenant_name.onmicrosoft.com",
    "TenantId": "common",
    "ClientId": "azure_ad_client_id",
    "ClientSecret": "client_secret",
    "CallbackPath": "/signin-oidc"
  },
  "DownstreamApi": {
    "BaseUrl": "https://graph.microsoft.com/v1.0",
    "Scopes": "user.read"
  }
Run Code Online (Sandbox Code Playgroud)

然后添加[Authorize]主控制器,以便它会在渲染索引页面之前要求您登录。

[Authorize]
public class HomeController : Controller
{
    private readonly ITokenAcquisition _tokenAcquisition;

    public HomeController(ITokenAcquisition tokenAcquisition)
    {
        _tokenAcquisition = tokenAcquisition;
    }

    [AuthorizeForScopes(ScopeKeySection = "DownstreamApi:Scopes")]
    public async Task<IActionResult> IndexAsync()
    {
        string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new string[] { "user.read" });
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)