为啥我的受 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 保护