欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

Microsoft 标识平台访问令牌 有大用

你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

Microsoft 标识平台访问令牌

访问令牌使客户端可以安全地调用受保护的 Web API,并可由 Web API 用来执行身份验证和授权。 根据 OAuth 规范,访问令牌是没有固定格式的不透明字符串 - 某些标识提供者 (IDP) 使用 GUID,另一些标识提供者使用加密的 blob。 Microsoft 标识平台使用各种访问令牌格式,具体取决于接受令牌的 API 的配置。 开发人员在 Microsoft 标识平台上注册的自定义 API 可以从两种不同格式的 JSON 网络令牌 (JWT) 中进行选择,这两种格式称为“v1”和“v2”,Microsoft 开发的 API(如 Microsoft Graph)或 Azure 中的 API 有其他专有令牌格式。 这些专有格式可能是加密的令牌、JWT 或不会进行验证的特殊 JWT 样式令牌。

客户端必须将访问令牌视为不透明的字符串,因为令牌的内容仅适用于资源 (API)。 开发人员可以使用 jwt.ms 之类的站点来解码 JWT,但仅限进行验证和调试。 但请注意,你为 Microsoft API 接收的令牌可能并非始终为 JWT,你无法始终对其进行解码。

要获得有关访问令牌内部内容的详细信息,客户端应使用随访问令牌一起返回给客户端的令牌响应数据。 当客户端请求访问令牌时,Microsoft 标识平台还会返回一些有关访问令牌的元数据供应用使用。 此信息包含访问令牌的过期时间及其有效范围。 此数据可让应用执行访问令牌的智能缓存,而无需分析访问令牌本身。

请参阅以下部分,了解你的 API 可以如何验证和使用访问令牌中的声明。

注意

除非另行说明,否则本页上的所有文档仅适用于为已注册 API 颁发的令牌。 它不适用于为 Microsoft 拥有的 API 颁发的令牌,不能使用这些令牌来验证 Microsoft 标识平台将如何为你创建的 API 颁发令牌。

令牌格式和所有权

v1.0 和 v2.0

Microsoft 标识平台提供了两个版本的访问令牌:v1.0 和 v2.0。 这些版本控制令牌中有哪些声明,确保 Web API 可以控制其令牌的样式。 Web API 在注册过程中选择了其中一个版本作为默认值 - v1.0 用于仅限 Azure AD 的应用,v2.0 用于支持使用者帐户的应用。 这可由使用accessTokenAcceptedVersion中的 accessTokenAcceptedVersion 设置的应用程序控制,其中 null 和 1 生成 v1.0 令牌,而 2 生成 v2.0 令牌。

令牌用于什么应用?

访问令牌请求中涉及两个参与方:请求令牌的客户端,和调用 API 时接受令牌的资源 (API)。 令牌中的 aud 声明指示令牌适用的资源(其受众)。 客户端使用令牌,但不应理解或尝试分析它。 资源接受令牌。

Microsoft 标识平台支持从任何版本的终结点颁发任何令牌版本 - 它们不相关。 因此,当资源将 accessTokenAcceptedVersion 设置为 2 时,客户端调用 v1.0 终结点来获取该 API 的令牌会收到 v2.0 访问令牌。 资源始终拥有其令牌(带 aud 声明的令牌),是唯一可以更改其令牌详细信息的应用程序。 这就是为什么更改客户端的访问令牌可选声明不会更改在 请求令牌时接收到的访问令牌,该令牌由 Microsoft Graph 资源所有。

示例令牌

v1.0 和 v2.0 令牌很相似,都包含许多相同的声明。 此处提供了每种令牌的示例。 但是,这些示例令牌不会进行验证,因为密钥在发布之前已经轮换,个人信息已从其中删除。

