警告
本内容适用于较旧版本的 Azure AD v1.0 终结点。 将 Microsoft标识平台 用于新项目。
OpenID Connect 是基于 OAuth 2.0 协议构建的简单标识层。 OAuth 2.0 定义了用于获取和使用 访问令牌 访问受保护资源的机制,但它们未定义提供标识信息的标准方法。 OpenID Connect 将身份验证作为 OAuth 2.0 授权过程的扩展实现。 它以 id_token
的形式提供有关最终用户的信息,用于验证用户的标识并提供有关用户的基本配置文件信息。
如果要构建托管在服务器上并通过浏览器访问的 Web 应用程序,则 OpenID Connect 是我们的建议。
将应用程序注册到您的 AD 租户
首先,将应用程序注册到 Azure Active Directory (Azure AD) 租户。 这将为你的应用程序提供一个应用程序 ID,并使它能够接收令牌。
登录到 Azure 门户。
选择 Azure AD 租户,方法是在页面右上角选择帐户,然后选择 “切换目录 ”导航,然后选择相应的租户。
- 如果帐户下只有一个 Azure AD 租户,或者已选择相应的 Azure AD 租户,请跳过此步骤。
在 Azure 门户中,搜索并选择 Azure Active Directory。
在 Azure Active Directory 左侧菜单中,选择 “应用注册”,然后选择“ 新建注册”。
按照提示进行操作并创建新应用程序。 本教程的 Web 应用程序或公共客户端(移动和桌面)应用程序并不重要,但如果想要 Web 应用程序或公共客户端应用程序的特定示例,请查看 我们的快速入门。
- 名称 是应用程序名称,并向最终用户描述应用程序。
- 在“支持的帐户类型”下,选择“任何组织目录中的帐户和个人 Microsoft 帐户”。
- 提供 重定向 URI。 对于 Web 应用程序,这是用户可以登录的应用的基本 URL。 例如,
http://localhost:12345
。 对于公共客户端(移动 & 桌面),Azure AD 使用它返回令牌响应。 输入特定于应用程序的值。 例如,http://MyFirstAADApp
。
完成注册后,Azure AD 将为应用程序分配唯一的客户端标识符( 应用程序 ID)。 在下一部分中需要此值,因此请从应用程序页复制此值。
若要在 Azure 门户中查找应用程序,请选择 “应用注册”,然后选择“ 查看所有应用程序”。
使用 OpenID Connect 的身份验证流
最基本的登录流包含以下步骤 - 下面详细介绍了每个登录流。
OpenID Connect 元数据文档
OpenID Connect 描述一个元数据文档,其中包含应用执行登录所需的大部分信息。 这包括要使用的 URL 和服务公共签名密钥的位置等信息。 可在以下位置找到 OpenID Connect 元数据文档:
https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration
元数据是一个简单的 JavaScript 对象表示法(JSON)文档。 有关示例,请参阅以下代码片段。 此代码片段的内容在 openID Connect 规范 中完全描述。 请注意,提供租户 ID 而不是 common
代替上述 {tenant} 将导致返回 JSON 对象中特定于租户的 URI。
{
"authorization_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/authorize",
"token_endpoint": "https://login.microsoftonline.com/{tenant}/oauth2/token",
"token_endpoint_auth_methods_supported":
[
"client_secret_post",
"private_key_jwt",
"client_secret_basic"
],
"jwks_uri": "https://login.microsoftonline.com/common/discovery/keys"
"userinfo_endpoint":"https://login.microsoftonline.com/{tenant}/openid/userinfo",
...
}
如果应用由于使用 声明映射 功能而具有自定义签名密钥,则必须追加包含 appid
应用 ID 的查询参数,才能获取 jwks_uri
指向应用的签名密钥信息。 例如:https://login.microsoftonline.com/{tenant}/.well-known/openid-configuration?appid=6731de76-14a6-49ae-97bc-6eba6914391e
包含 jwks_uri
的 https://login.microsoftonline.com/{tenant}/discovery/keys?appid=6731de76-14a6-49ae-97bc-6eba6914391e
。
发送登录请求
当 Web 应用程序需要对用户进行身份验证时,它必须将用户定向到 /authorize
终结点。 此请求类似于 OAuth 2.0 授权代码流的第一回合,但有一些重要的区别:
- 请求必须在
openid
参数中包含范围scope
。 -
response_type
参数必须包含id_token
。 - 请求必须包含
nonce
参数。
因此,示例请求如下所示:
// Line breaks for legibility only
GET https://login.microsoftonline.com/{tenant}/oauth2/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e
&response_type=id_token
&redirect_uri=http%3A%2F%2Flocalhost%3a12345
&response_mode=form_post
&scope=openid
&state=12345
&nonce=7362CAEA-9CA5-4B43-9BA3-34D7C303EBA7
参数 | 类型 | 说明 |
---|---|---|
租户 | 必填 | 请求路径中的 {tenant} 值可用于控制登录应用程序的用户。 允许的值是租户标识符,例如,用于租户无关令牌的 8eaef023-2b34-4da1-9baa-8bc8c9d6a490 、contoso.onmicrosoft.com 或 common 。 |
客户端ID | 必填 | 您在注册应用程序到 Azure AD 时所分配的应用程序 ID。 可以在 Azure 门户中找到此信息。 单击 Azure Active Directory,单击 “应用注册”,选择应用程序并在应用程序页上找到应用程序 ID。 |
response_type(响应类型) | 必填 | 必须包含用于 OpenID Connect 登录的 id_token 。 它还可能包括其他response_types,如 code 或 token 。 |
范围 | 推荐 | OpenID Connect 规范要求范围 openid ,该范围转换为许可 UI 中的“登录”权限。 在 v1.0 终结点上,此 OIDC 范围和其他范围被忽略,但对于符合标准的客户端来说,仍然是最佳实践。 |
nonce | 必填 | 由应用生成且包含在请求中的值,以声明方式包含在生成的 id_token 中。 然后,应用可以验证此值,以减少令牌重播攻击。 该值通常是随机的、唯一的字符串或 GUID,可用于标识请求的源。 |
重定向URI | 推荐 | 您的应用程序的 redirect_uri,应用程序可在此处发送和接收身份验证响应。 它必须与您在门户中注册的某个 redirect_uris 完全匹配,但 URL 必须进行编码。 如果缺失,用户代理将被随机发回至应用注册的某个重定向 URI。 最大长度为 255 字节 |
响应模式 | 自选 | 指定用于将生成的授权代码发送回应用程序的方法。 支持的值适用于 form_post HTTP 表单帖子 和 fragment URL 片段。 对于 Web 应用程序,我们建议使用 response_mode=form_post 来确保将令牌安全传输到应用程序。 包含id_token的任何流的默认值为 fragment 。 |
州 | 推荐 | 请求中包含的一个值,随令牌响应返回。 任何你想要的内容都可以成为一个字符串。 随机生成的唯一值通常用于 防止跨站点请求伪造攻击。 该状态也用于在身份验证请求出现之前,对应用中用户的状态信息进行编码,例如用户之前浏览的网页或视图。 |
提示 | 自选 | 表示需要的用户交互类型。 目前,唯一有效的值为“login”、“none”和“consent”。
prompt=login 强制用户在该请求上输入其凭据,从而否定单一登录。
prompt=none 相反 - 它可确保用户不会显示任何交互式提示。 如果无法通过单一登录以无提示方式完成请求,终结点将返回错误。
prompt=consent 在用户登录后触发 OAuth 同意对话框,要求用户向应用授予权限。 |
登录提示 | 自选 | 如果您提前知道用户的用户名,可以用于预先填充登录页面的用户名或电子邮件地址字段。 通常,应用在重新身份验证期间使用此参数,并且已使用 preferred_username 声明从以前的登录中提取用户名。 |
此时,系统会要求用户输入凭据并完成身份验证。
示例响应
在用户进行身份验证后,发送到登录请求中指定的 redirect_uri
的示例响应可能如下所示:
POST / HTTP/1.1
Host: localhost:12345
Content-Type: application/x-www-form-urlencoded
id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNB...&state=12345
参数 | 说明 |
---|---|
id_token(身份令牌) | 应用请求的 id_token 。 可以使用 id_token 来验证用户的标识,并开始与用户进行会话。 |
州 | 请求中包含的一个值,也在令牌响应中返回。 随机生成的唯一值通常用于 防止跨站点请求伪造攻击。 该状态也用于在身份验证请求出现之前,对应用中用户的状态信息进行编码,例如用户之前浏览的网页或视图。 |
错误响应
错误响应可能也发送到 redirect_uri
,让应用可以适当地处理:
POST / HTTP/1.1
Host: localhost:12345
Content-Type: application/x-www-form-urlencoded
error=access_denied&error_description=the+user+canceled+the+authentication
参数 | 说明 |
---|---|
错误 | 可用于分类错误类型并响应错误的错误码字符串。 |
错误描述 | 帮助开发人员识别身份验证错误根本原因的特定错误消息。 |
授权终结点错误的错误代码
下表描述了可在错误响应的 error
参数中返回的各个错误代码。
错误代码 | 说明 | 客户行动 |
---|---|---|
无效请求 | 协议错误,例如,缺少必需的参数。 | 修复并重新提交请求。 这是一个开发错误,通常在初步测试时发现。 |
未授权的客户端 | 不允许客户端应用程序请求授权代码。 | 当客户端应用程序未在 Azure AD 中注册或未添加到用户的 Azure AD 租户时,通常会发生这种情况。 应用程序可以通过提供安装说明来提示用户进行应用程序的安装,并将其添加到 Azure AD。 |
拒绝访问 | 资源所有者拒绝了许可 | 除非用户同意,否则客户端应用程序可以通知用户无法继续。 |
不支持的响应类型 | 授权服务器不支持请求中的响应类型。 | 修复并重新提交请求。 这是一个开发错误,通常在初步测试时发现。 |
服务器错误 | 服务器遇到意外的错误。 | 重试请求。 这些错误可能是临时状况导致的。 客户端应用程序可能会向用户解释其响应因临时错误而延迟。 |
暂时不可用 | 服务器暂时繁忙,无法处理请求。 | 重试请求。 客户端应用程序可能会向用户解释,其响应因临时条件而延迟。 |
资源无效 | 目标资源无效,因为它不存在,Azure AD 找不到它,或者未正确配置。 | 这表示资源(如果存在)尚未在租户中配置。 应用程序可以通过提供安装说明来提示用户进行应用程序的安装,并将其添加到 Azure AD。 |
验证 id_token
仅接收 id_token
不足以对用户进行身份验证;必须根据应用的要求验证签名并验证 id_token
中的声明。 Azure AD 终结点使用 JSON Web 令牌(JWT)和公钥加密来对令牌进行签名并验证它们是否有效。
可以选择在客户端代码中验证 id_token
,但一种常见做法是将 id_token
发送到后端服务器并在那里执行验证。
你可能还希望根据方案验证其他声明。 一些常见的验证包括:
- 确保用户/组织已注册应用。
- 使用
wids
或roles
声明确保用户具有适当的授权/权限。 - 为了确保已达到某种身份验证的力度,例如采用多重身份验证。
验证 id_token
后,可以开始与用户进行会话,并使用 id_token
中的声明获取应用中用户的相关信息。 此信息可用于显示、记录、个性化等。有关 id_tokens
和声明的详细信息,请阅读 AAD id_tokens。
发送注销请求
如果想要将用户从应用注销,则清除应用的 Cookie 或结束与用户的会话是不够的。 还必须将用户重定向到 end_session_endpoint
进行注销。如果未能执行此操作,用户将能够重新对应用进行身份验证,而无需再次输入其凭据,因为他们将在 Azure AD 终结点拥有一个有效的单一登录会话。
只需将用户重定向到 OpenID Connect 元数据文档中列出的 end_session_endpoint
:
GET https://login.microsoftonline.com/common/oauth2/logout?
post_logout_redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
参数 | 类型 | 说明 |
---|---|---|
登出后重定向URI | 推荐 | 成功注销后,用户应重定向到的 URL。此 URL 必须与在应用注册门户中为应用程序注册的重定向 URI 之一匹配。 如果未包含 post_logout_redirect_uri ,则用户会显示一条通用消息。 |
单一登录
将用户重定向到 end_session_endpoint
时,Azure AD 会从浏览器中清除用户的会话。 但是,用户仍可能登录到使用 Azure AD 进行身份验证的其他应用程序。 为了使这些应用程序能够同时注销用户,Azure AD 会将 HTTP GET 请求发送到用户当前登录到的所有应用程序的已注册 LogoutUrl
。 应用程序必须通过清除任何标识用户的会话并返回 200
响应来响应此请求。 如果要在应用程序中支持单一注销,则必须在应用程序的代码中实现此类 LogoutUrl
。 可以从 Azure 门户设置 LogoutUrl
:
- 登录到 Azure 门户。
- 单击页面右上角的帐户,选择 Active Directory。
- 在左侧导航面板中,依次选择 “Azure Active Directory”、“ 应用注册 ”和“应用程序”。
- 单击 “设置”,然后单击 “属性 ”并找到 “注销 URL ”文本框。
令牌获取
许多 Web 应用不仅需要让用户登录,还需要代表该用户使用 OAuth 访问 Web 服务。 此方案结合使用 OpenID Connect 进行用户身份验证,同时获取一个 authorization_code
,该 authorization_code
可用于通过 OAuth 授权代码流 来获取 access_tokens
。
获取访问令牌
若要获取访问令牌,需要从上面修改登录请求:
// Line breaks for legibility only
GET https://login.microsoftonline.com/{tenant}/oauth2/authorize?
client_id=6731de76-14a6-49ae-97bc-6eba6914391e // Your registered Application ID
&response_type=id_token+code
&redirect_uri=http%3A%2F%2Flocalhost%3a12345 // Your registered Redirect Uri, url encoded
&response_mode=form_post // `form_post' or 'fragment'
&scope=openid
&resource=https%3A%2F%2Fservice.contoso.com%2F // The identifier of the protected resource (web API) that your application needs access to
&state=12345 // Any value, provided by your app
&nonce=678910 // Any value, provided by your app
通过在请求中包含权限范围并使用 response_type=code+id_token
,authorize
终结点可确保用户已同意 scope
查询参数中指示的权限,并返回应用一个授权代码来交换访问令牌。
成功的响应
使用 redirect_uri
发送到 response_mode=form_post
的成功响应如下所示:
POST /myapp/ HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik1uQ19WWmNB...&code=AwABAAAAvPM1KaPlrEqdFSBzjqfTGBCmLdgfSTLEMPGYuNHSUYBrq...&state=12345
参数 | 说明 |
---|---|
身份令牌 | 应用请求的 id_token 。 可以使用 id_token 来验证用户的标识,并开始与用户进行会话。 |
代码 | 应用请求的 authorization_code。 应用可以使用授权代码请求目标资源的访问令牌。 Authorization_codes生存期较短,通常在大约 10 分钟后过期。 |
州 | 如果请求中包含 state 参数,响应中就应该出现相同的值。 应用应该验证请求和响应中的 state 值是否完全相同。 |
错误响应
错误响应可能也发送到 redirect_uri
,让应用可以适当地处理:
POST /myapp/ HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
error=access_denied&error_description=the+user+canceled+the+authentication
参数 | 说明 |
---|---|
错误 | 可用于分类错误类型并响应错误的错误码字符串。 |
错误描述 | 帮助开发人员识别身份验证错误根本原因的特定错误消息。 |
有关可能的错误代码及其建议的客户端作的说明,请参阅 授权终结点错误的错误代码。
一旦获得code
和id_token
授权后,就可以代表用户签入并获取访问令牌。 若要登录用户,必须验证 id_token
,具体如上所述。 若要获取访问令牌,可以按照 OAuth 代码流文档中的“使用授权代码请求访问令牌”部分中所述的步骤进行作。
后续步骤
- 详细了解 访问令牌。
-
详细了解
id_token
和索赔。