使用 Azure AD B2C 在你自己的 Web API 中启用身份验证
若要授权访问 Web API,可以仅处理包含 Azure Active Directory B2C (Azure AD B2C) 颁发的有效访问令牌的请求。 本文介绍了如何启用对 Web API 的 Azure AD B2C 授权。 完成本文中的步骤后,只有获取了有效访问令牌的用户才有权调用你的 Web API 终结点。
先决条件
在开始操作之前,请阅读以下文章之一,其中介绍了如何为调用 Web API 的应用配置身份验证。 然后,按照本文中的步骤将示例 Web API 替换为你自己的 Web API。
概述
基于令牌的身份验证确保对 Web API 的请求包含有效的访问令牌。
该应用完成以下步骤:
通过 Azure AD B2C 对用户进行身份验证。
获取一个具有对 Web API 终结点的必需权限(作用域)的访问令牌。
使用以下格式,在 HTTP 请求的身份验证标头中将该访问令牌作为持有者令牌进行传递:
Authorization: Bearer <access token>
该 Web API 完成以下步骤:
从 HTTP 请求中的授权标头读取持有者令牌。
验证该令牌。
验证令牌中的权限(作用域)。
读取在令牌中编码的声明(可选)。
响应 HTTP 请求。
应用注册概述
要使应用能够通过 Azure AD B2C 登录并调用 Web API,需要在 Azure AD B2C 目录中注册两个应用程序。
Web 应用程序、移动应用程序或 SPA 应用程序注册使你的应用可以通过 Azure AD B2C 登录。 应用注册过程会生成一个应用程序 ID(也称为客户端 ID),用于唯一标识你的应用程序(例如,应用 ID:1)。
注册 Web API 后,你的应用就能够调用受保护的 Web API。 注册将公开 Web API 权限(范围)。 应用注册过程会生成一个应用程序 ID,用于唯一标识你的 Web API(例如,应用 ID:2)。 向应用(应用 ID:1)授予对 Web API 范围(应用 ID:2)的权限。
下图描绘了应用程序注册和应用程序体系结构:
准备开发环境
在接下来的步骤中,创建一个新的 Web API 项目。 选择编程语言:ASP.NET Core 或 Node.js。 确保有一台运行以下任一软件的计算机:
步骤 1:创建受保护的 Web API
创建一个新的 Web API 项目。 首先,选择要使用的编程语言:ASP.NET Core 或 Node.js。
使用 dotnet new
命令。 dotnet new
命令创建一个名为 TodoList 的新文件夹,其中包含 Web API 项目资产。 打开目录,然后打开 Visual Studio Code。
dotnet new webapi -o TodoList
cd TodoList
code .
系统提示你“将所需资产添加到项目”时,请选择“是”。
步骤 2:安装依赖项
在你的 Web API 项目中添加身份验证库。 身份验证库将分析 HTTP 身份验证头,验证令牌,并提取声明。 有关详细信息,请查看该库的文档。
若要添加身份验证库,请运行以下命令安装相应的包:
dotnet add package Microsoft.Identity.Web
步骤 3:启动身份验证库
添加所需的代码来启动身份验证库。
打开 Startup.cs,然后在类的开头添加以下 using
声明:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
找到 ConfigureServices(IServiceCollection services)
函数。 然后在 services.AddControllers();
代码行的前面添加以下代码片段:
public void ConfigureServices(IServiceCollection services)
{
// Adds Microsoft Identity platform (Azure AD B2C) support to protect this Api
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(options =>
{
Configuration.Bind("AzureAdB2C", options);
options.TokenValidationParameters.NameClaimType = "name";
},
options => { Configuration.Bind("AzureAdB2C", options); });
// End of the Microsoft Identity platform block
services.AddControllers();
}
找到 Configure
函数。 然后,紧接在 app.UseRouting();
代码行的后面添加以下代码片段:
app.UseAuthentication();
更改后,你的代码应如以下代码片段所示:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
// Add the following line
app.UseAuthentication();
// End of the block you add
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
步骤 4:添加终结点
向 Web API 中添加两个终结点:
- 匿名的
/public
终结点。 此终结点返回当前日期和时间。 使用它通过匿名调用来调试 Web API。 - 受保护的
/hello
终结点。 此终结点返回访问令牌中的name
声明值。
若要添加匿名终结点,请执行以下操作:
在 /Controllers 文件夹下,添加 PublicController.cs 文件,然后将其添加到以下代码片段:
using System;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
namespace TodoList.Controllers
{
[ApiController]
[Route("[controller]")]
public class PublicController : ControllerBase
{
private readonly ILogger<PublicController> _logger;
public PublicController(ILogger<PublicController> logger)
{
_logger = logger;
}
[HttpGet]
public ActionResult Get()
{
return Ok( new {date = DateTime.UtcNow.ToString()});
}
}
}
若要添加受保护的终结点,请执行以下操作:
在 /Controllers 文件夹下,添加 HelloController.cs 文件,然后将其添加到以下代码:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Identity.Web.Resource;
namespace TodoList.Controllers
{
[Authorize]
[RequiredScope("tasks.read")]
[ApiController]
[Route("[controller]")]
public class HelloController : ControllerBase
{
private readonly ILogger<HelloController> _logger;
private readonly IHttpContextAccessor _contextAccessor;
public HelloController(ILogger<HelloController> logger, IHttpContextAccessor contextAccessor)
{
_logger = logger;
_contextAccessor = contextAccessor;
}
[HttpGet]
public ActionResult Get()
{
return Ok( new { name = User.Identity.Name});
}
}
}
HelloController
控制器由 AuthorizeAttribute 修饰,这将仅向已通过身份验证的用户授予访问权限。
该控制器还使用 [RequiredScope("tasks.read")]
进行修饰。 RequiredScopeAttribute 验证 Web API 是否是使用正确的范围 tasks.read
调用的。
步骤 5:配置 Web 服务器
在开发环境中,将 Web API 设置为侦听传入的 HTTP 或 HTTPS 请求端口号。 本示例使用 HTTP 端口 6000 和 HTTPS 端口 6001。 Web API 的基 URI 将为 http://localhost:6000
(针对 HTTP)和 https://localhost:6001
(针对 HTTPS)。
将以下 JSON 代码片段添加到 appsettings.json 文件。
"Kestrel": {
"EndPoints": {
"Http": {
"Url": "http://localhost:6000"
},
"Https": {
"Url": "https://localhost:6001"
}
}
}
步骤 6:配置 Web API
向配置文件中添加配置。 该文件包含有关 Azure AD B2C 标识提供者的信息。 Web API 应用使用此信息来验证访问令牌,该访问令牌由 Web 应用当作持有者令牌传递。
在项目根文件夹下,打开 appsettings.json 文件,然后添加以下设置:
{
"AzureAdB2C": {
"Instance": "https://contoso.b2clogin.cn",
"Domain": "contoso.partner.onmschina.cn",
"ClientId": "<web-api-app-application-id>",
"SignedOutCallbackPath": "/signout/<your-sign-up-in-policy>",
"SignUpSignInPolicyId": "<your-sign-up-in-policy>"
},
// More settings here
}
在 appsettings.json 文件中,更新以下属性:
部分 | 密钥 | 值 |
---|---|---|
AzureAdB2C | 实例 | Azure AD B2C 租户名称的第一部分(例如 https://contoso.b2clogin.cn )。 |
AzureAdB2C | 域 | Azure AD B2C 租户的完整租户名称(例如 contoso.partner.onmschina.cn )。 |
AzureAdB2C | ClientId | Web API 应用程序 ID。 在上面的示意图中,它是标有“应用 ID: 2”的应用程序。 若要了解如何获取 Web API 应用程序注册 ID,请参阅先决条件。 |
AzureAdB2C | SignUpSignInPolicyId | 用户流或自定义策略。 若要了解如何获取用户流或策略,请参阅先决条件。 |
步骤 7:运行并测试 Web API
最后,使用你的 Azure AD B2C 环境设置运行该 Web API。
在命令 shell 中,通过运行以下命令来启动 Web 应用:
dotnet run
你应会看到以下输出,这意味着你的应用已启动并正在运行,并已做好接收请求的准备。
Now listening on: http://localhost:6000
若要停止该程序,请在命令 shell 中选择“Ctrl+C”。 可以使用 node app.js
命令重新运行应用。
提示
若要运行 dotnet run
命令,还可以使用 Visual Studio Code 调试程序。 Visual Studio Code 的内置调试程序有助于加速编辑、编译和调试循环。
打开浏览器并转到 http://localhost:6000/public
。 在浏览器窗口中,应会看到显示了以下文本以及当前日期和时间。
步骤 8:从应用中调用 Web API
尝试在不使用访问令牌的情况下调用受保护的 Web API 终结点。 打开浏览器并转到 http://localhost:6000/hello
。 API 将返回“未授权”HTTP 错误消息,此时可以确认该 Web API 受持有者令牌的保护。
继续配置应用以调用 Web API。 有关指导,请参阅先决条件部分。
后续步骤
获取 GitHub 中的完整示例:
- 使用 Microsoft 标识库获取 Web API。