我有一个应用程序,需要访问一个自定义的API以及通过图形API发送电子邮件的能力。当我获得访问令牌时,我似乎只能传递图形或api作用域,但不能同时传递两者。
我创建我的应用程序如下
_clientApp = PublicClientApplicationBuilder.Create(ClientId)
.WithAuthority(AzureCloudInstance.AzurePublic, Tenant)
.Build();然后我按如下方式进行身份验证
private async Task<AuthenticationResult> AuthenticateAsync(string[] scopes)
{
string error = String.Empty;
AuthenticationResult authResult = null;
var accounts = await _clientApp.GetAccountsAsync();
var firstAccount = accounts.FirstOrDefault();
try
{
authResult = await _clientApp.AcquireTokenSilent(scopes, firstAccount).ExecuteAsync();
}
catch (MsalUiRequiredException ex)
{
// A MsalUiRequiredException happened on AcquireTokenSilent.
// This indicates you need to call AcquireTokenInteractive to acquire a token
System.Diagnostics.Debug.WriteLine($"MsalUiRequiredException: {ex.Message}");
try
{
authResult = await _clientApp.AcquireTokenInteractive(scopes)
.WithAccount(accounts.FirstOrDefault())
.WithPrompt(Prompt.SelectAccount)
.ExecuteAsync();
}
catch (MsalException msalex)
{
error += $"Error Acquiring Token:{System.Environment.NewLine}{msalex}" + Environment.NewLine;
}
}
catch (Exception ex)
{
error += $"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}" + Environment.NewLine;
}
if (string.IsNullOrEmpty(error))
return authResult;
else
throw new AuthenticationException(error);
}如果我通过作用域
string[] graphsScopes = new string[] { "user.read" };我可以成功发送电子邮件,但我无法调用我的customAPI,如果我通过作用域
string[] customScopes = new string[] { "api://<MyApiId>/<MyScopeName>" };我可以调用我的自定义API,但无法发送电子邮件。
如果我尝试同时添加两个,我只会在AuthenticationResult中获得作用域数组中最先出现的那个的作用域。
如果我对AuthenticateAsync进行两次调用,每个作用域一个,并使用为它们各自的api调用检索到的两个单独的AccessTokens,并发送一封电子邮件,这一切都可以工作,但我不确定为什么我需要在我的应用程序中管理两个不同的访问令牌,以访问azure门户中的一个注册应用程序。
我发现了这个Multiple resources in a single authorization request问题,其中提到不能混合来自microsoft graph和outlook.office 365.com的作用域,但没有说明为什么或是否同样适用于混合customAPI作用域和图形作用域
发布于 2019-12-10 17:52:24
在静默获取tokens时,至少需要调用两次AcquireToken。这是因为访问令牌只对一个API有效,该API由令牌中的aud (aud)声明命名。因此,要调用两个API,您需要两个不同的访问令牌。
以前在交互式身份验证时为两个不同的API指定作用域时会出现问题,但IIRC现在应该可以工作了。您应该能够使用获得的刷新令牌来获取不同API的令牌。或者更准确地说,在交互调用之后,您应该能够静默地获取另一个API的令牌。
https://stackoverflow.com/questions/59264331
复制相似问题