[Bug] AcquireTokenSilent always calls a new refresh token when .WithAuthority is set on it.
See original GitHub issueWhich Version of MSAL are you using ? MSAL 4.5.0
Platform net45, netcore
What authentication flow has the issue? AcquireTokenSilent
Other? - please describe;
Is this a new or existing app? This is a new app or experiment
Repro
public async Task<AuthenticationResult> GetAuthTokenForGraphAsync(string clientId, string cacheFileName, string cacheFilePath)
{
IPublicClientApplication publicClientApp = PublicClientApplicationBuilder
.Create(clientId)
.Build();
StorageCreationProperties storageCacheProperty = new StorageCreationPropertiesBuilder(cacheFileName, cacheFilePath, clientId)
.Build();
MsalCacheHelper msalCacheHelper = await MsalCacheHelper.CreateAsync(storageCacheProperty);
msalCacheHelper.RegisterCache(publicClientApp.UserTokenCache);
List<string> scopes = new List<string> { "User.Read" };
var accounts = await publicClientApp.GetAccountsAsync();
try
{
return await publicClientApp.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
// .WithAuthority(publicClientApp.Authority) causes MSAL to always call a new refresh token even if the token cache is in a valid state.
.WithAuthority(publicClientApp.Authority)
.ExecuteAsync();
}
catch (MsalUiRequiredException)
{
return await publicClientApp.AcquireTokenWithDeviceCode(scopes,
deviceCodeResult =>
{
Console.WriteLine(deviceCodeResult.Message);
return Task.FromResult(0);
}).ExecuteAsync();
}
}
var authenticationProvider = new DelegateAuthenticationProvider(async (request) =>
{
string clientId = YOUR_CLIENT_ID;
string cacheFileName = "UserCacheFileName.bin3";
string cacheFilePath = YOUR_CACHE_FILE_PATH;
AuthenticationResult result = await GetAuthTokenForGraphAsync(clientId, cacheFileName, cacheFilePath);
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result.AccessToken);
});
GraphServiceClient graphClient = new GraphServiceClient(authenticationProvider);
// Make request.
for (int i = 0; i < 25; i++)
{
User me = await graphClient.Me.Request().GetAsync();
Console.WriteLine(me.Id);
}
Expected behavior
MSAL should always use a valid token from the token cache when .WithAuthority(URI)
is set on publicClientApp.AcquireTokenSilent(......)
.
Actual behavior
When .WithAuthority(URI)
is set on publicClientApp.AcquireTokenSilent(......)
, MSAL always calls https://login.microsoftonline.com/common/oauth2/v2.0/token
to get a refresh token for every call. This behavior is expensive, and the calling app occasionally gets throttled for making looping calls.
Additional context/ Logs / Screenshots Current call pattern:
Expected call pattern:
This issue could potentially be present in other OAuth flows besides device code flow.
Issue Analytics
- State:
- Created 4 years ago
- Comments:6 (3 by maintainers)
Top GitHub Comments
@peombwa Included in 4.6 release
@peombwa As a workaround, we can check if the first segment of Authority is “common”, “organizations”, or “consumers” and if so, just not call WithAuthority() on AcquireTokenSilent.