在ID/访问令牌中挣扎着可选索赔

发布于 2025-02-06 01:32:50 字数 4010 浏览 1 评论 0 原文

我正在更新一个从AD-FS 2016到Azure AD V2的内部开发的单页应用程序(Typescript/React)。由于我(开发人员)无法直接访问Azure游戏机,并且正在与(非开发人员)Sysadmin合作,因此事情变得有些复杂。

我已经实施了PKCE并使流量正常;现在,我可以从服务器中获取JWT访问,ID和刷新令牌,并通过JWKS对其进行身份验证。到目前为止,一切都很好。

现在,我的应用程序要了解更多内容:

  • 是否应将用户视为管理员。这是从组成员身份推断出的
  • 用户首选用户名和名称/姓氏,

我们通过设置“角色”并将其映射到Azure Console中的组来处理。然后,我们将角色主张添加到代币中。我可以在“ id_token”中找到它是字符串数组。没问题。

我感到困惑了一段时间,因为我在“ Access_Token”中寻找它,但是对于我的应用程序来说,使用“ ID_Token”并不是问题。

第二个确实给我们带来了问题。无论我们将什么放入“可选索赔”对话框中 - 我们添加了所有这些字段,以及更多的ID令牌,它们都不会出现在其中。我们正在做的任何事情似乎都会影响出来的实际令牌。

我开始认为我错过了有关获取信息的问题。我正在使用 https://graph.microsoft.com/profile https://graph.microsoft.com/email 和 https:// .microsoft.com/user.read 示波器和管理员已代表应用程序授权这些。用户是从我们的内部Active Directory同步的,AD-FS也正在运行,因此我知道此信息在其中。我尝试用资源参数弄乱,但显然在Azure AD V2中弃用了这一点。

我已经阅读并重新阅读以及其他在线文档,以下段落使我感到困惑,让我认为那该问题可能与范围有关:

始终使用资源的清单而不是客户端生成访问令牌。因此,在请求中...范围= https://graph.microsoft.com/user.read ...资源是Microsoft Graph API。因此,使用Microsoft Graph API清单创建访问令牌,而不是客户端的清单。更改应用程序的清单将永远不会导致Microsoft Graph API看起来不同的令牌。为了验证您的访问更改有效,请为您的应用程序请求令牌,而不是另一个应用程序。

还是我切换到使用 id_token 的原因?

optional_claims 配置清单的部分看起来像这样:

    "optionalClaims": {
        "idToken": [
            {
                "name": "email",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "upn",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "groups",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "family_name",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "given_name",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "preferred_username",
                "source": null,
                "essential": false,
                "additionalProperties": []
            }
        ],
        "accessToken": [
            {
                "name": "email",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "groups",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "preferred_username",
                "source": null,
                "essential": false,
                "additionalProperties": []
            }
        ],
        "saml2Token": [
            {
                "name": "groups",
                "source": null,
                "essential": false,
                "additionalProperties": []
            }
        ]
    },

但是ID标签中产生的有效负载看起来像:

{
  "aud": "redacted",
  "iss": "https://login.microsoftonline.com/redacted/v2.0",
  "iat": 1654770319,
  "nbf": 1654770319,
  "exp": 1654774219,
  "email": "redacted",
  "groups": [
    "redacted",
    "redacted",
    "redacted",
    "redacted"
  ],
  "rh": "redacted",
  "roles": [
    "redacted"
  ],
  "sub": "redacted",
  "tid": "redacted",
  "uti": "redacted",
  "ver": "2.0"
}

任何拥有更多经验的平台经验的人可以帮助我了解我们在这里做错了什么?我们需要定义自定义范围吗?我们是否只是忘记打开选项?

所有的帮助感恩地收到了!提前致谢...

I am updating an internally developed single-page app (Typescript/React) that uses OAuth2 from AD-FS 2016 to Azure AD v2. Things are complicated slightly by the fact that I (the developer) don't have direct access to the Azure console and am working on this with a (non-developer) sysadmin who does.

I have implemented PKCE and got the flow working; I can now obtain JWT access, ID and refresh tokens from the server and authenticate them via JWKS. So far so good.

