使用 Azure Active Directory B2C 在示例 Node.js Web API 中配置身份验证
本文介绍如何配置一个示例 Node.js Web 应用程序以调用示例 Node.js Web API。 该 Web API 需要由 Azure AD B2C 本身提供保护。 在此设置中,某个 Web 应用(例如“应用 ID:1”)将调用某个网络 API(例如“应用 ID:2”)。 用户在该 Web 应用中进行身份验证以获取访问令牌,该令牌随后用于调用受保护的 Web API。
概述
基于令牌的身份验证确保对 Web API 的请求附带有效的访问令牌。
该 Web 应用完成以下事件:
通过 Azure AD B2C 对用户进行身份验证。
获取一个具有对 Web API 终结点的必需权限(作用域)的访问令牌。
在 HTTP 请求的身份验证标头中将该访问令牌作为持有者令牌进行传递。 它使用以下格式:
Authorization: Bearer <token>
该 Web API 完成以下事件:
从 HTTP 请求中的授权标头读取持有者令牌。
验证该令牌。
验证令牌中的权限(作用域)。
响应 HTTP 请求。 如果令牌无效,则 Web API 终结点将以
401 Unauthorized
HTTP 错误做出响应。
应用注册概述
要使应用能够通过 Azure AD B2C 登录并调用 Web API,必须在 Azure AD B2C 目录中注册两个应用程序。
Web 应用注册能让你的应用使用 Azure AD B2C 登录。 在注册过程中,请指定重定向 URI。 重定向 URI 是用户完成身份验证之后 Azure AD B2C 将用户重定向到的终结点。 此应用注册过程会生成应用程序 ID(也称为“客户端 ID”),将其作为该应用的唯一标识。 你还将为应用生成客户端机密。 应用使用该客户端机密交换访问令牌的授权代码。
Web API 注册可使应用调用安全的 Web API。 注册内容包括 Web API 的作用域。 作用域提供了一种方法来管理受保护资源(例如你的 Web API)的访问权限。 你可以向 Web API 的作用域授予 Web 应用访问权限。 在请求访问令牌时,你的应用需要在请求的作用域参数中指定所需的访问权限。
下图描绘了应用程序注册和应用程序体系结构:
先决条件
Visual Studio Code 或其他代码编辑器。
步骤 1:配置用户流
当用户尝试登录你的应用时,该应用会通过用户流向授权终结点发起身份验证请求。 用户流定义并控制用户体验。 用户完成用户流后,Azure AD B2C 会生成一个令牌,然后将用户重定向回应用程序。
请创建用户流或自定义策略(如果你尚未这样做)。 重复这些步骤以按如下所述创建三个单独的用户流:
- 组合的“登录和注册”用户流,例如
susi
。 此用户流还支持“忘记密码”体验。 - “个人资料编辑”用户流,例如
edit_profile
。 - “密码重置”用户流,例如
reset_password
。
Azure AD B2C 将在用户流名称前面追加 B2C_1_
。 例如,susi
重命名为 B2C_1_susi
。
步骤 2:注册 Web 应用和 API
在此步骤中,你将创建 Web 和 Web API 应用程序注册,并指定 Web API 的范围。
步骤 2.1:注册 Web API 应用程序
请按照以下步骤创建 Web API 应用注册(应用 ID: 2):
登录 Azure 门户。
确保正在使用的目录包含 Azure AD B2C 租户。 在门户工具栏中选择“目录 + 订阅”图标。
在“门户设置 | 目录+订阅”页上的“目录名称”列表中找到你的 Azure AD B2C 目录,然后选择“切换”。
在 Azure 门户中,搜索并选择“Azure AD B2C”。
选择“应用注册”,然后选择“新建注册” 。
对于名称,请输入应用程序的名称(例如 my-api1) 。 保留“重定向 URI”和“支持的帐户类型”的默认值。
选择“注册”。
完成应用注册后,选择“概述”。
记录“应用程序(客户端) ID”值,以便在稍后配置 Web 应用程序时使用。
步骤 2.2:配置作用域
选择所创建的 my-api1 应用程序(应用 ID:2)以打开其“概述”页面 。
在“管理”下,选择“公开 API” 。
选择“应用程序 ID URI”旁边的“设置”链接。 将默认值 (GUID) 替换为一个唯一名称(例如“tasks-api”),然后选择“保存”。
Web 应用在请求 Web API 的访问令牌时,应将此 URI 添加为你为 API 定义的每个范围的前缀。
在“此 API 定义的范围”下选择“添加范围”。
若要创建一个用于定义对 API 的读取访问权限的范围,请执行以下操作:
- 对于“范围名称”,输入“tasks.read” 。
- 对于“管理员同意显示名称”,输入“对任务 API 的读取访问权限” 。
- 对于“管理员同意说明”,输入“允许对任务 API 进行读取访问” 。
选择“添加作用域”。
选择“添加范围”,然后添加一个用于定义对 API 的写入访问权限的范围:
- 对于“范围名称”,输入“tasks.write” 。
- 对于“管理员同意显示名称”,“对任务 API 的写入访问权限” 。
- 对于“管理员同意说明”,输入“允许对任务 API 进行写入访问” 。
选择“添加作用域”。
步骤 2.3:注册 Web 应用
要创建 SPA 注册,请执行以下操作:
- 登录 Azure 门户。
- 如果有权访问多个租户,请选择顶部菜单中的“设置”图标,切换到“目录 + 订阅”菜单中的 Azure AD B2C 租户。
- 搜索并选择“Azure AD B2C”。
- 选择“应用注册”,然后选择“新建注册” 。
- 输入应用程序的名称(例如“应用 ID:1”)。
- 在“支持的帐户类型”下,选择“任何标识提供者或组织目录中的帐户(用于通过用户流对用户进行身份验证)” 。
- 在“重定向 URI”下,选择“Web”,然后在 URL 文本框中输入
http://localhost:3000/redirect
- 在“权限”下,选中“授予对 OpenID 和脱机访问权限的管理员许可”复选框。
- 选择“注册” 。
步骤 2.4:创建客户端机密
- 在“Azure AD B2C - 应用注册”页中,选择你创建的应用程序,例如“应用 ID:1”。
- 在左侧菜单中“管理”下,选择“证书和机密”。
- 选择“新建客户端机密”。
- 在“说明”框中输入客户端机密的说明。 例如,clientsecret1。
- 在“过期时间”下,选择机密持续生效的时间,然后选择“添加”。
- 记录密码的值,以便在客户端应用程序代码中使用。 退出此页面后,此机密值永不再显示。 在应用程序的代码中将此值用作应用程序机密。
步骤 2.5:向 Web 应用授予 API 权限
若要向应用(应用 ID:1)授予权限,请执行以下步骤:
选择“应用注册”,然后选择你所创建的应用(应用 ID:1) 。
在“管理”下选择“API 权限”。
在“已配置权限”下,选择“添加权限”。
选择“我的 API”选项卡。
选择应授予 Web 应用程序访问权限的 API(应用 ID:2)。 例如,输入“my-api1”。
在“权限”下展开“任务”,然后选择之前定义的范围(例如,tasks.read 和 tasks.write )。
选择“添加权限”。
选择“向<租户名称>授予管理员许可”。
选择 “是” 。
选择“刷新”,然后验证两个范围的“状态”下是否均显示“已授予...” 。
从“配置权限”列表中,选择范围,然后复制范围全名。
步骤 3:获取 Web 应用示例代码
此示例演示 Web 应用程序如何使用 Azure AD B2C 来实现用户注册和登录。 然后,该应用将获取访问令牌并调用受保护的 Web API。
若要获取 Web 应用示例代码,可以执行以下操作之一:
下载 ZIP 文件。 解压缩 zip 文件以获取示例 Web 应用。
通过运行以下命令,从 GitHub 克隆该示例代码:
git clone https://github.com/Azure-Samples/active-directory-b2c-msal-node-sign-in-sign-out-webapp.git
步骤 3.1:安装应用依赖项
打开控制台窗口,切换到包含 Node.js 示例应用的目录。 例如:
cd active-directory-b2c-msal-node-sign-in-sign-out-webapp/call-protected-api
运行以下命令以安装应用依赖项:
npm install && npm update
步骤 3.2:配置示例 Web 应用
在代码编辑器(例如 Visual Studio Code)中打开 Web 应用。 打开 call-protected-api
文件夹下的 .env
文件。 此文件包含有关 Azure AD B2C 标识提供者的信息。 更新以下应用设置:
密钥 | 值 |
---|---|
APP_CLIENT_ID |
在步骤 2.3 中注册的 Web 应用的“应用程序(客户端) ID”。 |
APP_CLIENT_SECRET |
在步骤 2.4 中创建的 Web 应用的客户端密码值 |
SIGN_UP_SIGN_IN_POLICY_AUTHORITY |
在步骤 1 中创建的用户流经的“登录和注册”用户流机构(例如 https://<your-tenant-name>.b2clogin.cn/<your-tenant-name>.partner.onmschina.cn/<sign-in-sign-up-user-flow-name> )。 请将 <your-tenant-name> 替换为你的租户的名称,将 <sign-in-sign-up-user-flow-name> 替换为你的“登录和注册”用户流的名称,例如 B2C_1_susi 。 了解如何获取租户名称。 |
AUTHORITY_DOMAIN |
Azure AD B2C 机构域,例如 https://<your-tenant-name>.b2clogin.cn 。 将 <your-tenant-name> 替换为租户的名称。 |
APP_REDIRECT_URI |
应用程序重定向 URI,Azure AD B2C 会在其中返回身份验证响应(令牌)。 该 URI 与在 Azure 门户中注册应用时设置的“重定向 URI”匹配。 此 URL 需可公开访问。 将该值保留原样。 |
LOGOUT_ENDPOINT |
Azure AD B2C 注销终结点,例如 https://<your-tenant-name>.b2clogin.cn/<your-tenant-name>.partner.onmschina.cn/<sign-in-sign-up-user-flow-name>/oauth2/v2.0/logout?post_logout_redirect_uri=http://localhost:3000 。 请将 <your-tenant-name> 替换为你的租户的名称,将 <sign-in-sign-up-user-flow-name> 替换为你的“登录和注册”用户流的名称,例如 B2C_1_susi 。 |
更新后,最终配置文件应类似于以下示例:
SERVER_PORT=3000
#web apps client ID
APP_CLIENT_ID=<You app client ID here>
#session secret
SESSION_SECRET=sessionSecretHere
#web app client secret
APP_CLIENT_SECRET=<Your app client secret here>
#tenant name
TENANT_NAME=<your-tenant-name>
#B2C sign up and sign in user flow/policy name and authority
SIGN_UP_SIGN_IN_POLICY_AUTHORITY=https://<your-tenant-name>.b2clogin.cn/<your-tenant-name>.partner.onmschina.cn/<sign-in-sign-up-user-flow-name>
AUTHORITY_DOMAIN=https://<your-tenant-name>.b2clogin.cn
#client redorect url
APP_REDIRECT_URI=http://localhost:3000/redirect
LOGOUT_ENDPOINT=https://<your-tenant-name>.b2clogin.cn/<your-tenant-name>.partner.onmschina.cn/<sign-in-sign-up-user-flow-name>/oauth2/v2.0/logout?post_logout_redirect_uri=http://localhost:3000
步骤 4:获取 Web API 示例代码
注册 Web API 并定义其作用域后,请配置 Web API 代码,使其适用于你的 Azure AD B2C 租户。
若要获取 Web API 示例代码,请执行下列操作之一:
通过运行以下命令,从 GitHub 克隆该示例 Web API 项目:
git clone https://github.com/Azure-Samples/active-directory-b2c-javascript-nodejs-webapi.git
你还可以直接前往 GitHub 上的 Azure-Samples/active-directory-b2c-javascript-nodejs-webapi 项目。
步骤 4.1:更新 Web API
在代码编辑器中打开
config.json
文件。使用前面创建的用户流和应用程序注册修改变量值:
对于
tenantName
,请使用你的租户名称,例如fabrikamb2c
。对于
clientID
,请使用在步骤 2.1 中创建的 Web API 的“应用程序(客户端) ID”。对于
policyName
,请使用在步骤 1 中创建的“登录和注册”用户流的名称,例如B2C_1_susi
。
更新后,代码应如以下示例所示:
config.json:
{
"credentials": {
"tenantName": "fabrikamb2c",
"clientID": "93733604-cc77-4a3c-a604-87084dd55348"
},
"policies": {
"policyName": "B2C_1_susi"
},
"resource": {
"scope": ["tasks.read"]
},
"metadata": {
"authority": "login.partner.microsoftonline.cn",
"discovery": ".well-known/openid-configuration",
"version": "v2.0"
},
"settings": {
"isB2C": true,
"validateIssuer": true,
"passReqToCallback": false,
"loggingLevel": "info"
}
}
步骤 4.2:安装应用依赖项
打开控制台窗口,切换到包含 Node.js Web API 示例的目录。 例如:
cd active-directory-b2c-javascript-nodejs-webapi
运行以下命令:
npm install && npm update
步骤 5:运行 Web 应用和 API
现已准备好测试 Web 应用程序在限定范围内对 Web API 的访问。 在本地计算机上同时运行 Node.js Web API 和示例 Web 应用程序。
在终端中,导航到示例 Web API 并启动 Node.js Web API 服务器。 例如:
cd active-directory-b2c-javascript-nodejs-webapi node index.js
控制台窗口将显示该应用程序所在的端口号。
Listening on port 5000...
在另一个终端实例中,导航到示例 Web 应用并启动 Node.js Web 应用服务器。 例如:
cd active-directory-b2c-msal-node-sign-in-sign-out-webapp/call-protected-api node index.js
控制台窗口将显示该应用程序所在的端口号。
Msal Node Auth Code Sample app listening on port !3000
在浏览器中转到
http://localhost:3000
。 应会看到带有以下两个按钮的页面:“登录以调用受保护 API”和“或调用匿名 API”。若要调用匿名 API,请选择“或调用匿名 API”。 该 API 将以包含
date
键的 JSON 对象做出响应,例如:{"date":"2022-01-27T14:21:22.681Z"}
匿名 API 是 Web API 中不受保护的终结点。 无需访问令牌即可访问该终结点。
若要调用受保护的 API 终结点,请选择“登录以调用受保护 API”按钮。 系统会提示你进行登录。
输入登录凭据,例如电子邮件地址和密码。 如果没有帐户,请选择“立即注册”创建一个帐户。 成功登录或注册后,应会看到带有“调用受保护 API”按钮的以下页面。
若要调用受保护 API,请选择“调用受保护 API”按钮。 该 API 将以包含
name
键的 JSON 对象做出响应,该键的值是你帐户的别名,例如:{"name": "User 1"}