新的 Azure AD 应用程序在通过管理门户更新之前无法运行

New Azure AD application doesn't work until updated through management portal

我使用 AAD Graph API 在 Azure AD 中创建了一个新应用程序。 ()

不幸的是,在我访问 Azure 管理门户中的应用程序配置页面并进行外观更改并保存之前,它不允许我的客户端访问请求的资源。删除更改并再次保存后,它仍然有效。 更改前和更改后退步骤之前的应用程序清单文件完全相同(如 diff.exe 中所说它们相同)。

对比应用认证时返回的JWT token,发现post-change access token包含"roles"部分。在管理门户中保存应用程序之前返回的访问令牌中不存在整个 "roles" 部分。

因此,Azure 管理门户似乎在保存更改时对应用程序执行 "something"。问题是它是什么,我可以使用 AAD 图做同样的事情吗 API?

有几个问题。 Azure 后端的一些错误现在已经修复,还有一些我不知道是必要的对 API 的缺失调用。 多亏了 MS 支持中一些非常乐于助人的人,我们才能够让它工作。

创建应用程序时,您需要执行以下操作:

  1. 创建一个 application 对象。
  2. 为应用程序设置 RequiredResourceAccess,即。应用程序对 Azure Graph API 等具有哪些权限。这是在门户的 "permissions to other applications" 设置中配置的内容。您可以通过手动配置权限获取必要的 GUID,然后查看应用程序的 AAD 清单文件。
  3. 为应用程序创建 service principal
  4. AppRoleAssignments 添加到服务主体。

最后一部分是我之前遗漏的部分。即使您已经在应用程序对象上配置了 RequiredResourceAccess,服务主体仍然需要 AppRoleAssignments 才能真正拥有访问资源的权限。

创建 AppRoleAssignments 时,确定要分配哪个 PrincipalId 有点棘手,因为这是其他资源的服务主体的 AAD ObjectId。

这是添加 AppRoleAssignment 以访问 Azure AD Graph API 的片段。 client 是一个 ActiveDirectoryClient 实例,sp 是我的应用程序的 ServicePrincipal:

// find the azure ad service principal
var aadsp =
     client.ServicePrincipals.Where(csp => csp.AppId == "00000002-0000-0000-c000-000000000000")
     .ExecuteSingleAsync().Result;

// create the app role assignment
var azureDirectoryReadAssignment = new AppRoleAssignment
{
    PrincipalType = "ServicePrincipal",
    PrincipalId = Guid.Parse(sp.ObjectId), //
    Id = Guid.Parse("5778995a-e1bf-45b8-affa-663a9f3f4d04"), // id for Directory.Read
    // azure active directory resource ID
    ResourceId = Guid.Parse(aadsp.ObjectId) // azure active directory resource ID
};
// add it to the service principal
sp.AppRoleAssignments.Add(azureDirectoryReadAssignment);
// update the service principal in AAD
await sp.UpdateAsync();

我的经验是你需要等待很短的时间,可能是 2-3 分钟,新创建的对象在 AAD 中生效,然后你可以使用新的应用程序进行身份验证。

除了上面 RasmusW 的回答之外,根据您要实现的目标,您可能还需要做一些其他事情。

  1. 如果您希望委派权限起作用,您还需要将 Oauth2PermissionGrant 添加到根级别的 Oauth2PermissionGrants 集合中。这应该有呼叫者 SPN ObjectId 的 clientId,被叫 SPN 对象 ID 的 ResourceId。 Oauth2PermissionGrant 的 Scope 值为 key。它应该有 space 个分隔值。这里的每个值都来自目标 SPN 上的 Oauth2Permission 对象的 'Value' 属性。
  2. 此外,您可能还需要处于适当的 DirectoryRole 中,例如目录读者。