Now, my apps to know a couple more things:

  • whether or not the user should be treated as an administrator. This is inferred from group memberships
  • the preferred username and first name/surname of the user

The first of these we dealt with by setting up a "role" and mapping it out to groups in the Azure console. We then added the role claim to the tokens. I can find this as a string array in "id_token". No problem.

I was confused for a while because I was looking for it in "access_token", but it's not a problem for my app to use "id_token" instead.

The second is the thing that is really giving us problems. No matter what we put into the "optional claims" dialog - we've added all these fields and more, for the ID token, they do not appear in it. Nothing we are doing seems to affect the actual tokens that come out at all.

I am beginning to think that I have missed something out with regards to obtaining the information. I am using the https://graph.microsoft.com/profile, https://graph.microsoft.com/email and https://graph.microsoft.com/user.read scopes and the administrator has authorized these on behalf of the app. The user is synced from our in-house active directory, which the AD-FS is running from as well, so I know that this information is in there. I tried messing with the resource parameter but this is deprecated in Azure AD v2 apparently.

I've read and re-read https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-optional-claims along with other online documentation, and the following passage confuses me and makes me think that the issue might be related to scopes:

Access tokens are always generated using the manifest of the resource, not the client. So in the request ...scope=https://graph.microsoft.com/user.read... the resource is the Microsoft Graph API. Thus, the access token is created using the Microsoft Graph API manifest, not the client's manifest. Changing the manifest for your application will never cause tokens for the Microsoft Graph API to look different. In order to validate that your accessToken changes are in effect, request a token for your application, not another app.

Or is that just the reason that I switched to using the id_token?

The optional_claims section of the configuration manifest looks like this:

    "optionalClaims": {
        "idToken": [
            {
                "name": "email",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "upn",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "groups",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "family_name",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "given_name",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "preferred_username",
                "source": null,
                "essential": false,
                "additionalProperties": []
            }
        ],
        "accessToken": [
            {
                "name": "email",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "groups",
                "source": null,
                "essential": false,
                "additionalProperties": []
            },
            {
                "name": "preferred_username",
                "source": null,
                "essential": false,
                "additionalProperties": []
            }
        ],
        "saml2Token": [
            {
                "name": "groups",
                "source": null,
                "essential": false,
                "additionalProperties": []
            }
        ]
    },

But the resulting payload in the ID tag looks like this:

{
  "aud": "redacted",
  "iss": "https://login.microsoftonline.com/redacted/v2.0",
  "iat": 1654770319,
  "nbf": 1654770319,
  "exp": 1654774219,
  "email": "redacted",
  "groups": [
    "redacted",
    "redacted",
    "redacted",
    "redacted"
  ],
  "rh": "redacted",
  "roles": [
    "redacted"
  ],
  "sub": "redacted",
  "tid": "redacted",
  "uti": "redacted",
  "ver": "2.0"
}

Can anyone who has more experience of the platform help me understand what we are doing wrong here? Do we need to define custom scopes? Have we simply forgotten to turn an option on?

All help gratefully received! Thanks in advance...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

你的心境我的脸 2025-02-13 01:32:50

我试图在环境中重现相同的结果,并以下结果:

我已经实现了 pkce Flow 并获得了JWT访问,ID和刷新令牌。

我添加了以下可选索赔:
转到Azure Portal - > Azure Active Directory->应用注册 - >您的应用程序 - >令牌配置
“在此处输入图像说明”

请检查您用于获得令牌的范围。

当我仅给出 openID 作为范围时,得到如下的响应:
“在此处输入映像说明”

但是当我给出范围为 openID> openID profile email use user.read ,成功获得了所有可选索赔,如下所示:
“在此处输入图像说明”

I tried to reproduce the same in my environment and got below results:

I have implemented PKCE flow and got JWT access, ID and refresh tokens.

I added optional claims like below:
Go to Azure Portal -> Azure Active Directory -> App Registrations -> Your App -> Token Configuration
enter image description here

Please check the scopes you are using to get token.

When I gave only openid as scope, got response like below:
enter image description here

But when I gave scope as openid profile email user.read, got all optional claims successfully like below:
enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文