【问题标题】:How to use Azure AD Graph API access for service principals?如何使用 Azure AD Graph API 访问服务主体?
【发布时间】:2017-08-29 18:45:22
【问题描述】:

我有一个使用 adal4j 的有效 Azure AD/Azure 守护程序应用程序,该应用程序使用用户/密码身份验证。由于 ADFS 的问题,我希望也能够使用服务主体(客户端 ID/秘密)进行身份验证。这似乎适用于应用程序的 Azure(非 AD)部分,因为可以为相关订阅定义 SP 角色,但是对于 Azure AD 部分,我得到:

response code 403, error: Authorization_RequestDenied: Insufficient privileges to complete the operation.

...这发生在第一次调用 Graph API 时 - 我使用 https://graph.windows.net 范围从 AuthenticationContext.acquireToken() 获取有效令牌。

我的帐户是目录中的所有者。我尝试使用应用程序上的“授予权限”按钮,还尝试制作同意 URL(有效)并使用它来同意应用程序在目录中具有必要的权限。似乎两者都不会影响这一点。

应用是原生应用,因为它是守护程序/服务应用,所以不能参与 OAuth2 同意。

如何使用 SP 访问 Azure AD Graph API 进行身份验证?提醒一下,未更改,该应用使用(非 ADFS)用户/密码,SP 使用 Azure API,而不是 Azure AD Graph API。

谢谢...

附:我也尝试过使用 Azure Graph API,微软现在推荐它而不是 Azure AD Graph API。结果相同,并且同样适用于用户/密码凭据。

修改这一点以将 adal4j 排除在外——这似乎更像是一个通用的 Azure AD 问题。这是问题的一个例子,使用 curl:

客户端凭据令牌请求:

curl --request POST "https://login.windows.net/367cxxxx41e5/oauth2/token" --data-urlencode "resource=https://graph.windows.net" --data-urlencode "client_id=9d83yyyy08cd" --data-urlencode "grant_type=client_credentials" --data-urlencode "client_secret=secret"

客户端凭据令牌响应:

{"token_type":"Bearer","expires_in":"3599","ext_expires_in":"0","expires_on":"1491486990","not_before":"1491483090","resource":"https://graph.windows.net","access_token":"eyJ0zzzz2zVA"}

使用客户端凭据令牌的 Azure AD REST 查询:

curl "https://graph.windows.net/367cxxxx41e5/tenantDetails" --header "Authorization: eyJ0xxxx2zVA" --header "Accept: application/json;odata=minimalmetadata" --header "api-version: 1.6"

使用客户端凭据令牌的 Azure AD REST 响应:

{"odata.error":{"code":"Authorization_RequestDenied","message":{"lang":"en","value":"Insufficient privileges to complete the operation."}}}

现在,将其与(注意相同的租户 ID/应用 ID)进行对比:

密码凭证令牌请求:

curl --request POST "https://login.windows.net/367cxxxx41e5/oauth2/token" --data-urlencode "resource=https://graph.windows.net" --data-urlencode "client_id=9d83yyyy08cd" --data-urlencode "grant_type=password" --data-urlencode "username=bozo@clown.com" --data-urlencode "password=password"

密码凭证令牌响应:

{"token_type":"Bearer","scope":"Directory.AccessAsUser.All Directory.Read.All Group.Read.All Member.Read.Hidden User.Read User.Read.All User.ReadBasic.All","expires_in":"3599","ext_expires_in":"0","expires_on":"1491489157","not_before":"1491485257","resource":"https://graph.windows.net","access_token":"eyJ0zzzz0EXQ","refresh_token":"AQABzzzzAgAA"}

使用密码凭据令牌的 Azure AD REST 查询:

curl "https://graph.windows.net/367cxxxx41e5/tenantDetails" --header "Authorization: eyJ0xxxx0EXQ" --header "Accept: application/json;odata=minimalmetadata" --header "api-version: 1.6"

使用密码凭据令牌的 Azure AD REST 响应:

