Merge branch 'main' of https://git.azuze.fr/kawa/Sharepoint-Toolbox
This commit is contained in:
@@ -45,14 +45,13 @@ public class GraphClientFactory
|
||||
{
|
||||
var pca = await _msalFactory.GetOrCreateAsync(clientId);
|
||||
|
||||
// When a tenant is specified we must NOT reuse cached accounts from /common
|
||||
// (or a different tenant) — they route tokens to the wrong authority.
|
||||
IAccount? account = null;
|
||||
if (tenantId is null)
|
||||
{
|
||||
var accounts = await pca.GetAccountsAsync();
|
||||
account = accounts.FirstOrDefault();
|
||||
}
|
||||
// Always reuse a cached account when one exists — `WithTenantId` on the
|
||||
// silent/interactive call redirects the authority, and MSAL stores
|
||||
// refresh tokens per tenant. Skipping the cached account forces an
|
||||
// interactive prompt on every Graph call (the bug that produced 4–5
|
||||
// sign-in windows during app registration).
|
||||
var accounts = await pca.GetAccountsAsync();
|
||||
var account = accounts.FirstOrDefault();
|
||||
|
||||
var graphScopes = scopes ?? new[] { "https://graph.microsoft.com/.default" };
|
||||
|
||||
@@ -68,7 +67,7 @@ public class GraphClientFactory
|
||||
internal class MsalTokenProvider : IAccessTokenProvider
|
||||
{
|
||||
private readonly IPublicClientApplication _pca;
|
||||
private readonly IAccount? _account;
|
||||
private IAccount? _account;
|
||||
private readonly string[] _scopes;
|
||||
private readonly string? _tenantId;
|
||||
|
||||
@@ -87,19 +86,35 @@ internal class MsalTokenProvider : IAccessTokenProvider
|
||||
Dictionary<string, object>? additionalAuthenticationContext = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
// Refresh _account from PCA cache each call — interactive flows on a
|
||||
// sibling token provider populate the cache, and we want the next
|
||||
// request on this provider to use that account silently.
|
||||
if (_account is null)
|
||||
{
|
||||
var silent = _pca.AcquireTokenSilent(_scopes, _account);
|
||||
if (_tenantId is not null) silent = silent.WithTenantId(_tenantId);
|
||||
var result = await silent.ExecuteAsync(cancellationToken);
|
||||
return result.AccessToken;
|
||||
var accounts = await _pca.GetAccountsAsync();
|
||||
_account = accounts.FirstOrDefault();
|
||||
}
|
||||
catch (MsalUiRequiredException)
|
||||
|
||||
if (_account is not null)
|
||||
{
|
||||
var interactive = _pca.AcquireTokenInteractive(_scopes);
|
||||
if (_tenantId is not null) interactive = interactive.WithTenantId(_tenantId);
|
||||
var result = await interactive.ExecuteAsync(cancellationToken);
|
||||
return result.AccessToken;
|
||||
try
|
||||
{
|
||||
var silent = _pca.AcquireTokenSilent(_scopes, _account);
|
||||
if (_tenantId is not null) silent = silent.WithTenantId(_tenantId);
|
||||
var result = await silent.ExecuteAsync(cancellationToken);
|
||||
return result.AccessToken;
|
||||
}
|
||||
catch (MsalUiRequiredException)
|
||||
{
|
||||
// fall through to interactive
|
||||
}
|
||||
}
|
||||
|
||||
var interactive = _pca.AcquireTokenInteractive(_scopes);
|
||||
if (_tenantId is not null) interactive = interactive.WithTenantId(_tenantId);
|
||||
var interactiveResult = await interactive.ExecuteAsync(cancellationToken);
|
||||
// Cache the account so subsequent calls on this provider go silent.
|
||||
_account = interactiveResult.Account;
|
||||
return interactiveResult.AccessToken;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user