MSAL 未将令牌存储在缓存中

MSAL not storing token in cache

这是代码:

using Microsoft.Identity.Client;

var scopes = new string[] { "user.read" };
var clientId = "4a1aa1d5-c567-49d0-ad0b-cd957a47f842";
var tenant = "common";
var authority = "https://login.microsoftonline.com/" + tenant;
IPublicClientApplication publicClientApp;
AuthenticationResult authResult;

publicClientApp = PublicClientApplicationBuilder.Create(clientId)
  .WithAuthority(authority)
  .WithRedirectUri("http://localhost:8080")
  .Build();

var accounts = await publicClientApp
  .GetAccountsAsync()
  .ConfigureAwait(false);
IAccount? firstAccount = accounts.FirstOrDefault();

authResult = await publicClientApp
  .AcquireTokenInteractive(new string[] { "user.read" })
  .ExecuteAsync()
  .ConfigureAwait(false);

authResult = await publicClientApp
  .AcquireTokenSilent(new string[] { "user.read" }, firstAccount)
  .ExecuteAsync();

这是抛出的异常:

Unhandled exception. MSAL.NetCore.4.44.0.0.MsalUiRequiredException: 
        ErrorCode: user_null
Microsoft.Identity.Client.MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call. 
   at Microsoft.Identity.Client.Internal.Requests.Silent.SilentRequest.ExecuteAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.Silent.SilentRequest.ExecuteAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
   at Microsoft.Identity.Client.ApiConfig.Executors.ClientApplicationBaseExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenSilentParameters silentParameters, CancellationToken cancellationToken)
   at Program.<Main>$(String[] args) in /home/adrian/temp/microsoft-identity-platform/simpler-version-public/Program.cs:line 25
   at Program.<Main>(String[] args)
        StatusCode: 0 
        ResponseBody:  
        Headers:

csproj 文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RootNamespace>simpler_version_public</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Identity.Client" Version="4.44.0" />
  </ItemGroup>

</Project>

我的理解是调用AcquireTokenInteractive()应该自动将token存入缓存,AcquireTokenSilent()从缓存中获取token。那为什么我会收到错误消息?我在WSL中运行这段代码,dotnet --versionreturns6.0.300.

您在 AcquireTokenInteractive 之前调用 GetAccountsAsync,但 return 没有任何帐户。没有帐户传递给 AcquireTokenSilent,并且此方法不知道应该为哪个帐户获取访问令牌。

调用AcquireTokenInteractive后需要调用GetAccountsAsync。在这种情况下,它将 return 帐户和 AcquireTokenSilent 将从指定帐户的缓存中获取令牌。

authResult = await publicClientApp
  .AcquireTokenInteractive(new string[] { "user.read" })
  .ExecuteAsync()
  .ConfigureAwait(false);

var accounts = await publicClientApp
  .GetAccountsAsync()
  .ConfigureAwait(false);
IAccount? firstAccount = accounts.FirstOrDefault();    

authResult = await publicClientApp
  .AcquireTokenSilent(new string[] { "user.read" }, firstAccount)
  .ExecuteAsync();

根据 Microsoft 在 Github 存储库中提供的示例,您只需使用 app.AddInMemoryTokenCache() with ConfidentialClientApplicationBuilder, and new StorageCreationPropertiesBuilder(...).WithLinuxKeyring(...)PublicClientApplicationBuilder