v1.0

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSIsImtpZCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSJ9.eyJhdWQiOiJlZjFkYTlkNC1mZjc3LTRjM2UtYTAwNS04NDBjM2Y4MzA3NDUiLCJpc3MiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC9mYTE1ZDY5Mi1lOWM3LTQ0NjAtYTc0My0yOWYyOTUyMjIyOS8iLCJpYXQiOjE1MzcyMzMxMDYsIm5iZiI6MTUzNzIzMzEwNiwiZXhwIjoxNTM3MjM3MDA2LCJhY3IiOiIxIiwiYWlvIjoiQVhRQWkvOElBQUFBRm0rRS9RVEcrZ0ZuVnhMaldkdzhLKzYxQUdyU091TU1GNmViYU1qN1hPM0libUQzZkdtck95RCtOdlp5R24yVmFUL2tES1h3NE1JaHJnR1ZxNkJuOHdMWG9UMUxrSVorRnpRVmtKUFBMUU9WNEtjWHFTbENWUERTL0RpQ0RnRTIyMlRJbU12V05hRU1hVU9Uc0lHdlRRPT0iLCJhbXIiOlsid2lhIl0sImFwcGlkIjoiNzVkYmU3N2YtMTBhMy00ZTU5LTg1ZmQtOGMxMjc1NDRmMTdjIiwiYXBwaWRhY3IiOiIwIiwiZW1haWwiOiJBYmVMaUBtaWNyb3NvZnQuY29tIiwiZmFtaWx5X25hbWUiOiJMaW5jb2xuIiwiZ2l2ZW5fbmFtZSI6IkFiZSAoTVNGVCkiLCJpZHAiOiJodHRwczovL3N0cy53aW5kb3dzLm5ldC83MmY5ODhiZi04NmYxLTQxYWYtOTFhYi0yZDdjZDAxMjIyNDcvIiwiaXBhZGRyIjoiMjIyLjIyMi4yMjIuMjIiLCJuYW1lIjoiYWJlbGkiLCJvaWQiOiIwMjIyM2I2Yi1hYTFkLTQyZDQtOWVjMC0xYjJiYjkxOTQ0MzgiLCJyaCI6IkkiLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJzdWIiOiJsM19yb0lTUVUyMjJiVUxTOXlpMmswWHBxcE9pTXo1SDNaQUNvMUdlWEEiLCJ0aWQiOiJmYTE1ZDY5Mi1lOWM3LTQ0NjAtYTc0My0yOWYyOTU2ZmQ0MjkiLCJ1bmlxdWVfbmFtZSI6ImFiZWxpQG1pY3Jvc29mdC5jb20iLCJ1dGkiOiJGVnNHeFlYSTMwLVR1aWt1dVVvRkFBIiwidmVyIjoiMS4wIn0.D3H6pMUtQnoJAGq6AHd

在 JWT.ms 中查看此 v1.0 令牌。

v2.0

eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6Imk2bEdrM0ZaenhSY1ViMkMzbkVRN3N5SEpsWSJ9.eyJhdWQiOiI2ZTc0MTcyYi1iZTU2LTQ4NDMtOWZmNC1lNjZhMzliYjEyZTMiLCJpc3MiOiJodHRwczovL2xvZ2luLm1pY3Jvc29mdG9ubGluZS5jb20vNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3L3YyLjAiLCJpYXQiOjE1MzcyMzEwNDgsIm5iZiI6MTUzNzIzMTA0OCwiZXhwIjoxNTM3MjM0OTQ4LCJhaW8iOiJBWFFBaS84SUFBQUF0QWFaTG8zQ2hNaWY2S09udHRSQjdlQnE0L0RjY1F6amNKR3hQWXkvQzNqRGFOR3hYZDZ3TklJVkdSZ2hOUm53SjFsT2NBbk5aY2p2a295ckZ4Q3R0djMzMTQwUmlvT0ZKNGJDQ0dWdW9DYWcxdU9UVDIyMjIyZ0h3TFBZUS91Zjc5UVgrMEtJaWpkcm1wNjlSY3R6bVE9PSIsImF6cCI6IjZlNzQxNzJiLWJlNTYtNDg0My05ZmY0LWU2NmEzOWJiMTJlMyIsImF6cGFjciI6IjAiLCJuYW1lIjoiQWJlIExpbmNvbG4iLCJvaWQiOiI2OTAyMjJiZS1mZjFhLTRkNTYtYWJkMS03ZTRmN2QzOGU0NzQiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJhYmVsaUBtaWNyb3NvZnQuY29tIiwicmgiOiJJIiwic2NwIjoiYWNjZXNzX2FzX3VzZXIiLCJzdWIiOiJIS1pwZmFIeVdhZGVPb3VZbGl0anJJLUtmZlRtMjIyWDVyclYzeERxZktRIiwidGlkIjoiNzJmOTg4YmYtODZmMS00MWFmLTkxYWItMmQ3Y2QwMTFkYjQ3IiwidXRpIjoiZnFpQnFYTFBqMGVRYTgyUy1JWUZBQSIsInZlciI6IjIuMCJ9.pj4N-w_3Us9DrBLfpCt

