Exception: AcquireTokenSilentAsync An item with the same key has already been added. Key: User-Agent
See original GitHub issueWhich Version of MSAL are you using ? MSAL 2.2.1-preview
Which platform has the issue? Xamarin Android
What authentication flow has the issue?
- Desktop
- Interactive
- Integrated Windows Auth
- Username / Password
- Device code flow (browserless)
- Mobile
- Web App
- Authorization code
- OBO
- Web API
- OBO
Repro I have a Xamarin forms application - users have accounts on Azure AD B2C. I am using this library to authenticate the user and get a token to pass on to my WebApi. It works really well. However I am seeing an exception randomly when I call AcquireTokenSilentAsync.
I have a service class where I have placed all my web calls - so everything that needs access to the API is using this code. I have background threads and button events which call this function.
Issue appears to happen most on app resume/startup when my app will make 2 calls to the API (one of which is running a separate thread). In most cases - one of them succeeds, and one fails with the exception. An item with the same key has already been added. Key: User-Agent. Should I just retry the failed one in the hope it passes the next time? Or is there something extra I need to do?
Here is my code:
`public async Task<T> GetSecureAsync<T>(string apiUrl, bool forceRefreshToken = false)
{
try
{
AuthenticationResult ar = null;
try
{
var accounts = await App.AuthenticationClient.GetAccountsAsync();
ar = await App.AuthenticationClient.AcquireTokenSilentAsync(ApplicationSettings.Scopes, accounts.FirstOrDefault());//, ApplicationSettings.Authority, forceRefreshToken);
}
catch (Exception ex)
{
LogException(ex, nameof(GetSecureAsync), typeof(Client).ToString());
}
if (ar != null)
{//use token and call API
using (HttpClient client = new HttpClient(new NativeMessageHandler() { Timeout = TimeSpan.FromMilliseconds(30000) }))
{`
Expected behavior User should be authenticated if a token exists in cache for them - an AuthenticationResult should be returned.
Actual behavior An exception is thrown: An item with the same key has already been added. Key: User-Agent
Additional context/ Logs / Screenshots Here is the stack trace of the exception:
System.Collections.Generic Dictionary
2[TKey,TValue].TryInsert (TKey key, TValue value, System.Collections.Generic.InsertionBehavior behavior)
System.Collections.Generic Dictionary2[TKey,TValue].Add (TKey key, TValue value) System.Net.Http.Headers HttpHeaders.GetValues[T] (System.String name) System.Net.Http.Headers HttpRequestHeaders.get_UserAgent () Microsoft.Identity.Core.Http HttpManager+<ExecuteAsync>d__9.MoveNext () System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) System.Runtime.CompilerServices ConfiguredTaskAwaitable
1+ConfiguredTaskAwaiter[TResult].GetResult ()
Microsoft.Identity.Core.Http HttpManager+<ExecuteWithRetryAsync>d__8.MoveNext ()
System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices ConfiguredTaskAwaitable1+ConfiguredTaskAwaiter[TResult].GetResult () Microsoft.Identity.Core.Http HttpManager+<SendGetAsync>d__5.MoveNext () System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) System.Runtime.CompilerServices ConfiguredTaskAwaitable
1+ConfiguredTaskAwaiter[TResult].GetResult ()
Microsoft.Identity.Core.Http HttpRequest+<SendGetAsync>d__3.MoveNext ()
System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices ConfiguredTaskAwaitable1+ConfiguredTaskAwaiter[TResult].GetResult () Microsoft.Identity.Core.OAuth2 OAuth2Client+<ExecuteRequestAsync>d__8
1[T].MoveNext ()
System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices ConfiguredTaskAwaitable1+ConfiguredTaskAwaiter[TResult].GetResult () Microsoft.Identity.Core.OAuth2 OAuth2Client+<DiscoverAadInstanceAsync>d__6.MoveNext () System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) System.Runtime.CompilerServices ConfiguredTaskAwaitable
1+ConfiguredTaskAwaiter[TResult].GetResult ()
Microsoft.Identity.Core.Instance AadInstanceDiscovery+<SendInstanceDiscoveryRequestAsync>d__10.MoveNext ()
System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices ConfiguredTaskAwaitable1+ConfiguredTaskAwaiter[TResult].GetResult () Microsoft.Identity.Core.Instance AadInstanceDiscovery+<DoInstanceDiscoveryAndCacheAsync>d__9.MoveNext () System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) System.Runtime.CompilerServices ConfiguredTaskAwaitable
1+ConfiguredTaskAwaiter[TResult].GetResult ()
Microsoft.Identity.Core.Instance AadInstanceDiscovery+<GetMetadataEntryAsync>d__5.MoveNext ()
System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices ConfiguredTaskAwaitable1+ConfiguredTaskAwaiter[TResult].GetResult () Microsoft.Identity.Client TokenCache+<GetCachedOrDiscoverAuthorityMetaDataAsync>d__42.MoveNext () System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) System.Runtime.CompilerServices ConfiguredTaskAwaitable
1+ConfiguredTaskAwaiter[TResult].GetResult ()
Microsoft.Identity.Client TokenCache+<GetAccountsAsync>d__46.MoveNext ()
System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task)
System.Runtime.CompilerServices ConfiguredTaskAwaitable1+ConfiguredTaskAwaiter[TResult].GetResult () Microsoft.Identity.Client ClientApplicationBase+<GetAccountsAsync>d__33.MoveNext () System.Runtime.CompilerServices TaskAwaiter.ThrowForNonSuccess (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.HandleNonSuccessAndDebuggerNotification (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter.ValidateEnd (System.Threading.Tasks.Task task) System.Runtime.CompilerServices TaskAwaiter
1[TResult].GetResult ()
MyApp.Services Client+<GetSecureAsync>d__0`1[T].MoveNext
Issue Analytics
- State:
- Created 5 years ago
- Comments:8
Top GitHub Comments
I think so yes, I put a call to GetAccountsAsync after I initalise the Public Client Applocation and it seems to work. Happy to close
awesome…thanks for getting back so quickly @WilliamWatterson86 If you run into any more issues, please open another issue. thanks. I’ll update the wiki as well, for others who run into this issue.