Asp.net core MSAL.Net未向AcquireTokenSilent调用传递任何帐户或登录提示

Asp.net core MSAL.Net未向AcquireTokenSilent调用传递任何帐户或登录提示,asp.net-core,microsoft-graph-api,msal,microsoft-identity-platform,Asp.net Core,Microsoft Graph Api,Msal,Microsoft Identity Platform,我见过许多相同或相似的问题,并尝试过他们所有的答案,如果有的话,但这些都不适合我 我正在使用Microsoft的Github帐户作为我的项目库 它只适用于登录用户 该项目有1个WebApi,1个Angular应用程序 然后,我按照这个步骤向调用图API添加代码。 以下是控制器代码: [Authorize] [Route("api/[controller]")] [ApiController] public class BillsController : ControllerBase {

我见过许多相同或相似的问题,并尝试过他们所有的答案,如果有的话,但这些都不适合我

我正在使用Microsoft的Github帐户作为我的项目库

它只适用于登录用户

该项目有1个WebApi,1个Angular应用程序

然后,我按照这个步骤向调用图API添加代码。 以下是控制器代码:

[Authorize]
[Route("api/[controller]")]
[ApiController]
public class BillsController : ControllerBase
{
    static readonly string[] scopeRequiredByApi = new string[] { "access_as_user" };
    readonly ITokenAcquisition tokenAcquisition;
    readonly WebOptions webOptions;

    public BillsController(ITokenAcquisition tokenAcquisition,
                          IOptions<WebOptions> webOptionValue)
    {
        this.tokenAcquisition = tokenAcquisition;
        this.webOptions = webOptionValue.Value;
    }

    [HttpGet]
    [AuthorizeForScopes(Scopes = new[] { Constants.ScopeUserRead, Constants.ScopeMailRead })]
    public async Task<IActionResult> Profile()
    {
        HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi);

        var subject = string.Empty;
        try
        {
            // Initialize the GraphServiceClient. 
            Graph::GraphServiceClient graphClient = GetGraphServiceClient(new[] { Constants.ScopeUserRead, Constants.ScopeMailRead });

            var me = await graphClient.Me.Request().GetAsync();
            // Get user photo
            var messages = await graphClient.Me.MailFolders.Inbox.Messages.Request().GetAsync();
            subject = messages.First().Subject;
            return Ok(subject);
        }
        catch (System.Exception ex)
        {
            throw ex;
        }
    }

    private Graph::GraphServiceClient GetGraphServiceClient(string[] scopes)
    {
        return GraphServiceClientFactory.GetAuthenticatedGraphClient(async () =>
        {
            string result = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
            return result;
        }, webOptions.GraphApiUrl);
    }
}
todo-view.component.html

<button (click)="getEmails();">Get Emails</button>
获取电子邮件


我在Startup.cs中添加了以下代码,并删除了AddWebAppCallsProtectedWebApi。 AddProtectedWebApiCallsProtectedWebApi(配置).AddInMemoryTokenCaches()

现在它向我抛出一条不同的错误消息:


我的react应用程序也有同样的问题。由于AuthorizeForScopes用于返回视图,因此它不适用于API解决方案。我能够添加一些配置选项来让它工作

我做的第一件事就是使用SQL缓存。这有助于在站点重新启动时停止“无登录提示”错误。在此之后,令牌将正常工作,直到超时,在此之后,令牌将从缓存中删除,错误将再次出现

为此,我开始查看配置设置。我将配置更改为以下内容

services
    .AddWebAppCallsProtectedWebApi(new string[] { "User.Read" }, idOps =>
    {
        Configuration.Bind("AzureAd", idOps);
        idOps.SaveTokens = true;
        idOps.RefreshOnIssuerKeyNotFound = true;
        idOps.SingletonTokenAcquisition = true;
        idOps.UseTokenLifetime = true;
    },
    ops => Configuration.Bind("AzureAd", ops))
    .AddDistributedTokenCaches()
    .AddDistributedSqlServerCache(options =>
    {
        options.ConnectionString = Configuration.GetConnectionString("Site_DbContext");
        options.SchemaName = "dbo";
        options.TableName = "_TokenCache";
    });
我还没有对它做太多测试来找出神奇的组合,但最合适的地方似乎是
SingletonTokenAcquisition
。有了这个集合,它看起来就像一个混合缓存。当第一次设置时,它将令牌拉入内存并保存它,因此如果它从数据库缓存中删除,它仍然可以访问它

刷新可能需要其他设置,但我还没有测试过


我注意到的一件事是,令牌在刷新之前不会被添加回SQL缓存,因此,如果令牌被删除,站点停止运行并清除内存,错误可能会再次出现,但这是我迄今为止找到的最佳解决方案。我可以让我的SPA运行24小时,并且仍然能够提取新数据。

Franva,你检查过最近的问题线程和解决方法()吗?感谢@Dev在该问题上的帮助,解决方案是使用我在解决方案中所做的
[AuthorizeForScopes(Scopes=newstring[]{“User.Read”})]
。你见过其他的解决方法吗?不客气@Franva。很高兴您已经在使用解决方案。无论何时我看到任何替代解决方案,我都可以提供更新。抱歉@Dev我想我造成了一些沟通错误。我想说的是,通过使用“``[AuthorizeForScopes(Scopes=newstring[]{”User.Read“})]”``并不能解决我的问题。错误仍然存在。我在react应用程序中看到了相同的问题。在初始身份验证时,它将令牌放在缓存(sql)中,并在令牌的生命周期内正常工作。如果令牌过期,它将从缓存中删除,我将收到“无帐户或登录提示”错误。AuthorizeForScopes用于返回视图(MVC),如果调用API(我的API是核心3.1 API),它将不起作用,因此我不确定该怎么做,因为这似乎是一般建议。你找到答案了吗?
<button (click)="getEmails();">Get Emails</button>
services
    .AddWebAppCallsProtectedWebApi(new string[] { "User.Read" }, idOps =>
    {
        Configuration.Bind("AzureAd", idOps);
        idOps.SaveTokens = true;
        idOps.RefreshOnIssuerKeyNotFound = true;
        idOps.SingletonTokenAcquisition = true;
        idOps.UseTokenLifetime = true;
    },
    ops => Configuration.Bind("AzureAd", ops))
    .AddDistributedTokenCaches()
    .AddDistributedSqlServerCache(options =>
    {
        options.ConnectionString = Configuration.GetConnectionString("Site_DbContext");
        options.SchemaName = "dbo";
        options.TableName = "_TokenCache";
    });