Tob*_*obi 5 c# single-sign-on azure-active-directory azure-ad-graph-api azure-ad-msal
我正在开发一个小 WPF 应用程序,该应用程序应该从 MS Graph API 查询一些数据。我想使用 SSO,这样用户就不必单独登录应用程序。
该应用程序在加入 Azure AD 的设备上运行。该用户是AADC同步的AD用户。AAD 租户与 ADFS 联合。用户使用 Hello for Business (PIN) 或密码进行身份验证。由此产生的问题是相同的。
我可以确认用户通过以下方式获得了 PRT:
dsregcmd /status
AzureAdPrt: YES
Run Code Online (Sandbox Code Playgroud)
如果重要的话:Azure AD 中的应用程序注册设置为“将应用程序视为公共客户端”。并配置以下重定向 URI:
根据我找到的示例,我使用以下代码来尝试获取访问令牌。但是该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;
}
}
Run Code Online (Sandbox Code Playgroud)
为了能够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();
}
Run Code Online (Sandbox Code Playgroud)
使用这个try/catch模式而不是if/else逻辑,你就可以开始了。
为了进一步参考,有这个msal 桌面示例,其中涵盖了许多常见场景。
如果您在每个操作上实例化一个新的 _msalClient,那么这就解释了为什么其他调用不起作用。您可以将 _msalClient 作为静态/单例实例,也可以实现序列化令牌缓存。这是一个缓存示例
| 归档时间: |
|
| 查看次数: |
15005 次 |
| 最近记录: |