{"odata.metadata":"https://graph.windows.net/367cxxxx41e5/$metadata#directoryObjects/Microsoft.DirectoryServices.TenantDetail","value":[{"odata.type":"Microsoft.DirectoryServices.TenantDetail","objectType":"Company","objectId":"367cxxxx41e5","deletionTimestamp":null,"assignedPlans":[{"assignedTimestamp":"2017-02-24T03:25:33Z","capabilityStatus":"Enabled","service":"SharePoint","servicePlanId":"e95byyyyc014"},...

此时我的怀疑是,在创建应用程序时由 Azure AD 默认创建的 SP 不包含必要的权限。我将尝试创建一个具有指定权限的新 SP。这样的例子比比皆是,但都集中在目标应用程序是一些神话般的 LOB 应用程序,而不是 Azure AD。而且,与半生不熟的门户网站一样,必须使用 CLI 来执行此操作。

</snark>

此外,我已验证任何具有 Reader 角色的人都应该能够执行该查询。我已将贡献者和所有者都添加到 SP,但没有任何效果。

另外,FWIW,我已验证 SP 在理论上具有我在门户中输入的 Azure AD(和其他)权限。我想。

    PS C:\> Get-AzureADServicePrincipalOAuth2PermissionGrant -objectid 'a9f9xxxx5377'|format-list -property consenttype,resourceid,scope

ConsentType : AllPrincipals
ResourceId  : c569xxxxe7f0
Scope       : Member.Read.Hidden User.Read User.ReadBasic.All User.Read.All Group.Read.All Directory.Read.All
              Directory.AccessAsUser.All

ConsentType : AllPrincipals
ResourceId  : 3318xxxx66a5
Scope       : user_impersonation

ConsentType : AllPrincipals
ResourceId  : 8c0fxxxx4198
Scope       : User.Read.All User.ReadBasic.All Group.Read.All Directory.Read.All Directory.AccessAsUser.All User.Read

PS C:\> get-azureadobjectbyobjectid -objectids 'c569xxxxe7f0','3318xxxx66a5','8c0fxxxx4198'

 ObjectId     AppId                                DisplayName
--------     -----                                -----------
8c0fxxxx4198 00000003-0000-0000-c000-000000000000 Microsoft Graph
3318xxxx66a5 797f4846-ba00-4fd7-ba43-dac1f8f63013 Windows Azure Service Management API
c569xxxxe7f0 00000002-0000-0000-c000-000000000000 Microsoft.Azure.ActiveDirectory

【问题讨论】:

  • 您好,您是否尝试过在门户网站上使用新的应用注册(预览版)。它列出了您已经拥有的 SP,并允许您添加 Microsoft Graph API 权限,但您需要成为管理员才能同意这些 - 尝试此处的步骤 - docs.microsoft.com/en-us/graph/auth-v2-service

标签: azure-ad-graph-api adal4j


【解决方案1】:

根据您的描述,根据我的经验,我认为问题是由两个原因引起的。

  1. 在 Azure 门户的 Azure AD 中注册的应用程序的Required permissions 选项卡中不添加Windows Azure Active Directory (Microsoft.Azure.ActiveDirectory) 的api 访问权限,如下所示并选择相关权限。

作为参考,您可以参考其他 SO 线程 Trouble with authorization using client_credentials Azure AD Graph API 或官方文档 here 和有用的 blog

  1. 不为此服务主体分配Contributor。您需要运行下面的 powershell 命令来执行此操作。

    New-AzureRmRoleAssignment -RoleDefinitionName Contributor -ServicePrincipalName 'applicationID'
    

    或者您也可以通过 Azure CLI 或仅在 Azure 门户上参考我对另一个 SO 线程 Cannot list image publishers from Azure java SDK 的回答。

希望对你有帮助。

【讨论】:

  • 彼得潘:感谢您的回复。请参阅我的扩展帖子,包括善/恶的卷曲示例。正如我所提到的,我认为问题不在于门户中列举的权限,而是分配给 SP 的权限(遗憾的是,门户中不可用)。我从一开始就有这些。我怀疑你的答案中的#2 部分是正确的。
  • 彼得潘:对不起——不高兴。我尝试(分别)添加贡献者和所有者角色,但仍然收到相同的错误。 RoleAssignmentId:/subscriptions/ff34xxxx65df/providers/Microsoft.Authorization/roleAssignments/0c7exxxxaa2b 范围:/subscriptions/ff34xxxx65df DisplayName:测试 Azure AD 客户端 ID SignInName:RoleDefinitionName:所有者 RoleDefinitionId:8e3axxxxb635 ObjectId:a9f9xxxx5377 ObjectType:ServicePrincipal
  • 彼得潘:我确实想知道的一件事是 SP 角色的范围。使用 New-AzureRmRoleAssignment,范围必须是订阅。由于该目录并没有真正与订阅相关联,如何告诉它使用哪个范围?如果您查看良好的用户令牌响应,它包括为应用定义的范围。当我尝试添加这些范围时,它们会被拒绝。到目前为止,我对 Azure AD 订阅的体验是它们不能直接用于角色分配。至少 Azure CLI(不是 PowerShell)在尝试执行 RBAC 时会拒绝这些订阅。
猜你喜欢
  • 1970-01-01
  • 2020-08-06
  • 2014-08-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
  • 2017-11-12
  • 1970-01-01
相关资源
最近更新 更多