在 JWT.ms 中查看此 v2.0 令牌。

访问令牌中的声明

JWT(JSON Web 令牌)拆分成三个部分:

  • 标头 - 提供有关如何验证令牌的信息,包括有关令牌的类型及其签名方式的信息。

  • 有效负载 - 包含有关正在尝试调用你的服务的用户或应用的所有重要数据。

  • 签名 - 用于验证令牌的原始材料。

每个部分由句点 (.) 分隔,并分别采用 Base64 编码。

仅当存在可以填充声明的值时,才提供声明。 你的应用不应依赖于提供的声明。 示例包括 pwd_exp(并非每个租户都要求密码过期)和 family_namepwd_exp流代表无名称的应用程序)。 始终会提供用于验证访问令牌的声明。

某些声明用于帮助 Azure AD 保护重复使用的令牌。 在说明中,这些声明标记为“不透明”,表示不可公开使用。 这些声明不一定会显示在令牌中,我们可能在不发出通告的情况下添加新的声明。

标头声明

声明格式说明
typ字符串 - 始终为“JWT”指示令牌是 JWT。
alg字符串指示用于对令牌进行签名的算法,例如“RS256”
kid字符串指定可用于验证此令牌签名的公钥指纹。 在 v1.0 和 v2.0 访问令牌中已发出。
x5t字符串功能与 kid 相同(在用法和值方面)。 x5t 是在 v1.0 访问令牌中仅出于兼容目的而发出的旧式声明。

有效负载声明

