【问题标题】:MSAL System.InvalidOperationException: CompactToken parsing failed with error code: 80049217MSAL System.InvalidOperationException:CompactToken 解析失败,错误代码:80049217
【发布时间】:2022-01-05 18:47:37
【问题描述】:

我正在使用 MSAL for .NET 来获取我的 Graph API 请求的令牌,但突然之间,我收到以下错误,我可以看到很多关于此的帖子,但没有解决错误 80049217 的原因发生?有谁知道为什么会发生这个错误,也许是避免这个错误的解决方案?

System.InvalidOperationException:CompactToken 解析失败 错误代码:80049217

更新 22-01-10 获取访问令牌的方法示例(Client 是所有线程使用包含此方法的工厂类重用的 HttpClient 的实例。_confidentialClient 是 MSAL .NET 库中 IConfidentialClientApplication 的实例):

private IConfidentialClientApplication _confidentialClient;

public void Initialize()
{
    // Construct the ConfidentialClientApplication
    _confidentialClient = 
        ConfidentialClientApplicationBuilder.Create("clientId")
            .WithClientSecret("clientSecret")
            .WithAuthority("authority")
            .Build();
}

// Multiple threads will access this method
private async Task GetAccessToken()
{
    try
    {
        Console.WriteLine("Acquire token....");
        // Is the .AcquireTokenForClient method thread safe??
        var result = await _confidentialClient.AcquireTokenForClient("https://graph.microsoft.com/.default").ExecuteAsync();
        if(Client.DefaultRequestHeaders.Authorization?.Parameter == result.AccessToken)
        {
            Console.WriteLine("Token havn't changed.");
            return;
        }
        Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
        Console.WriteLine("Acquire token successfully!");
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}

该工厂类与 Graph API 交互的所有线程都将首先调用 GetAccessToken 方法,以确保 HttpClient 在 Authorization 标头中具有有效的 AccessToken。据我了解 IConfidentialClientApplication,AcquireTokenForClient() 将在内部缓存中查找有效令牌,如果没有,则获取一个新令牌,这就是该方法总是被任何线程调用的原因。

更新 22-01-13: 添加了一些有关如何构建 IConfidentialClientApplication 的逻辑。

【问题讨论】:

  • 您能告诉我们您是如何生成访问令牌的吗?代码 sn-p 或您遵循的教程?恐怕您的代码有问题,然后它使您获得的令牌不是正确的令牌。
  • @TinyWang 我使用 MSAL.NET 库的 IConfidentialClientApplication 接口更新了我如何获取访问令牌的示例。应用程序运行了几个小时以获取新令牌等,没有任何异常,突然(我看不到模式,因为我不知道是什么触发了 CompactToken 错误)它进入了 CompactToken 异常。
  • 您似乎在您的 asp.net 核心后端项目中编写了此代码,并且您想要一种方法来帮助生成不同范围的访问令牌,而无需输入用户名/密码来登录,以便它可以服务于不同的场景。但是你在这里犯了一个错误。请先查看this document。在服务器/守护应用程序中,您只能使用客户端凭证流来生成访问令牌,因此图 api 的范围应该是
  • https://graph.microsoft.com/.default 但不是你写的user.read。或许this section可以帮到你。
  • @TinyWang 对不起,这是一个错字,范围是原因 .default 已经(编辑了代码 sn-p)。是的,您对应用程序的假设是正确的。

标签: c# asp.net-core microsoft-graph-api msal


【解决方案1】:

您似乎在您的 asp.net 核心后端项目中编写了此代码,并且您想要一种方法来帮助生成不同范围的访问令牌,而无需输入用户名/密码来登录,以便它可以服务于不同的场景。但是你在这里犯了一个错误。

请先查看this document。在server/daemon应用中,只能使用client credential flow来生成access token,所以graph api的范围应该是https://graph.microsoft.com/.default,this section提供了使用client credential的示例代码在您的 asp.net 核心应用程序中流动。这是sn-p。

var scopes = new[] { "https://graph.microsoft.com/.default" };

// Multi-tenant apps can use "common",
// single-tenant apps must use the tenant ID from the Azure portal
var tenantId = "common";
// Values from app registration
var clientId = "YOUR_CLIENT_ID";
var clientSecret = "YOUR_CLIENT_SECRET";
// using Azure.Identity;
var options = new TokenCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};
// https://docs.microsoft.com/dotnet/api/azure.identity.clientsecretcredential
var clientSecretCredential = new ClientSecretCredential(
    tenantId, clientId, clientSecret, options);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);

【讨论】:

  • 我使用 Microsoft.Identity.Client 命名空间的 IConfidentialClientApplication 使用我的应用程序使用客户端获取访问令牌的方式更新了原始帖子。应用程序未使用 Azure.Identity 或 Microsoft.Graph 包。
  • 您也可以使用var tokenRequestContext = new TokenRequestContext(scopes); var token = clientSecretCredential.GetTokenAsync(tokenRequestContext).Result.Token;获取访问令牌。那么你就不需要使用graph sdk了。但它仍然使用 Azure.Identity 包。
  • 我不知道如何使用IConfidentialClientApplication,因为我从不使用它。对不起,'
猜你喜欢
  • 2020-02-28
  • 1970-01-01
  • 1970-01-01
  • 2022-10-25
  • 2017-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多