Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在单个IPublicClientApplication.AcquireTokenSilent调用中混合图形和customAPI作用域_C#_Azure Active Directory_Azure Ad Graph Api - Fatal编程技术网

C# 在单个IPublicClientApplication.AcquireTokenSilent调用中混合图形和customAPI作用域

C# 在单个IPublicClientApplication.AcquireTokenSilent调用中混合图形和customAPI作用域,c#,azure-active-directory,azure-ad-graph-api,C#,Azure Active Directory,Azure Ad Graph Api,我有一个应用程序,它需要访问自定义API以及通过Graphs API发送电子邮件的能力。 当我获得我的访问令牌时,我似乎只能传递图形或api作用域,而不能同时传递这两者 我创建我的应用程序如下 _clientApp = PublicClientApplicationBuilder.Create(ClientId) .WithAuthority(AzureCloudInstance.AzurePublic, Tenant) .Build(); pr

我有一个应用程序,它需要访问自定义API以及通过Graphs 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);
    }
然后,我进行如下验证

_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);
    }
我可以成功发送电子邮件,但如果我通过范围,我无法调用我的customAPI

string[] customScopes = new string[] { "api://<MyApiId>/<MyScopeName>" };
string[]customScopes=新字符串[]{“api://”};
我可以调用自定义API,但不能发送电子邮件

如果我尝试同时添加这两个,我只会在AuthenticationResult中获取作用域数组中最先出现的作用域

如果我对AuthenticateTasync进行两次调用,每个作用域调用一次,并使用为各自对我的api的调用而检索的两个单独的AccessToken并发送电子邮件,这一切都会起作用,但我不确定为什么我需要在我的应用程序中管理两个不同的AccessToken,以便在azure门户中注册一个应用程序


我发现了这个问题,其中提到无法混合来自microsoft graph和outlook.office365.com的作用域,但没有说明为什么或是否同样适用于混合customAPI作用域和graph作用域

当以静默方式获取令牌时,至少需要调用AcquireToken两次。 这是因为访问令牌仅对一个API有效, 由令牌中的观众(aud)声明命名。 因此,要调用两个API,需要两个不同的访问令牌

在交互身份验证时,为两个不同的API指定作用域曾经存在问题,但IIRC现在应该可以工作了。 您应该能够使用获得的刷新令牌来获取不同API的令牌。
或者更准确地说,您应该能够在交互调用后以静默方式获取另一个API的令牌。

是的,它确实以静默方式获取第二个令牌,但我不明白为什么我需要两个令牌,而我需要的两个API权限都列在同一个应用程序中。你有没有可能理解这是什么原因,我认为这是一个限制?一个应用程序需要它们,但你调用两个API,因此需要两个访问令牌。正如我所说,一个访问令牌只对一个API有效,并且您正在调用两个API。我认为这其中有一个方面我不是百分之百地理解,但至少我知道这是做这件事的必要方式,我没有不必要地使事情复杂化。非常感谢你的邀请help@russelrillema考虑一个调用多个API的应用程序。应用程序可能被授权代表用户调用所有API(例如,用户已同意),但每个API尚未被授权调用其他API。单独的访问令牌(每一个都标识它的目标API)确保一个API使用的访问令牌不能被该API重新用于调用另一个API。(续…)(…)如果(且仅当)一个API被授权代表用户调用另一个API,则可用于将第一个API收到的访问令牌交换为新的访问令牌,该访问令牌现在用于第二个API。