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

Posted

技术标签:

【中文标题】从 PowerApp(或逻辑应用)调用受 AAD 保护的 Azure 函数【英文标题】:Call AAD Protected Azure Function from PowerApp (or Logic App) 【发布时间】:2021-08-04 01:38:27 【问题描述】:

我有一个设置为使用 AAD 身份验证(最新(非经典)方法)的 Azure 函数,当我使用 Postman 或自定义时,我无法通过 401 错误连接器。我关注了关于设置自定义连接器的Microsoft Docs 文章。

我的初始测试包括以下内容:

创建了一个新的 Azure Function App 为函数应用设置系统分配的 MSI 使用 AzureAD 设置身份验证(经典方法) 在 AzureAD 中创建额外的应用程序注册(用于自定义连接器)并执行必要的配置/同意 为 PowerApps 创建了一个自定义连接器 在自定义连接器中成功测试

虽然这在使用经典身份验证方法配置时有效,但我随后在 Function App 中配置了新方式的身份验证,这导致我的所有请求都返回 401。当我将 Function App 配置为对未经身份验证的请求使用 302 时,我可以使用针对 HTTP 触发函数的浏览器请求进行身份验证。但是,如果我尝试使用 Postman、测试自定义连接器或连接到逻辑应用程序中的函数,我总是会收到 401。所有身份验证配置都显示正确并且用户分配已配置。

我已查找教程或其他已使用安全 Azure 函数配置 PowerApps 连接的教程,但我无法找到我要查找的内容。如果可能的话,我想使用最新的方法来设置身份验证,但如果没有,另一种方法是重新创建函数应用程序并通过经典方法设置身份验证(注意:一旦你配置了新的身份验证方法,你就可以' t 返回并通过经典模式进行设置)。

更新:也想添加一些截图:

Authentication 部分中,我将其设置为需要身份验证(注意:当更改为不需要身份验证时,api 调用工作正常)。

应用程序公开了user_impersonation api,如文档中所述(自定义应用注册已授权此api)

自定义应用注册(即 connector 应用注册)设置为使用 api 并获得同意。我还生成了一个 客户端密码 供 Postman 使用。

在 LINQPad 中,我使用 connector 应用程序注册了一些代码以获取 Access Token。但是,我仍然收到相同的 401 错误。我尝试同时使用 hostnameFunction app auth app id - 都导致 401。令牌成功返回,但对 Function 的调用失败。

更新 #2:解决 PowerApp 自定义连接器问题

在遵循@bowman-zhu 解决方案(从 Issuer URL 中删除 /v2.0)之后,我能够克服 401 错误。我的下一步是再次测试自定义连接器。由于这是最初的痛点,我想提供解决方案的详细信息。

最初,我仍然收到错误消息,因此我决定从 Azure Active Directory 作为身份提供者切换到使用 Generic Oauth 2。 遵循 Microsoft 文档创建自定义连接器后,Client idClient secret 特定于连接器应用注册Authorization URLToken URL 也从应用程序注册中删除(即使它们是 v2.0,它们仍然有效)。我为Refresh URL 使用了与授权URL 相同的值。范围是 <guid>/.default(其中 是函数应用的授权应用注册的应用 ID)。

验证和更新连接器后,我测试了其中一个 API 调用,最终一切都按预期工作。

【问题讨论】:

嗨,有更新吗? @BowmanZhu - 还没有机会进行测试,但计划今天进行测试并以结果回复。谢谢你的回答顺便说一句! 【参考方案1】:

更新:

检查您的发行人 URL:

或者将 accessTokenAcceptedVersion 改为 2:

无论如何,请确保问题 url 版本相同。

(发现Authentication还是有很多问题,很多东西不会自动配置。)

原答案:

这是你遇到的问题:

您需要授权:

例如,如果你使用的是python,那么:

1、最新的Authentication不会自动暴露你的function app,所以需要添加:

1、创建一个客户端广告应用来访问上面的api。

2,使用如下代码获取令牌(客户端ID和秘密是从上面的广告应用程序获取):

import requests
from azure.identity import ClientSecretCredential 
import json

client_id = 'xxx'
tenant_id = 'xxx'
client_secret = 'xxx'
subscription_id = 'xxx'

credential = ClientSecretCredential(tenant_id=tenant_id, client_id=client_id, client_secret=client_secret)

print(credential.get_token('https://0416bowman.azurewebsites.net/.default'))

accesstoken = str(credential.get_token('https://0416bowman.azurewebsites.net/.default'))[19:1141]

print(accesstoken)

3、将访问令牌添加到Authorization标头中,如果您使用的是邮递员,您应该这样做:

下面的url可以让你检查token是否正确:

https://jwt.io/

【讨论】:

更新了问题以包含屏幕截图。我尝试了您的建议,但仍然收到 401 错误。我的屏幕截图显示了在 LINQPad 中进行的测试,但我也通过 Postman 使用通过 LINQPad 代码收到的访问令牌进行了测试。 @Michael 请检查 Issuer URL,我已经更新了答案。 取下/v2.0 后,我能够通过LINQPad 处理请求!如此奇怪的问题,但这正是我让事情向前发展所需要的。我终于能够让 Postman 也能正常工作。 另外,我更新了原始问题以反映我为解决 PowerApps 中的自定义连接器所做的工作。感谢您的帮助@bowman-zhu!

以上是关于从 PowerApp(或逻辑应用)调用受 AAD 保护的 Azure 函数的主要内容,如果未能解决你的问题,请参考以下文章

使用 react-aad-msal 缺少范围从 react SPA 调用 web api

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

使用 Edge 从批处理文件全屏启动 Powerapp

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

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

如何清除 Powerapp 中的文本输入?