c# - MSAL.NET 中的 token 缓存序列化不起作用

标签 c# .net azure-active-directory msal adal

尝试序列化从使用 MSAL 进行身份验证返回的 token 缓存时,我遇到了一些问题。
我会很感激任何帮助,因为我真的不明白我做错了什么。
这是我们的情况/问题:
我们目前使用 ADAL 允许用户从我们的桌面应用程序对其 SharePoint Online 帐户进行身份验证,但希望切换到 MSAL。
我们已经实现了两种可能的身份验证流程。一个 publicClientApplication,允许用户使用其当前事件的 Microsoft 凭据和一个 ConfidentialClientApplication 进行身份验证,它允许使用证书进行身份验证,如下面代码的 catch block 所示:

                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();
                    }
                } 
到目前为止,代码工作正常,初始身份验证在两种情况下都成功。
现在的问题是我们希望保留获得的 token ,以便用户下次启动我们的程序并尝试访问 SharePoint 时不必再次进行身份验证。但是尝试使用先前存储的 token 进行静默身份验证是行不通的,无论是对于公共(public)应用程序还是 secret 应用程序。
然而,AfterAccessNotification 的序列化似乎确实有效,因为至少有一些东西被写入缓存文件。但是读回这些数据却没有。需要指出的一件事是 GetAccountsAsync() 将始终返回 0。
到目前为止,我从 Microsoft 文档和此处的其他问题中读到的是,应用程序的内存缓存在重新创建时当然会丢失,解决方案似乎是 TokenCacheHelper 的实现。我们的帮助类是按照文档中的建议实现的:
    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)
                                        );
                }
            }
        }

    }
我对使用 TokenCacheHelper 或这里的其他东西有重大误解吗?
或者有没有更简单的方法来持久化 token 缓存?
使用 ADAL 似乎要简单得多。
非常感谢您的帮助。

最佳答案

我们找出了导致问题的原因。只需调用 TokenCacheHelper.EnableSerialization(m_authContext.UserTokenCache);在尝试获取 token 之前丢失。

关于c# - MSAL.NET 中的 token 缓存序列化不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68395034/

相关文章:

c# - 以编程方式获取 C# 堆栈跟踪

c# - 实现 BindingList<T>

c# - 使用 CanUserAddRows 为 DataGrid 的新行设置样式

.net - Control.ResolveUrl 与 Control.ResolveClientUrl 与 VirtualPathUtility.ToAbsolute

azure - 如何从 VSCode Azure Functions 扩展登录我的 Azure 帐户?

c# - 如何从 Apache NMS ActiveMQ 消息中获取底层流句柄

c# - 打开包含附件的默认邮件管理器 (Windows)

C# - 如果用户在插入记录后刷新页面,则会创建重复记录。我怎样才能防止这种情况发生?

ASP.net Core 2.0 AzureAd Bearer JWT-Token Auth 在验证签名时不会失败

Azure Ad B2C 用户访问其他目录中的资源