为啥我的受 AAD 保护的 Azure 函数在使用来自 UWP 应用的访问令牌调用时返回 401?

Posted

技术标签:

【中文标题】为啥我的受 AAD 保护的 Azure 函数在使用来自 UWP 应用的访问令牌调用时返回 401?【英文标题】:Why does my AAD-protected Azure Function returns 401 when invoked with an access token from a UWP app?为什么我的受 AAD 保护的 Azure 函数在使用来自 UWP 应用的访问令牌调用时返回 401? 【发布时间】:2021-07-03 04:06:19 【问题描述】:

我已经阅读并尝试了this、this 和许多其他资源,但均未成功。

我有一个 UWP 应用,它调用受 AAD 保护的 HTTP 触发的 Azure 函数。我在 Azure 门户的 AAD 部分创建了两个应用注册。 API 应用程序注册指定了一个范围,并具有一个应用程序 ID URI api://5e6b2b53-...。在“身份验证”刀片上,我将 https://login.microsoftonline.com/common/oauth2/nativeclient 设置为重定向 URI。我已经设置了和UWP应用注册的redirect 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 Function 页面上,我设置了:

发行者 URL 由我的 Azure 租户 ID 组成,如 here 所述:

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

【问题讨论】:

我认为错误可能来自暴露的api。当我添加身份验证时,我的公开 api 会自动生成。 “自动生成”是什么意思? 我的意思是 azure 广告应用中的设置,包括“添加客户端密码”、“公开 api” 【参考方案1】:

我发现从

更改颁发者 URL(在 Azure 函数应用注册中指定)
https://login.microsoftonline.com/[tenant ID]

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

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

【讨论】:

【参考方案2】:

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

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

然后我关注this doc,通过 azure ad 启用身份验证。这意味着我创建了一个新的天蓝色广告应用程序,公开一个这样的 api。

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

【讨论】:

为什么要硬编码访问令牌?它来自哪里? 我写了一个demo,所以我从邮递员那里生成访问令牌,您在代码中生成访问令牌时遇到麻烦吗? 我找到了解决方案;我提供了它作为这个 SO question 的答案。 感谢您的回复先生,并祝贺您。我还尝试在“Express”中添加身份验证(经典),但没有在“Advance”中添加,所以我没有像你那样做那么多配置。无论如何,这很好:) 感谢您的宝贵时间。

以上是关于为啥我的受 AAD 保护的 Azure 函数在使用来自 UWP 应用的访问令牌调用时返回 401?的主要内容,如果未能解决你的问题,请参考以下文章

从 PowerApp(或逻辑应用)调用受 AAD 保护的 Azure 函数

C++:为啥我的 DerivedClass 的构造函数无法访问 BaseClass 的受保护字段?

为啥我无法在 Azure 门户中访问我的 AAD 应用注册,但我可以使用 Azure CLI 查看它?

401 Unauthorized while access azure function with bearer token |功能应用受 AAD 保护

在 AAD 保护的 Azure Web 应用程序中检索访问令牌

为啥不能将继承的受保护构造函数公开?