c# - MSAL - PublicClientApplication - GetAccountsAsync() 不返回任何帐户

标签 c# azure-active-directory single-sign-on azure-ad-graph-api msal

我正在开发一个小 WPF 应用程序,它应该从 MS Graph API 查询一些数据。我想使用 SSO,所以用户不必单独登录应用程序。

该应用在已加入 Azure AD 的设备上运行。用户是 AADC 同步 AD 用户。 AAD 租户与 ADFS 联合。用户使用 Hello for Business (PIN) 或密码进行身份验证。产生的问题是一样的。

我可以确认用户通过以下方式获得了 PRT:

dsregcmd /status

AzureAdPrt: YES

以防万一:Azure AD 中的应用注册设置为“将应用程序视为公共(public)客户端”。并且配置了以下重定向 URI:
  • https://login.microsoftonline.com/common/oauth2/nativeclient
  • https://login.live.com/oauth20_desktop.srf
  • msalxxxxxxx(appId)://auth
  • 骨灰盒:ietf:wg:oauth:2.0:oob

  • 根据我找到的示例,我正在使用以下代码尝试获取访问 token 。然而 GetAccountsAsync()方法不返回任何用户,也不抛出任何错误或异常。

    谁能告诉我,我在这里缺少什么?

    任何帮助将非常感激!

    PS:当我使用“交互式身份验证”尝试此操作时,它工作正常。
    public GraphAuthProvider(string appId, string tenantId, string[] scopes)
    {
        _scopes = scopes;
    
        try
        {
            _msalClient = PublicClientApplicationBuilder
                    .Create(appId)
                    .WithAuthority(AadAuthorityAudience.AzureAdMyOrg, true)
                    .WithTenantId(tenantId)
                    .Build();
        }
        catch (Exception exception)
        {
            _log.Error(exception.Message);
            _log.Error(exception.StackTrace);
            throw;
        }
    }
    
    public async Task<string> GetAccessToken()
    {
        _log.Info("Starting 'GetAccessToken'...");
        var accounts = await _msalClient.GetAccountsAsync();
        _userAccount = accounts.FirstOrDefault();
    
    
        // If there is no saved user account, the user must sign-in
        if (_userAccount == null)
        {
            _log.Info("No cached accounts found. Trying integrated authentication...");
            [...]
        }
        else
        {
            // If there is an account, call AcquireTokenSilent
            // By doing this, MSAL will refresh the token automatically if
            // it is expired. Otherwise it returns the cached token.
    
            var userAccountJson = await Task.Factory.StartNew(() => JsonConvert.SerializeObject(_userAccount));
            _log.Info($"Found cached accounts. _userAccount is: {userAccountJson}");
    
            var result = await _msalClient
                .AcquireTokenSilent(_scopes, _userAccount)
                .ExecuteAsync();
    
            return result.AccessToken;
        }
    }
    

    最佳答案

    能够拥有IAccounts从 MSAL(访问缓存)返回,它必须在某个时候引导缓存。您缺少起点,在您的情况下是 AcquireTokenInteractive .

    建议在 MSAL 上使用以下 try/catch 模式:

    try
    {
        var accounts = await _msalClient.GetAccountsAsync();
    
        // Try to acquire an access token from the cache. If an interaction is required, MsalUiRequiredException will be thrown.
        result = await _msalClient.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
                    .ExecuteAsync();
    }
    catch (MsalUiRequiredException)
    {
        // Acquiring an access token interactively. MSAL will cache it so you can use AcquireTokenSilent on future calls.
        result = await _msalClient.AcquireTokenInteractive(scopes)
                    .ExecuteAsync();
    }
    
    

    使用这个 try/catch 模式而不是你的 if/else 逻辑,你会很高兴。

    为了进一步引用,有这个msal desktop samples其中涵盖了一系列常见场景。

    更新

    如果您在每个操作上都实例化一个新的 _msalClient,那么这就解释了为什么其他调用不起作用。您可以将 _msalClient 作为静态/单例实例,也可以实现序列化 token 缓存。 Here is a cache example

    关于c# - MSAL - PublicClientApplication - GetAccountsAsync() 不返回任何帐户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62210738/

    相关文章:

    javascript - 从外部网站验证 Moodle 用户

    javascript - 从应用程序授予对共享邮箱的访问权限

    java - 使用 SPNEGO Web SSO 自动登录

    c# - 如何避免重复代码?

    c# - 列表属性 setter

    azure - Azure AD B2C 中的身份提供程序菜单未显示

    适用于 UWP 的 Azure AD B2C 需要 API 范围,但我没有

    single-sign-on - SAML 2.0,单点注销问题

    c# - 在 akka.net 中立即触发多个线程

    c# - 城堡 ActiveRecord 3 : ActiveRecordLinq queries using Equals not work