声明格式说明
aud字符串,一个应用 ID URI 或 GUID标识令牌的目标接收方 - 其受众。 你的 API 必须验证此值,如果值不匹配,则必须拒绝该令牌。 在 v2.0 令牌中,它始终是 API 的客户端 ID,而在 v1.0 令牌中,它可以是请求中使用的客户端 ID 或资源 URI,具体取决于客户端请求令牌的方式。
iss字符串,STS URI标识构造并返回令牌的安全令牌服务 (STS),以及对用户进行身份验证的 Azure AD 租户。 如果颁发的令牌是 v2.0 令牌(请参阅 ver 声明),则 URI 将以 /v2.0 结尾。 表示用户是来自 Microsoft 帐户的使用者用户的 GUID 为 9188040d-6c67-4c5b-b112-36a304b66dad。 应用可使用声明的 GUID 部分限制可登录应用的租户集(如果适用)。
idp字符串,通常是 STS URI记录对令牌使用者进行身份验证的标识提供者。 除非用户帐户与颁发者不在同一租户中,否则此值与颁发者声明的值相同 - 例如,来宾。 如果声明不存在,则意味着可以改用 iss 的值。 对于在组织上下文中使用的个人帐户(例如,受邀加入 Azure AD 租户的个人帐户),idp 声明可能是“live.com”或包含 Microsoft 帐户租户 9188040d-6c67-4c5b-b112-36a304b66dad 的 STS URI。
iatint,Unix 时间戳“Issued At”表示针对此令牌进行身份验证的时间。
nbfint,Unix 时间戳“nbf”(不早于)声明指定只能在哪个时间之后接受 JWT 的处理。
expint,Unix 时间戳“exp”(过期时间)声明指定只能在哪个时间(含)之前接受 JWT 的处理。 请务必注意,资源也可以在此时间之前拒绝令牌,例如,需要对身份验证进行更改,或者检测到令牌吊销时。
aio不透明字符串一个内部声明,Azure AD 用它来记录有关重复使用令牌的数据。 资源不应使用此声明。
acr字符串,“0”或“1”仅在 v1.0 令牌中提供。 “身份验证上下文类”声明。 值为“0”表示最终用户身份验证不符合 ISO/IEC 29115 要求。
amr字符串的 JSON 数组仅在 v1.0 令牌中提供。 标识对令牌使用者进行身份验证的方式。 有关更多详细信息,请参阅 amr 声明部分
appid字符串,GUID仅在 v1.0 令牌中提供。 使用令牌的客户端的应用程序 ID。 该应用程序可以自身名义或者代表用户进行操作。 应用程序 ID 通常表示应用程序对象,但它还可以表示 Azure AD 中的服务主体对象。
azp字符串,GUID仅在 v2.0 令牌中存在,取代了 appid。 使用令牌的客户端的应用程序 ID。 该应用程序可以自身名义或者代表用户进行操作。 应用程序 ID 通常表示应用程序对象,但它还可以表示 Azure AD 中的服务主体对象。
appidacr“0”、“1”或“2”仅在 v1.0 令牌中提供。 表示对客户端进行身份验证的方式。 对于公共客户端,值为“0”。 如果使用客户端 ID 和客户端机密,则值为“1”。 如果使用客户端证书进行身份验证,则值为“2”。
azpacr“0”、“1”或“2”仅在 v2.0 令牌中存在,取代了 appidacr。 表示对客户端进行身份验证的方式。 对于公共客户端,值为“0”。 如果使用客户端 ID 和客户端机密,则值为“1”。 如果使用客户端证书进行身份验证,则值为“2”。
preferred_username字符串表示用户的主用户名。 可以是电子邮件地址、电话号码或未指定格式的一般用户名。 其值是可变的,可能随时改变。 由于此值是可变的,因此它不能用于做出授权决定。 它可以用于用户名提示,但在人工可读的 UI 中用作用户名。 需要 profile 范围才能接收此声明。 仅在 v2.0 令牌中提供。
nameString提供一个用户可读值,用于标识令牌使用者。 该值不一定唯一,而且可变,只能用于显示目的。 需要 profile 范围才能接收此声明。
scp字符串,范围的空格分隔列表应用程序公开的、客户端应用程序已请求(和接收)其许可的范围集。 应用应该验证这些范围是否为应用公开的有效范围,并根据这些范围的值做出授权决策。 仅为用户令牌包含此值。
roles字符串数组、权限列表应用程序公开的、请求方应用程序或用户有权调用的权限集。 对于应用程序令牌,在执行客户端凭据流(v1.0v2.0)期间使用此声明代替用户范围。 对于用户令牌,使用用户在目标应用程序上分配的角色进行填充。
widsRoleTemplateID GUID 的数组表示从 Azure AD 内置角色中的角色部分分配给此用户的租户范围角色。 此声明通过groupMembershipClaims的 groupMembershipClaims 属性针对每个应用程序进行配置。 必须将其设置为“All”或“DirectoryRole”。 由于令牌长度方面的原因,它在通过隐式流获取的令牌中可能不存在。
groupsGUID 的 JSON 数组指定表示使用者的组成员身份的对象 ID。 这些值具有唯一性(请参阅对象 ID),可安全地用于管理访问,例如强制要求授权访问资源。 组声明中包含的组通过groupMembershipClaims的 groupMembershipClaims 属性基于每个应用程序进行配置。 值为 null 将排除所有组;值为“SecurityGroup”将只包括“Active Directory 安全组”成员身份;值为“All”将包括安全组和 Microsoft 365 通讯组列表。

