Microsoft-authentication-library-for-dotnet: COMException calling PublicClientApplication.AcquireTokenSilentAsync

Created on 8 Sep 2018  路  16Comments  路  Source: AzureAD/microsoft-authentication-library-for-dotnet

Which Version of MSAL are you using ?
MSAL 2.0.0-preview

Which platform has the issue?
UWP

What authentication flow has the issue?

  • Desktop

    • [x] Interactive

Repro

string[] Scopes = new[] { "User.Read", "Files.ReadWrite.AppFolder", "Files.Read.All" };
PublicClientApplication app = new PublicClientApplication(ServiceApiKeys.MsalClientId) { RedirectUri = ServiceApiKeys.MsalClientRedirectUri };
AuthenticationResult auth = await app.AcquireTokenAsync(Scopes, null);

Expected behavior
I'd expect this to work, as it did in 1.1.4-preview0002.

Actual behavior
When signing in with an MSA, I see the following exception:

    System.Runtime.InteropServices.COMException: 'The length of the state manager setting name has exceeded the limit.

Error trying to write application data container value'

   at System.Runtime.InteropServices.WindowsRuntime.IMap`2.Insert(K key, V value)
   at System.Runtime.InteropServices.WindowsRuntime.MapToDictionaryAdapter.Insert[K,V](IMap`2 _this, K key, V value)
   at System.Runtime.InteropServices.WindowsRuntime.MapToDictionaryAdapter.Indexer_Set[K,V](K key, V value)
   at Microsoft.Identity.Core.Telemetry.TelemetryTokenCacheAccessor.SaveAccessToken(MsalAccessTokenCacheItem item, RequestContext requestContext)
   at Microsoft.Identity.Client.TokenCache.SaveAccessAndRefreshToken(AuthenticationRequestParameters requestParams, MsalTokenResponse response)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.SaveTokenResponseToCache()
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.PostTokenRequest()
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__35.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Identity.Client.PublicClientApplication.<AcquireTokenForLoginHintCommonAsync>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Identity.Client.PublicClientApplication.<AcquireTokenAsync>d__14.MoveNext()

I've tried this with two different MSAs (an outlook.com email address and a private domain email address) and both have the same problem.

Additional context/ Logs / Screenshots
Another issue: when upgrading from 1.1.4-preview0002, the previously signed-in user is no longer available in PublicClientApplication.GetAccountsAsync(). This is annoying because apps using your library will need to ask their users to sign in again. Please migrate data from previous versions.

Also: having the name of the user on IUser was useful. What is the equivalent on IAccount?

Thanks.

P0 bug

All 16 comments

Thanks for the feedback.

The content of the cache is not kept when upgrading from MSAL 1.1.4-preview to MSAL 2.0.0, but MSAL.2.0.0 does migrate the cache from ADAL (where most production apps are). Sorry for the inconvenience
There are breaking changes in MSAL.Net 2.0.0 which are explained in https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/msal-net-2-released. If you use Visual Studio, you should have warning helping you migrating,

Note that the name of the user is now available from IAccount.Username.
Otherwise you have even richer information by calling the Microsoft Graph Me endpoint for the user

Thanks for your reply!

That's unfortunate about upgrades from previous releases of MSAL.

Because of the COMException I never managed to obtain a working instance of IAccount. Hopefully it'll have what I need.

Any ideas on the exception?

thanks for the update @mfeingol
We are going to look at the exception

@jennyf19 - this looks similar to the bug you just fixed where the dictionary key already exists - is it the same dictionary ?

Microsoft.Identity.Core.Telemetry.TelemetryTokenCacheAccessor.SaveAccessToken(MsalAccessTokenCacheItem item, RequestContext requestContext)

@mfeingol :for the COM exception, do you want to check if MSAL.NET 2.0.1 fixes it?

@jmprieur: still seeing the same exception with 2.0.1-preview:

System.Runtime.InteropServices.COMException (0x80073DC9)

The length of the state manager setting name has exceeded the limit.

Error trying to write application data container value

   at System.Runtime.InteropServices.WindowsRuntime.IMap`2.Insert(K key, V value)
   at System.Runtime.InteropServices.WindowsRuntime.MapToDictionaryAdapter.Insert[K,V](IMap`2 _this, K key, V value)
   at System.Runtime.InteropServices.WindowsRuntime.MapToDictionaryAdapter.Indexer_Set[K,V](K key, V value)
   at Microsoft.Identity.Core.Telemetry.TelemetryTokenCacheAccessor.SaveAccessToken(MsalAccessTokenCacheItem item, RequestContext requestContext)
   at Microsoft.Identity.Client.TokenCache.SaveAccessAndRefreshToken(AuthenticationRequestParameters requestParams, MsalTokenResponse response)
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.SaveTokenResponseToCache()
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.PostTokenRequest()
   at Microsoft.Identity.Client.Internal.Requests.RequestBase.<RunAsync>d__35.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Identity.Client.PublicClientApplication.<AcquireTokenForLoginHintCommonAsync>d__22.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.Identity.Client.PublicClientApplication.<AcquireTokenAsync>d__14.MoveNext()

I have the exact same problem.

Any update about this issue?

The same issue here too.

HI @sergioacortes @emulic - we'll look at this as soon as possible, apologies for the delay.

Looking at this now. The stack trace and the error message point out at an issue when storing the ATs. On UWP the library stores the tokens using the platform ApplicationData storage. I think in your case we're hitting a storage limit. Investigating further...

https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/blob/dev/core/src/Platforms/uap/TokenCacheAccessor.cs#L76

Ok, I now understand this problem and I can repro it. The repro steps are:

  1. Create a UWP app and configure it to perform auth with MSAL 2.x
  2. Configure it to perform an interactive token request and ask for several scopes - not just a few, e.g.

    "User.Read", "Files.ReadWrite.AppFolder", "Files.Read.All", "Calendars.Read", "Calendars.Read.Shared"

  3. Run the app and login when the browser requests you to

Actual: app crashes

Root cause: we get a token back fine, but when storing it to the token cache we

The root cause is that on UWP we're hitting a storage limitation when trying to store the AT. In 2.x we have changed the cache data schema and the storage key is a concatenation of :

  • HomeAccountId (2 guids)
  • Enviromnent (ussually "login.windows.net")
  • "accesstoken"
  • ClientId (Guid)
  • TenantId (Guid)
  • * Scopes * (user configurable, can be arbitrarily long)

According to this SO question, the key should be 255 chars or less. In our case, when using several scopes, the key exceeds 255.

Investigating how to fix this... Any suggestion welcome.

We have a fix and expect to hot fix this issue soon.

Not only scopes, any native or custom directory attribute added to the token might also increment the size.
Actually, I did hit with this error in previous versions, as I brought many custom directory attributes in the token; I didn't went though much thinking, but noticed that reducing the amount of custom attributes in the token to about 2, "made the error disappear", further than that ... boom.
Good you found the cause and fix is coming.

Actually we use a UWP platform dictionary to store both key and values. A access token key is just an identifier and does not hold the actual token. The dictionary value does...

@aespino27 @mfeingol @henriko2018 @sergioacortes @emulic

This has been fixed in MSAL v2.2.0-preview

Please re-open this issue if necessary.

Was this page helpful?
0 / 5 - 0 ratings