我有一个由Azure Active Directory保护的Azure功能。
如果已登录,我可以从浏览器成功调用该应用程序。
现在,我要做的是从不使用用户名和密码的应用程序中调用该函数,以便进行身份验证,而是使用受信任的应用程序客户端ID和客户端机密。
为此,我尝试使用为保护功能应用程序而创建的同一应用程序(例如ApplicationA)。我去了App Registrations,找到了通过在功能App身份验证/授权设置(ApplicationA)中配置Azure Active Directory身份验证提供程序创建的应用程序,并为此设置了客户端密码。
现在,我可以使用所述应用程序客户端ID和生成的密钥获取令牌。
但是,当我尝试使用该令牌调用函数时,出现401错误。
我在App Registration中对一个新创建的应用程序(例如ApplicationB)尝试了相同的操作,但结果相同,但仍然得到401。
我什至尝试在“订阅”中为该应用程序添加阅读者角色,但随后再次尝试-使用令牌调用Function时出现401。
我知道,应用程序设置中有类似API权限的内容。因此,我尝试将ApplicationB的权限添加到ApplicationA user_impersonation,但是它也不起作用,因此不是这样。
那么,如何为能够为其获取令牌的注册应用程序授予权限,以便可以使用此令牌来调用功能?
编辑:
我正在使用以下代码进行令牌获取:
using Microsoft.Identity.Client;
string ClientId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
string ClientSecret = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
string TenantId = "XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
string Authority = $"https://login.microsoftonline.com/{TenantId}";
string[] scopes = new string[] { "https://graph.microsoft.com/.default" };
IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(ClientId)
.WithClientSecret(ClientSecret)
.WithAuthority(new Uri(Authority))
.Build();
AuthenticationResult result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
string token = result.AccessToken;
您需要通过清单将至少一个应用程序许可(具有允许的成员类型Application的appRole)注册到功能app注册中。然后,您可以将应用程序权限分配给客户端应用程序。
您可以查看我的文章以获取有关定义权限的更多信息:https : //joonasw.net/view/defining-permissions-and-roles-in-aad
清单中的示例应用权限:
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"description": "Allow the application to read all things as itself.",
"displayName": "Read all things",
"id": "32028ccd-3212-4f39-3212-beabd6787d81",
"isEnabled": true,
"lang": null,
"origin": "Application",
"value": "Things.Read.All"
}
],
您需要自己定义id,它只需要是一个GUID。该value
是什么在在令牌发送roles
要求。描述和显示名称仅用于权限在UI中的显示方式。
我添加了应用角色并授予了该角色的权限,但是我仍然得到401。奇怪的是,当我解码令牌时,它不包含scp ot角色声明。
嗯,如果角色不存在,则表示权限未正确授予或令牌获取错误。您是否可以至少将令牌获取代码添加到问题中?
我编辑了问题。
好的,这是范围。我用
"https://myfunctionappname.azurewebsites.net/.default"
代替,"https://graph.microsoft.com/.default"
现在可以用了。谢谢。嗯,是的,它需要匹配应用程序注册中定义的ID URI(或者您可以使用
api-client-id-here/.default
)