有关将 groups 声明与隐式授权一起使用的详细信息,请参阅下文中的 hasgroups 声明。
对于其他流,如果用户所在的组数超出了某个限制(对于 SAML,为 150,对于 JWT,为 200),则会将超额声明添加到指向包含该用户的组列表的 Microsoft Graph 终结点的声明源。
hasgroupsBoolean如果存在,始终为 true,表示用户至少在一个组中。 如果完整组声明将导致 URI 片段超出 URL 长度限制(当前为 6 个或更多组),则在隐式授权流中用来替代 JWT 的 groups 声明。 指示客户端应当使用 Microsoft Graph API 来确定用户的组 (https://graph.microsoft.com/v1.0/users/{userID}/getMemberObjects)。
groups:src1JSON 对象对于长度不受限制(参阅上文中的 hasgroups)但对于令牌而言仍然太大的令牌请求,将包括指向用户的完整组列表的链接。 对于 JWT,作为分布式声明;对于 SAML,作为新声明替代 groups 声明。

JWT 值示例:
"groups":"src1"
"_claim_sources"src1" : { "endpoint" : "https://graph.microsoft.com/v1.0/users/{userID}/getMemberObjects" }
subString令牌针对其断言信息的主体,例如应用的用户。 此值固定不变,无法重新分配或重复使用。 可使用它安全地执行授权检查(例如,使用令牌访问资源时),并可将它用作数据库表中的键。 由于使用者始终会在 Azure AD 颁发的令牌中存在,我们建议在通用授权系统中使用此值。 但是,使用者是成对标识符 - 它对特定应用程序 ID 是唯一的。 因此,如果单个用户使用两个不同的客户端 ID 登录到两个不同的应用,这些应用将收到两个不同的使用者声明值。 这不一定是所需的,具体取决于体系结构和隐私要求。 另请参阅 oid 声明(在租户中的应用之间确实会保持相同)。
oid字符串,GUID请求的“主体”(身份已验证的用户或服务主体)的不可变标识符。 在 ID 令牌和应用+用户令牌中,此项是用户的对象 ID。 在仅限应用的令牌中,这是调用服务主体的对象 ID。 还可以使用它安全地执行授权检查,并将它用作数据库表中的键。 此 ID 唯一标识跨应用程序的主体 - 将同一用户登录的两个不同的应用程序会在 oid 声明中收到相同的值。 因此,对 Microsoft 联机服务(例如 Microsoft Graph)发出查询时可以使用 oid。 Microsoft Graph 将返回此 ID 作为给定id的 id 属性。 因为 oid 允许多个应用关联主体,所以需要 profile 范围才能为用户接收此声明。 如果单个用户存在于多个租户中,该用户将包含每个租户中的不同对象 ID - 它们将视为不同帐户,即使用户使用相同的凭据登录到每个帐户,也是如此。
tid字符串,GUID表示用户登录到的租户。 对于工作和学校帐户,该 GUID 就是用户登录到的组织的不可变租户 ID。 对于登录个人 Microsoft 帐户租户(Xbox、Teams for Life 或 Outlook 等服务)的情况,值为 9188040d-6c67-4c5b-b112-36a304b66dad。 若要接收此声明,你的应用必须请求 profile 范围。
unique_name字符串仅在 v1.0 令牌中提供。 提供一个用户可读值,用于标识令牌使用者。 不保证此值在租户中唯一,只应该用于显示目的。
uti字符串令牌标识符声明,等效于 JWT 规范中的 jti。 区分大小写的唯一每令牌标识符。
rh不透明字符串Azure 用来重新验证令牌的内部声明。 资源不应使用此声明。
ver字符串,1.0 或 2.0指示访问令牌的版本。

组超额声明

为了确保令牌大小不超过 HTTP 标头大小限制,Azure AD 对它包含在组声明中的对象 ID 数进行了限制。 如果用户所属的组数超过超额限制(SAML 令牌的为 150 个,JWT 令牌的为 200 个,通过隐式流颁发的令牌的仅为 6 个),则 Azure AD 不会在令牌中发出组声明。 但是,它会在令牌中包含超额声明,该声明指示应用程序查询 Microsoft Graph API 以检索用户的组成员身份。

{
  ...
  "_claim_names": {
   "groups": "src1"
    },
    {
  "_claim_sources": {
    "src1": {
        "endpoint":"[Url to get this user's group membership from]"
        }
       }
     }
  ...
}

可使用BulkCreateGroups.ps1文件夹中提供的 BulkCreateGroups.ps1 来帮助测试超额方案。

v1.0 基本声明

以下声明将包含在 v1.0 令牌中(如果适用),默认不会包含在 v2.0 令牌中。 如果使用 v2.0 并需要其中的某个声明,请使用可选声明来请求它们。

声明格式说明
ipaddrString进行身份验证的用户的来源 IP 地址。
onprem_sid字符串,采用 SID 格式如果用户使用了本地身份验证,则此声明会提供其 SID。 可在旧版应用程序中将 onprem_sid 用于授权。
pwd_expint,Unix 时间戳指示用户的密码何时过期。
pwd_urlString可向用户发送的,以重置其密码的 URL。
in_corpboolean表示客户端是否从企业网络登录。 如果不是,则不包括该声明。
nickname字符串用户的附加名称,不同于名字或姓氏。
family_nameString根据用户对象中的定义提供用户的姓氏。
given_name字符串根据用户对象中的设置提供用户的名字。
upnString用户的用户名。 可以是电话号码、电子邮件地址或无格式的字符串。 只应该用于显示目的,在重新身份验证方案中提供用户名提示。

amr 声明

Microsoft 标识可以通过与应用程序相关的不同方式进行身份验证。 amr 声明是可以包含多个项(例如 ["mfa", "rsa", "pwd"])的数组,适用于使用密码和 Authenticator 应用的身份验证。

说明
pwd密码身份验证,用户的 Microsoft 密码或应用的客户端机密。
rsa身份验证基于 RSA 密钥的证明,例如,使用 Microsoft Authenticator 应用。 这包括,身份验证是否是使用服务拥有的 X509 证书通过自签名的 JWT 执行的。
otp使用电子邮件或短信的一次性密码。
fed使用了联合身份验证断言(例如 JWT 或 SAML)。
wiaWindows 集成身份验证
mfa使用了多重身份验证。 如果存在这种情况,则也会包含其他身份验证方法。
ngcmfa等效于 mfa,用于预配某些高级凭据类型。
wiaormfa用户已使用 Windows 或 MFA 凭据进行身份验证。
none未执行任何身份验证。

访问令牌生存期

访问令牌的默认生存期是可变的。 发出后,将为访问令牌的默认生存期分配一个随机值,范围介于60-90 分钟之间(平均为 75 分钟)。 该变体通过在 60 到 90 分钟的时间内分散访问令牌需求来提高服务复原能力,从而防止 Azure AD 的流量每小时出现峰值。

对于 Microsoft Teams 和 Microsoft 365 等客户端,不使用条件访问的租户的默认访问令牌生存期为 2 小时。

可以调整访问令牌的生存期,控制客户端应用程序使应用程序会话过期的频率,以及它要求用户重新进行身份验证(以无提示方式或交互方式)的频率。 客户如果希望替代默认访问令牌生存期变体,则可使用可配置的令牌生成器 (CTL) 设置静态默认访问令牌生存期。

默认令牌生存期变体适用于启用了连续访问评估 (CAE) 的组织,即使配置了 CTL 策略也是如此。 长期令牌生存期的默认令牌生存期范围为 20 到 28 小时。 访问令牌过期后,客户端必须使用刷新令牌(通常以无提示方式)获取新的刷新令牌和访问令牌。

组织如果使用条件访问登录频率 (SIF) 来执行登录发生的频率,则不能替代默认访问令牌生存期变体。 使用 SIF 时,客户端凭据提示之间的时间是令牌生命周期(范围为 60 - 90 分钟)加上登录频率间隔。

下面举例说明了默认令牌生命周期变体如何与登录频率配合使用。 假设组织将登录频率设置为每小时一次。 由于令牌的生存期为 60-90 分钟(由于令牌生存期变体),实际登录间隔将发生在 1 小时到 2.5 小时之间。

如果持有生存期为 1 小时的令牌的用户在 59 分钟(恰好在超过登录频率之前)执行交互式登录,则不会出现凭据提示,因为登录低于 SIF 阈值。 如果颁发的新令牌的生存期为 90 分钟,则用户将在一个半小时内看不到凭据提示。 当尝试对 90 分钟令牌生存期进行无提示续订时,Azure AD 将需要凭据提示,因为总会话长度已超过 1 小时的登录频率设置。 在此示例中,由于 SIF 间隔和令牌生存期变体导致的凭据提示之间的时间差将为 2.5 小时。

验证令牌

并非所有应用都应当验证令牌。 只有在特定的场景中,应用才应当验证令牌:

  • Web API 必须验证由客户端发送给它们的访问令牌。 它们只能接受包含其 aud 声明的令牌。

  • 机密 Web 应用(例如 ASP.NET Core)必须通过混合流中的用户浏览器验证发送给它们的 ID 令牌,然后才允许访问用户的数据或建立会话。

如果上述方案均不适用,则对令牌进行验证对你的应用程序无益,而如果根据令牌的有效性做出决策,则可能会带来安全和可靠性方面的风险。 对令牌进行验证对公共客户端(例如原生应用或 SPA)无益 - 应用会直接与 IDP 进行通信,因此 SSL 保护可确保令牌有效。

API 和 Web 应用只能验证其中的 aud 声明与其应用程序匹配的令牌;其他资源可能有自定义令牌验证规则。 例如,Microsoft Graph 的令牌不会根据这些规则进行验证,因为它们采用了专有格式。 验证和接受用于另一个资源的令牌是混淆代理问题的一个示例。

如果应用程序需要根据以上说明验证 id_token 或 access_token,则应用应首先根据 OpenID 发现文档中的值来验证令牌的签名和颁发者。 例如,文档的租户独立版本位于 https://login.microsoftonline.com/common/.well-known/openid-configuration

我们为那些希望了解基础过程的用户提供了以下信息。 Azure AD 中间件具有验证访问令牌的内置功能,可以浏览我们的示例,以所选语言进行查找。 另外还有多个第三方开源库可用于 JWT 验证 - 几乎每个平台和语言都至少有一个选项。 有关 Azure AD 身份验证库和代码示例的详细信息,请参阅身份验证库

验证签名

JWT 包含三个段(以 . 字符分隔)。 第一个段称为标头,第二个称为主体,第三个称为签名。 签名段可用于验证令牌的真实性,使令牌可获得应用的信任。

Azure AD 颁发的令牌已使用行业标准非对称式加密算法(例如 RS256)进行签名。 JWT 的标头包含用于签名令牌的密钥和加密方法的相关信息:

{
  "typ": "JWT",
  "alg": "RS256",
  "x5t": "iBjL1Rcqzhiy4fpxIxdZqohM2Yk",
  "kid": "iBjL1Rcqzhiy4fpxIxdZqohM2Yk"
}

alg 声明表示用于对令牌进行签名的算法,而 kid 声明表示用于验证令牌的特定公钥。

在任何给定时间点,Azure AD 可以使用特定公钥 - 私钥对中的任何一组对 id_token 进行签名。 Azure AD 会定期滚动更新一组可能的密钥,因此应将应用编写成自动处理这些密钥更改。 对 Azure AD 所用公钥的更新进行检查的合理频率为每 24 小时一次。

可以使用位于以下位置的 OpenID Connect 元数据文档来获取验证签名所需的签名密钥数据:

https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration

提示

在浏览器中尝试打开此 URL

此元数据文档:

  • 是一个 JSON 对象,其中包含一些有用的信息,例如执行 OpenID Connect 身份验证所需的各种终结点的位置。

  • 包含 jwks_uri,提供公钥集的位置,这些公钥对应于那些用于对令牌进行签名的私钥。 位于 jwks_uri 的 JSON Web 密钥 (JWK) 包含在该特定时间点使用的所有公钥信息。 RFC 7517 中对 JWK 格式进行了说明。 你的应用可以使用 JWT 标头中的 kid 声明从本文档中选择公钥,该公钥对应于已用于对某个特定令牌签名的私钥。 然后可以使用正确的公钥和指定的算法来执行签名验证。

注意

我们建议使用 kid 声明来验证令牌。 虽然 v1.0 令牌同时包含 x5t 和 kid 声明,但 v2.0 令牌仅包含 kid 声明。

执行签名验证超出了本文档的范围 - 有许多开放源代码库可帮助这么做(如有必要)。 但是,Microsoft 标识平台有一个针对标准的令牌签名扩展 - 自定义签名密钥。

如果应用使用声明映射功能后生成了自定义签名密钥,则必须附加包含应用 ID 的 查询参数,以获取指向应用的签名密钥信息的 jwks_uri,该信息应用于验证。 例如:https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration?appid=6731de76-14a6-49ae-97bc-6eba6914391e 包含 https://login.microsoftonline.com/{tenant}/discovery/keys?appid=6731de76-14a6-49ae-97bc-6eba6914391e 的 jwks_uri

基于声明的授权

应用程序的业务逻辑将会强制规定此步骤,下面列出了一些常见的授权方法。

验证令牌是否适合你

  • 使用 aud 声明来确保该用户打算调用你的应用程序。 如果资源的标识符不在 aud 声明内,请拒绝它。

验证用户是否有权访问此数据

  • 使用 roles 和 wids 声明来验证用户本身是否获得了调用你的 API 的授权。 例如,管理员可能有权写入到你的 API,但普通用户不行。

  • 检查令牌中的 tid 是否与用于在你的 API 中存储数据的租户 ID 匹配。

    • 当用户将来自一个租户的数据存储在你的 API 中时,他们必须再次登录该租户才能访问该数据。 请勿允许从一个租户访问另一个租户的数据。

  • 使用 amr 声明验证已执行 MFA 的用户。 应使用条件访问强制实施此步骤。

  • 如果在访问令牌中请求了 roles 或 groups 声明,请验证用户是否在允许执行此操作的组中。

    • 对于使用隐式流检索的令牌,可能需要在 Microsoft Graph 中查询此数据,因为该数据通常很庞大,无法放到令牌中。

请勿使用 或 upn 声明值来确定访问令牌中的用户是否应有权访问数据! 此类可变声明值可能会随着时间的推移而更改,使其不安全且不可靠,无法进行授权。

请勿使用不可变声明值 和 sub 或 oid 作为组合键来存储以唯一标识你的 API 数据并确定是否应授予用户访问该数据的权限。

  • 可行:tid + sub

  • 更佳:tid + oid - 例如 oid 在各应用程序之间是一致的,因此应用的生态系统可以审核用户对数据的访问。

请勿使用可变的、人类可读的标识符(如 或 upn)来唯一标识数据。

  • 糟糕:email

  • 糟糕:upn

验证已使用户登录的应用程序是否有权访问此数据

  • 使用 scp 声明来验证该用户是否已向调用应用授予了调用你的 API 的权限。

  • 确保允许调用方客户端使用 appid 声明调用你的 API。

用户和应用程序令牌

应用程序可以为用户(经常讨论的流)或直接从应用程序(通过客户端凭据流)接收令牌。 这些仅限应用的令牌表示这种调用来自应用程序,而没有支持它的用户。 这些令牌的处理方式大致相同:

  • 使用 roles 查看已授予令牌使用者的权限。

  • 使用 oid 或 sub 来验证调用服务主体是否是预期的服务主体。

如果应用需要区分仅限应用的访问令牌和用户的访问令牌,请使用idtypidtyp。 通过将 idtyp 声明添加到 accessToken 字段,并检查值 app,可以检测仅限应用的访问令牌。 用户的 ID 令牌和访问令牌不包含 idtyp 声明。

令牌吊销

刷新令牌可能由于不同的原因而随时失效或吊销。 这些原因主要分为两个类别:超时和吊销。

令牌超时

使用令牌生存期配置,可以更改刷新令牌的生存期。 一些令牌未被使用(例如,用户在 3 个月内未打开应用)就过期了,这是正常现象,也在预料之中。 应用将遇到这样的情况:登录服务器会因时间问题而拒绝刷新令牌。

  • MaxInactiveTime:如果在 MaxInactiveTime 指定的时间内未使用刷新令牌,刷新令牌将不再有效。

  • MaxSessionAge:如果 MaxAgeSessionMultiFactor 或 MaxAgeSessionSingleFactor 已设置为其默认值(“直到吊销”)以外的值,则在经过 MaxAgeSession* 中设置的时间后,需要重新进行身份验证。

  • 示例:

    • 租户的 MaxInactiveTime 为 5 天,用户去度假一周,因此 Azure AD 在 7 天内未看到用户发出的新令牌请求。 下次用户请求新令牌时,他们将看到其刷新令牌已被吊销,他们必须重新输入其凭据。

    • 敏感应用程序的 MaxAgeSessionSingleFactor 为 1 天。 如果用户在星期一登录,则在星期二(25 个小时后),他们需要重新进行身份验证。

撤销

服务器可能会由于以下原因而撤销刷新令牌:凭据发生更改,或者用户或管理员执行了相关操作。 刷新令牌分为两类:颁发给机密客户端的刷新令牌(最右边的列),和颁发给公共客户端的刷新令牌(所有其他列)。

更改基于密码的 Cookie基于密码的令牌不基于密码的 Cookie不基于密码的令牌机密客户端令牌
密码过期一直有效一直有效一直有效一直有效一直有效
用户更改了密码已撤销已撤销一直有效一直有效一直有效
用户执行 SSPR已撤销已撤销一直有效一直有效一直有效
管理员重置密码已撤销已撤销一直有效一直有效一直有效
用户通过 PowerShell 撤销刷新令牌已撤销已撤销已撤销已撤销已撤销
管理员通过 PowerShell 撤销用户的所有刷新令牌已撤销已撤销已撤销已撤销已撤销
Web 上的单一注销(v1.0v2.0已撤销一直有效已撤销一直有效一直有效

不基于密码

“不基于密码”登录是指用户在未键入密码的情况下登录。 “不基于密码”登录的示例包括:

  • 在 Windows Hello 中使用人脸

  • FIDO2 密钥

  • SMS

  • 语音

  • PIN

请查看主刷新令牌,了解有关主刷新令牌的更多详细信息。

后续步骤


来自  https://docs.microsoft.com/zh-cn/azure/active-directory/develop/access-tokens


普通分类: