Me enfrento a algunos problemas al intentar serializar el tokencache, devuelto de la autenticación con MSAL. Agradecería cualquier ayuda, ya que realmente no entiendo lo que estoy haciendo mal. Aquí está nuestra situación/problema:
Actualmente usamos ADAL para permitir que los usuarios se autentiquen en sus cuentas de SharePoint Online desde nuestra aplicación de escritorio, pero queremos cambiar a MSAL.
Hemos implementado dos posibles flujos de autenticación. Una publicClientApplication, para permitir que el usuario se autentique con sus credenciales de Microsoft actualmente activas y una ConfidentialClientApplication, que permite autenticarse con el uso de un certificado, como puede ver en el bloque catch del código a continuación:
try { Debugger.Launch(); if (certificate != null) { IConfidentialClientApplication m_authContext = ConfidentialClientApplicationBuilder.Create(pClientID) .WithTenantId(m_tenant).WithCertificate(certificate).WithRedirectUri(pClientRedirectURI).Build(); var accounts = await m_authContext.GetAccountsAsync(); authResult = await m_authContext.AcquireTokenSilent(m_scope, accounts.FirstOrDefault()).ExecuteAsync(); } else { IPublicClientApplication m_authContext = PublicClientApplicationBuilder.Create(pClientID).WithTenantId(m_tenant).WithRedirectUri(pClientRedirectURI).Build(); var accounts = await m_authContext.GetAccountsAsync(); authResult = await m_authContext.AcquireTokenSilent(m_scope, accounts.FirstOrDefault()).ExecuteAsync(); } } catch { if (certificate != null) { IConfidentialClientApplication m_authContext = ConfidentialClientApplicationBuilder.Create(pClientID) .WithTenantId(m_tenant).WithCertificate(certificate).WithRedirectUri(pClientRedirectURI).Build(); TokenCacheHelper.EnableSerialization(m_authContext.AppTokenCache); authResult = await m_authContext.AcquireTokenForClient(m_scope).WithForceRefresh(true).ExecuteAsync(); } else { IPublicClientApplication m_authContext = PublicClientApplicationBuilder.Create(pClientID) .WithTenantId(m_tenant).WithRedirectUri(pClientRedirectURI).Build(); TokenCacheHelper.EnableSerialization(m_authContext.UserTokenCache); authResult = await m_authContext.AcquireTokenInteractive(m_scope).ExecuteAsync(); } }Hasta ahora, el código funciona bien y la autenticación inicial es exitosa en ambos casos. El problema ahora es que nos gustaría conservar los tokens adquiridos, para que la próxima vez que el usuario inicie nuestro programa e intente acceder a SharePoint no tenga que autenticarse nuevamente. Pero tratar de autenticar en silencio con el uso de un token almacenado previamente no funciona, ni para la aplicación pública ni para la confidencial. Sin embargo, la serialización de AfterAccessNotification parece funcionar, ya que al menos algo se escribe en el archivo de caché. Pero la lectura de estos datos no lo hace. Una cosa a señalar es que GetAccountsAsync() siempre devolverá 0.
Lo que he leído hasta ahora, de la documentación de Microsoft y otras preguntas aquí, es que, por supuesto, el caché en memoria de las aplicaciones se perderá al recrearlo y la solución parece ser la implementación de TokenCacheHelper. Nuestra clase auxiliar se implementa como se sugiere en la documentación:
static class TokenCacheHelper { public static readonly string CacheFilePath = System.Reflection.Assembly.GetExecutingAssembly().Location + "msalcache.txt"; private static readonly object FileLock = new object(); public static void EnableSerialization(ITokenCache tokenCache) { Debugger.Launch(); tokenCache.SetBeforeAccess(BeforeAccessNotification); tokenCache.SetAfterAccess(AfterAccessNotification); } private static void BeforeAccessNotification(TokenCacheNotificationArgs args) { args.TokenCache.DeserializeMsalV3(File.Exists(CacheFilePath) ? ProtectedData.Unprotect(File.ReadAllBytes(CacheFilePath), null, DataProtectionScope.CurrentUser) : null); } private static void AfterAccessNotification(TokenCacheNotificationArgs args) { Debugger.Launch(); if (args.HasStateChanged) { lock (FileLock) { // reflect changesgs in the persistent store File.WriteAllBytes(CacheFilePath, ProtectedData.Protect(args.TokenCache.SerializeMsalV3(), null, DataProtectionScope.CurrentUser) ); } } } }¿Tengo un gran malentendido sobre el uso de TokenCacheHelper o algo más aquí? ¿O hay una manera más simple de conservar el tokencache? Esto parecía ser mucho menos complicado con el uso de ADAL.
Muchas gracias por su ayuda.
No hay forma más sencilla. Estoy usando esta clase provista por Mircosoft (TokenCacheHelper) y funciona muy bien. Estoy persistiendo el token ahora durante varias semanas. No hay problemas para leerlo y usarlo. En general, hasta donde lo probé, primero debe autenticarse de forma interactiva para muchos tipos de datos que desea leer y luego leer el token guardado para acciones futuras. Puede comprobar en su centro de seguridad de Azure qué datos ha autenticado de forma interactiva o puede autenticar de forma no interactiva.
¡Pruébalo!
PD: Consideraría toda la biblioteca de MS-graph en un "estado beta" y todavía con errores, propensa a errores y no terminada. Así que espere un comportamiento diferente ahora y en el futuro.
Saludos
Descubrimos qué estaba causando el problema. Simplemente hubo una llamada de TokenCacheHelper.EnableSerialization(m_authContext.UserTokenCache); falta antes de intentar adquirir el token silencioso.