【问题标题】:where should I create Active Directory app roles so that I can see those roles in the access token?我应该在哪里创建 Active Directory 应用程序角色,以便我可以在访问令牌中看到这些角色?
【发布时间】:2021-12-17 01:28:00
【问题描述】:

我已将 angular 应用程序Asp.Net 核心 Web API 注册到 Azure Active Directory。我已将 应用角色 添加到 Angular 的注册中。我还将角色分配给了一位用户。

当我登录用户时,我在访问令牌中看不到角色属性。我看到的都是"scp": "Directory.Read.All openid profile User.Read email",

角色属性出现在 id 标记中。像这样:

"roles": [
    "can_read_own_application"
],

鉴于 access_token 是 API 所期望的,为什么这个角色出现在 id_token 而不是 access_token 中。

顺便说一下,关于这个主题的文档数不胜数。我刚刚看了这个由微软员工制作的video。我找不到它说明应用角色应该添加到客户端应用程序还是 API 应用程序的位置。也许我这就是为什么角色没有出现在访问令牌中的原因。但是,添加到 API 注册中的应用角色甚至没有出现在令牌中。

感谢您的帮助。

编辑

  1. 我在 API 中添加了一个作用域

  2. 我使用客户端“ID”更新了 API 清单

"knownClientApplications": ["351d2a1d-fb5f-4527-b614-edb6d7277043" ]

  1. 我为客户端更新了 API 的权限

  1. 我更新了我的 Angular 代码

现在当我登录时,找不到上述范围。访问令牌具有以下值:

{
   "app_displayname": "MyApplication-Client-Local",
    //..
    "scp": "openid profile User.Read email",
}

我什至不记得曾询问过openidemail。我提到的范围是User.Readaccess_as_user

【问题讨论】:

  • 你将graph api user.read 和你的自定义api api"//xxx/access_as_user 设置在一起,这是不允许的。您只能设置一种 api 权限一次。您可以尝试将api://xxxx/access_as_user 放在user.read 之前,然后您会发现scp 包含您自定义的api 权限但没有graph api 权限。
  • @TinyWang,我知道我并没有真正理解整个概念。谢谢你的耐心。我还有更多要学的东西,但至少我现在可以建立一些具体的东西。 +1 为您提供帮助
  • 很好。感谢您的回复和投票:)

标签: azure-active-directory


【解决方案1】:

我想我可以在这里回答你的部分问题。

对于访问令牌,它是在 azure 广告应用程序的帮助下生成的。您可以在azure portal -> azure ad 中注册一个azure ad,也可以设置这个应用的api权限。

这里假设一个场景,你需要在你的租户中调用一个可以返回用户信息的api,然后你需要调用微软提供的get user graph api(这个api类似于你自己的api)。调用此 api 需要在 http 请求标头中有访问令牌,并且该令牌应包含读取用户信息的权限。就像描述的api文档一样,在调用api时,用于生成访问令牌的应用程序应该首先有User.Read permission type : delegateUser.Read.All permission type : application。然后添加api权限后,来自该应用的访问令牌将包含scp:User.Readroles:User.Read.All

application 和 delegate 类型的区别,可以简单理解为 access token 的生成方式。生成访问令牌的典型流程有 2 个,auth code flowclient credential flow。一种要求用户登录(delegate,表示代表用户,将返回 scp 声明),另一种只使用 azure ad 应用程序的 client-id 和 client-secret(应用程序,表示代表应用程序,始终在 daemon 应用程序或 api 应用程序中使用,将返回角色声明)。

现在你访问的token包含了正确的权限,用户api会解码token可以发现它有scp:User.Readroles:User.Read.All,然后api返回对http请求的响应。你自己的api也是一样的。您的 api 应首先解码访问令牌以检查传入请求是否具有访问 api 本身的正确权限,例如它需要 User.Richard.Read 权限,但是您在 azure ad 中找不到这种 api 权限,因为此 api 权限是自己定义的,所以需要另外注册一个azure ad应用来发挥api的作用,在这个应用中应该expose an api with the custom api permission。然后返回生成访问令牌的应用程序,然后为其分配 api 权限。然后你可以通过这个应用程序生成访问令牌,范围为User.Richard.Read

【讨论】:

  • 我阅读了您在回复中提供的所有链接。我也完成了本教程github.com/Azure-Samples/…。要么我做错了什么,要么我还不了解整个概念
  • 也许您可以在问题中更新您的要求,以便有人可以帮助您设计如何实现该功能....
  • 请看我刚刚更新的问题。希望你能看到我所做的一切。
【解决方案2】:

关注this tutorial step by step之后。我意识到从 Azure AD 请求/获取令牌不是一次性操作。

  1. 我注册了 2 个应用程序:客户端应用程序 (angular) 和 API (asp.net core web api)。

  2. 当用户登录时,他/她获得的令牌来自客户端注册。这是有道理的,因为在登录过程中提供的信息是客户端应用程序的信息。

难怪现在访问令牌不包含我向 API 注册的权限。顺便说一句,令牌中属性 audience 的值是 Graph 本身的值 00000003-0000-0000-c000-000000000000。因此,这个token是用来查询用户身份等的。

  1. 只有当我调用 API 时,Angular 才会向 Azure AD 发出另一个 POST 请求,以获取 API 可用的令牌,其中使用刷新令牌和指向我的范围的 url这里提到了

    export const protectedResources = { 待办事项列表:{ 端点:“https://localhost:44351/api/todolist”, 范围:["api://8755d178-93a7-4a30-95ea-b59177e85d7f/access_as_user"], }, }

    protectedResourceMap.set(protectedResources.todoListApi.endpoint, protectedResources.todoListApi.scopes);

当这个令牌到达时,它包含值"aud": "the_api_guid""scp": "access_as_user"

【讨论】:

    最近更新 更多