【问题标题】:Microsoft.Graph.ServiceException' Code: BadRequest Message: Current authenticated context is not valid for this requestMicrosoft.Graph.ServiceException' 代码:BadRequest 消息:当前经过身份验证的上下文对此请求无效
【发布时间】:2017-10-06 15:41:00
【问题描述】:

我在使用 Microsoft Graph API 时遇到问题。每当我尝试获取日历时,都会收到以下错误消息:

抛出异常:“Microsoft.Graph.ServiceException”在 System.Private.CoreLib.dll:'代码:BadRequest 消息:当前 经过身份验证的上下文对此请求无效

一开始我以为和this的帖子差不多,但是我的用户是经过认证的,所以我相信不是这样的。

这是我的代码:

EventController.cs

public async Task<Calendar> GetEventInfoAsync()
    {
        var accessToken = await getAcessTokenAsync();
        DelegateAuthenticationProvider delegateAuthenticationProvider = new DelegateAuthenticationProvider(
            (requestMessage) => 
            {
                requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                return Task.FromResult(0);
            }
        );
        GraphServiceClient graphClient = new GraphServiceClient(delegateAuthenticationProvider);
        var calendar = await graphClient.Me.Calendar.Request().GetAsync();
        return calendar;
    }

这就是我获取访问令牌的方式:

public async Task<string> getAcessTokenAsync()
    {
        if(User.Identity.IsAuthenticated)
        {
            var userId = User.FindFirst("MicrosoftUserId")?.Value;
            ConfidentialClientApplication cca =
                new ConfidentialClientApplication( Configuration["MicrosoftAuth:ClientId"],
                                                    String.Format(System.Globalization.CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}{1}", "common", "/v2.0"),
                                                    Configuration["MicrosoftAuth:RedirectUri"]+ "signin-oidc", 
                                                    new Microsoft.Identity.Client.ClientCredential(Configuration["MicrosoftAuth:ClientSecret"]),
                                                    new SessionTokenCache(userId,_memoryCache).GetCacheInstance(),
                                                    null);               
            var token = await cca.AcquireTokenForClientAsync(new string[]{"https://graph.microsoft.com/.default"});
            return token.AccessToken;
        }
        else
            throw new Exception("User is not autenticated");
    }

最后,这是身份验证选项在启动文件中的样子。

services.AddAuthentication().AddOpenIdConnect(openIdOptions => 
        {
            openIdOptions.ResponseType = OpenIdConnectResponseType.CodeIdToken;
            openIdOptions.Authority = String.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}{1}", "common", "/v2.0");
            openIdOptions.ClientId = Configuration["MicrosoftAuth:ClientId"];
            openIdOptions.ClientSecret = Configuration["MicrosoftAuth:ClientSecret"];
            openIdOptions.SaveTokens = true;
            openIdOptions.TokenValidationParameters = new TokenValidationParameters{
                ValidateIssuer = false
            };
            var scopes = Configuration["MicrosoftAuth:Scopes"].Split(' ');
                foreach (string scope in scopes){
                    openIdOptions.Scope.Add(scope);
            }
            openIdOptions.Events = new OpenIdConnectEvents{
                OnAuthorizationCodeReceived = async (context) =>
                {   
                    var userId = context.Principal.Claims.First(item => item.Type == ObjectIdentifierType).Value;
                    IMemoryCache memoryCache = context.HttpContext.RequestServices.GetRequiredService<IMemoryCache>();
                    ConfidentialClientApplication cca =
                        new ConfidentialClientApplication( Configuration["MicrosoftAuth:ClientId"],
                                                            String.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}{1}{2}", "common", "/v2.0", "/adminconsent"),
                                                            Configuration["MicrosoftAuth:RedirectUri"]+ "signin-oidc", 
                                                            new Microsoft.Identity.Client.ClientCredential(Configuration["MicrosoftAuth:ClientSecret"]),
                                                            new SessionTokenCache(userId,memoryCache).GetCacheInstance(),
                                                            null);
                    var code = context.ProtocolMessage.Code;                        
                    var result = await cca.AcquireTokenByAuthorizationCodeAsync(code,new string[]{"User.Read.All", "Calendars.ReadWrite"});
                    context.HandleCodeRedemption(result.AccessToken, result.IdToken);
                },
            };
        });

我的应用程序已在 Microsoft 应用程序注册门户中注册,并且在我请求它时确实获得了一个令牌,因此我不确定可能是什么导致了问题。

【问题讨论】:

    标签: c# azure-active-directory microsoft-graph-api msal


    【解决方案1】:

    与预览线程相同的问题。 Azure AD 颁发的令牌有两种,委托使用或应用。您获得的令牌正在使用 client credentials 流,它是应用程序的委托。使用这种令牌请求时没有me 上下文(请参阅Get access on behalf of a userGet access without a user 了解区别)。

    要将 Microsoft Graph 与 Web 应用程序集成并委托用户调用 Microsoft Graph,您需要使用 代码授权流程OnAuthorizationCodeReceived 事件)作为您在 startup.cs 文件中的配置.

    【讨论】:

    • 我以为我正在这样做。我已将 openid 选项中的授权地址更改为 https://login.microsoftonline.com/common/v2.0/authorize?,并将 OnAuthorizationCodeReceived 事件的 CCA 中的授权地址更改为 https://login.microsoftonline.com/common/v2.0/token,但我仍然收到相同的错误消息。当我更改openId权限时,我必须单独添加元数据地址,如https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration
    • 您正在使用ConfidentialClientApplication,这是客户端凭据流。查看docs.microsoft.com/en-us/azure/active-directory/develop/… 以获取使用PublicClientApplication 的示例
    • 使用 OpenID 连接 PublicClientApplication 有意义吗?我认为现在有可用的方法来获取带有授权码的访问令牌。还是应该使用其他类型的 OpenId 事件?
    • 我在实现 PublicClientApplication 时遇到了问题。我真的不明白如何设置它。在示例中,它是在桌面应用程序中实现的,但我不确定如何在我的 MVC 项目中使用它。
    • @MarcosTrucco 请参考this code sample,它演示了将 Azure AD V2.0 端点与 Web 应用程序集成。如果您仍有问题,请随时告诉我。
    猜你喜欢
    • 2017-06-24
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 2021-05-26
    • 1970-01-01
    • 2021-08-30
    • 2023-04-07
    • 2021-12-03
    相关资源
    最近更新 更多