我在C#中有一个非常简单的Azure函数,为此我设置了Azure AD Auth。我刚刚使用Express设置在Function配置中创建了App注册。
public static class IsAuthenticated
{
[FunctionName("IsAuthenticated")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "options", Route = null)]
HttpRequest req,
ILogger log)
{
return new OkObjectResult("You are " + req.HttpContext.User.Identity.Name);
}
}
当我在浏览器中访问该功能时,所有功能均按预期工作(如果未登录,则必须登录并重定向到我的API)。但是,如果我尝试在需要Bearer令牌的任何地方访问函数,则会出现401 Unauthorized
错误。即使很奇怪,我也无法在Azure门户中执行该功能。
但是毫无疑问地获得了令牌,并将其添加到请求中:
我已经尝试了一些其他方法来解决此问题。首先,我认为这可能是CORS问题(因为我也有其中一些问题),只是将CORS设置为接受*,但没有任何变化。
然后,我已将我的API登录端点添加到重定向中,并尝试将隐式授予设置为也接受Access令牌,但仍无法正常工作。
有什么我忽略的东西吗? App Registration Express配置不应该只与Azure函数一起使用吗?
编辑:
按照@thomas-schreiter的建议在重定向中将URL放入我的函数应用程序并没有改变任何东西(我已经尝试了屏幕截图中的配置,还只是将每个值都放在了自己的位置上。) / p>
编辑2:
我现在也尝试通过手动方式with Postman获取Bearer令牌,但是在调用API时仍然遇到401。
答案 0 :(得分:7)
这花了很长时间才弄清楚,而且官方文档中对此的信息很少。
但是事实证明,问题是/是Azure函数不支持由oauth2 / v2.0 / Azure API生成的Bearer令牌。由于门户网站使用了这些功能(如果您的广告支持它们的话),因此您很幸运能够在其中运行该功能。
这也解释了为什么我的邮递员请求不起作用,因为我也在使用v2 API。切换到v1后,我可以访问我的API(在使用集成身份验证功能时,邮差不允许您添加resource_id,因此我不得不切换为手动处理所有内容)。
此后,意识到您正在编写JS客户端(在我的情况下为Angular)也不能使用MSAL。因此,可以选择ADAL,其中Angular实现看起来有些尴尬。因此,我决定使用angular-oauth2-oidc,这花了一个小时的时间才能使它与Azure AD很好地配合使用。
但是毕竟,我终于可以访问我的API。
我真的不明白为什么您不允许用户使用Azure AD v2令牌访问Azure Function应用程序,但是至少应该对此进行更好地记录。但是无论如何,我终于可以入睡了。
编辑:在我为此打开一个问题之后,他们添加了一条说明,即Azure Functions不支持v2,希望使其他人的生活更轻松。
https://docs.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad
答案 1 :(得分:5)
我设法使用以下配置使它通过邮递员工作。 重要的一课是在“允许的令牌受众”中进行设置,在这种情况下,邮递员用于获取令牌的“资源”名称应相同。我使用了此处提供的相同代码。在这种情况下,在Azure AD中注册的应用程序也是客户端和资源。通过邮递员进行配置和测试,如下所示
在邮递员中获取令牌
使用邮递员..具有承载令牌的授权标头调用azure函数
答案 2 :(得分:2)
您现在可以使用v2.0令牌!
在配置AAD时,不必选择“快速”,而必须选择“高级”并在URL末尾添加/v2.0部分。
这是我在控制台应用程序中使用的代码,用于向用户显示登录提示,然后获取承载令牌以与Azure函数一起使用。
string[] scopes = new string[] { "profile", "email", "openid" };
string ClientId = [clientId of Azure Function];
string Tenant = [tenantId];
string Instance = "https://login.microsoftonline.com/";
var _clientApp = PublicClientApplicationBuilder.Create(ClientId)
.WithAuthority($"{Instance}{Tenant}")
.WithDefaultRedirectUri()
.Build();
var accounts = _clientApp.GetAccountsAsync().Result;
var authResult = _clientApp.AcquireTokenInteractive(scopes)
.WithAccount(accounts.FirstOrDefault())
.WithPrompt(Prompt.SelectAccount)
.ExecuteAsync().Result;
var bearerTokenForAzureFunction = authResult.IdToken;
答案 3 :(得分:2)
在Function App上设置Active Directory身份验证时,请将管理模式设置为高级,并根据需要填写客户端ID和颁发者URL(如果需要,还可以填写客户端密码)。
重要的是,在允许令牌受众下,输入应用程序ID URI 。可以在公开API 选项下的已注册应用程序注册(在广告中)中找到。
这是我无法在Function App上进行身份验证的原因。在添加该令牌受众之前,我总是会得到一个带有有效访问令牌的401。
这个Azure active directory - Allow token audiences帮助我得到了答案,但是花了我一段时间才意识到它指的是什么。请记住,可以在您的应用程序注册中找到应用程序ID URI。
希望对您有帮助!
答案 4 :(得分:2)
如果你像我和原始海报一样用头撞墙,可能是你允许用户从“任何组织目录中的帐户(任何 Azure AD 目录 - 多租户)和个人 Microsoft 帐户(例如Skype、Xbox)。”
请注意,截至 2021 年 5 月,v2.0 可以完美运行。如果您使用 https://login.microsoftonline.com/TENANT_ID/oauth2/v2.0/token 通过 Postman 获取令牌(如上所述),您将获得一个有效令牌,您可以使用该令牌对您的 AZ 函数进行身份验证。
话虽如此,如果用户通过个人帐户或不在您的 AAD 中的帐户登录,MSAL 发出的令牌调用将使用默认的 Microsoft 租户 ID 请求,而不是您的租户身份证。
这就是我无法验证我的函数的原因。如果您使用租户的 AAD 中的用户登录,MSAL 非常棒且易于使用,一切都将按照文档中的描述工作。
答案 5 :(得分:1)
在AAD应用程序本身中,转到“设置”->“答复URL”,并验证“功能应用程序”的URL是否在列表中,其格式如下:https://mycoolapp.azurewebsites.net
。如果不是,则添加它。
如果使用插槽,则必须为两个插槽都添加它。
答案 6 :(得分:1)
我现在唯一能想到的就是允许的观众。
转到“ Active Directory”设置,然后单击“高级”。在允许令牌受众下 添加您确切的函数网址。它可能已经包含了回调URL,但是只需将其替换为仅函数库url,而无需进行任何回调,如图所示。
确保在按ok时,还保存了“身份验证/授权”设置以生效,并在1分钟左右后重试。我使用PostMan进行了测试,并传递了承载令牌,并且有效!
答案 7 :(得分:-1)
我今天正面临着同样的问题。问题出在我请求访问令牌时传递的资源ID。
例如,最初我使用功能URL作为资源ID来请求这样的令牌:
var allTrue = t2.All(x=>x.BoolProperty == true);
var allFalse = t2.All(x=>x.BoolProperty == false);
var anyNull = t2.Any(x=>x.BoolProperty.HasValue == false);
虽然这返回了访问令牌,但是使用访问令牌调用我的函数api时,我收到了未经授权的401。
我更改了代码,以将功能应用App ID作为资源传递:
AuthenticationResult authenticationResult = authenticationContext.AcquireTokenAsync("https://myfunction.azurewebsites.net", "myClientAppIdGUID", new Uri("https://login.live.com/oauth20_desktop.srf"), new PlatformParameters(PromptBehavior.SelectAccount)).Result;
现在一切正常。