C# 为什么我的AAD保护Azure函数在使用UWP应用程序的访问令牌调用时返回401?

C# 为什么我的AAD保护Azure函数在使用UWP应用程序的访问令牌调用时返回401?,c#,azure,authentication,azure-active-directory,azure-functions,C#,Azure,Authentication,Azure Active Directory,Azure Functions,我已经阅读并尝试了很多其他资源,但都没有成功 我有一个UWP应用程序,它调用受AAD保护的HTTP触发Azure函数。我在Azure门户的AAD部分创建了两个应用程序注册。API应用程序注册指定了一个作用域,并且应用程序ID URI为api://5e6b2b53-...。在“身份验证”刀片上,我设置https://login.microsoftonline.com/common/oauth2/nativeclient作为重定向URI。我已经设置了与UWP应用程序注册的重定向URI相同的值(我不知

我已经阅读并尝试了很多其他资源,但都没有成功

我有一个UWP应用程序,它调用受AAD保护的HTTP触发Azure函数。我在Azure门户的AAD部分创建了两个应用程序注册。API应用程序注册指定了一个作用域,并且应用程序ID URI为
api://5e6b2b53-...
。在“身份验证”刀片上,我设置
https://login.microsoftonline.com/common/oauth2/nativeclient
作为重定向URI。我已经设置了与UWP应用程序注册的重定向URI相同的值(我不知道是否正确)。我还设定:

在功能应用程序注册。我还为函数应用程序注册设置了以下重定向URI,但我不知道是否需要:

UWP应用程序注册使用我在功能应用程序注册中定义的正确范围。两个应用程序注册都是多租户的。我在UWP应用程序上用于调用受保护Azure函数的代码是:

namespace ClientApplication
{
    public partial class MainPage
    {
        private readonly HttpClient _httpClient;
        private const string ClientId     = "..."; // Client ID of the UWP app registration
        private const string Tenant       = "..."; // My Azure tenant ID 
        private const string Authority    = "https://login.microsoftonline.com/" + Tenant;
        private readonly string[] _scopes = { "api://5e6b2b53-.../user_impersonation2" };


        public MainPage()
        {
            _httpClient = new HttpClient();
            BindingContext = this;
            InitializeComponent();
        }


        private async void Button_OnClicked(object sender, EventArgs e)
        {
            var app = PublicClientApplicationBuilder.Create(ClientId)
                .WithAuthority(Authority)
                .WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
                .WithLogging((level, message, containsPii) =>
                {
                    Debug.WriteLine($"MSAL: {level} {message} ");
                }, LogLevel.Warning, false, true)
                .Build();

            AuthenticationResult result;
            var accounts = await app.GetAccountsAsync();

            try
            {
                result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
            }
            catch (MsalUiRequiredException)
            {
                try
                {
                    result = await app.AcquireTokenInteractive(_scopes).ExecuteAsync();
                }
                catch (Exception exception)
                {
                    Console.WriteLine(exception);
                    throw;
                }
            }

            if (result == null) return;

            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
            var response = _httpClient.GetAsync("URL of my HTTP-triggered Azure Function").Result;
            var jsonResponseContent = await response.Content.ReadAsStringAsync();
        }
    }
}
在Azure功能页面上,我设置:

其中,发卡机构URL由我的Azure租户ID组成,如下所述:

你能帮我理解为什么我用从身份提供者那里获得的访问令牌调用Azure函数时会得到401吗?这是我获得的访问令牌的重要部分


我做了一些测试,希望能有所帮助,如果我在某些地方误解了,请指出

首先,当我调用
GET时,我创建了一个http触发器函数https://xxx.azurewebsites.net/api/HttpTrigger1?name=asdfg
,我会得到类似于
你好asdfg
的响应

然后我通过azure ad启用了身份验证。这意味着我创建了一个新的azure ad应用程序,公开了一个类似这样的api。

在这一步之后,当我调用GET请求时,它会要求我登录,然后我可以得到相同的响应。接下来,我创建了另一个azure ad应用程序,并添加了我刚才公开的api的api权限,通过该应用程序,我可以生成该api范围内的访问令牌,并且通过授权请求头中的该访问令牌,我可以直接访问GET请求


我发现从

https://login.microsoftonline.com/[租户ID]

https://login.microsoftonline.com/[租户ID]/v2.0

解决了这个问题。我仍然不明白为什么它不起作用,因为文档说省略了
/v2.0

,我想可能是由于暴露的api导致的错误。我的公开api是在我添加身份验证时自动生成的。你说的“自动生成”是什么意思?我指的是azure ad app中的设置,包括“添加客户端机密”、“公开api”为什么要硬编码访问令牌?它来自哪里?我写了一个演示,所以我从postman生成了访问toke,你在代码中生成访问令牌有困难吗?我找到了解决方案;我提供它作为对这个问题的回答。谢谢你的回答,先生,祝贺你。我还尝试在“Express”中添加身份验证(经典),但没有在“Advance”中添加身份验证,因此我没有像您这样做过很多配置。不管怎样,很好:)谢谢你抽出时间。