使用 Azure AD 的不记名令牌保护 ASP.Net Core 3.1 API

Jos*_*osh 3 c# security jwt azure-active-directory asp.net-core-3.1

我有一个 .net core 3.1 Web API。我想使用 Azure AD 中的不记名令牌来保护端点。

我已遵循本指南。我已经注册了一个 API 应用程序和一个客户端应用程序。

在我的 API 中,我添加了 jwt 的注册(如代码中所述)

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(opt =>
    {
        opt.Audience = Configuration["AzureAd:ResourceId"];
        opt.Authority = $"{Configuration["AzureAd:Instance"]}{Configuration["AzureAd:TenantId"]}";
    });
Run Code Online (Sandbox Code Playgroud)

我的 API 配置部分如下所示

"AzureAd": {
    "ResourceId": "api://<client-id-guid>",
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "<tenant-id-guid>"
}
Run Code Online (Sandbox Code Playgroud)

其中client-id-guid是 api 应用程序的客户端 ID(使用 api:// 地址的默认配置)。

然后,对于我的客户,我在新解决方案中实施了测试以获取令牌并调用安全端点。

AadConfiguration config = AadConfiguration.ReadFromJsonFile("appsettings.json");

IConfidentialClientApplication app;

app = ConfidentialClientApplicationBuilder.Create(config.ClientId)
    .WithClientSecret(config.ClientSecret)
    .WithAuthority(new Uri(config.Authority))
    .Build();

string[] ResourceIds = new string[] {config.ResourceID};

var token = await app.AcquireTokenForClient(ResourceIds)
    .ExecuteAsync();

Assert.IsFalse(string.IsNullOrWhiteSpace(token.AccessToken));

var request = new RestRequestBuilder("https://my-api-staging.azurewebsites.net/api")
    .WithSegments("health-check", "auth")
    .WithBearerToken(token.AccessToken)
    .Build();

try
{
    var response = await _restHelper.GetJsonAsync<dynamic>(request);

    Assert.IsFalse(string.IsNullOrEmpty(response?.serverTime?.ToString()));
}
catch (RestException e)
{
    Assert.IsFalse(true, e.ResponseContent);
}
Run Code Online (Sandbox Code Playgroud)

以及本次测试的配置

{
    "Instance": "https://login.microsoftonline.com/{0}",
    "TenantId": "<tenant-id-guid>",
    "ClientId": "<client-id-guid>",
    "ClientSecret": "<client-secret>",
    "ResourceId": "api://<api-client-id-guid>/.default"
}
Run Code Online (Sandbox Code Playgroud)

租户 ID 是 API 和测试应用程序的销售

客户端ID是客户端应用程序注册的客户端ID,及其秘密

资源 Id 是 API 的应用程序 id,即 api:// 和 api 的客户端 Id

我可以很好地检索访问令牌。但是,当我使用给定的访问令牌调用端点时,出现以下错误:

在“CurrentUser\My”上找不到主题为“CN=TODO.azurewebsites.net”的有效证书

当我按照文档中的步骤操作时,我不确定为什么我的身份验证失败。

Joe*_*Cai 5

我可以很好地检索访问令牌。但是,当我使用给定的访问令牌调用端点时,出现以下错误:

我按照指南并在我的网站上进行了测试,效果非常好。

获取访问令牌后,您可以尝试在 postman 中使用它向核心 api 发送请求。而核心api是3.1版本,所以不必/api路由它。

在此输入图像描述

并且可以用来HttpClient调用核心webapi。

var token = await app.AcquireTokenForClient(ResourceIds).ExecuteAsync();
var accesstoken = token.AccessToken;
using (var client = new HttpClient())
{
    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accesstoken);
    var requestURl = new Uri($"https://xxxx.azurewebsites.net/weatherforecast");
    var response = client.GetAsync(requestURl).Result;
    string result = response.Content.ReadAsStringAsync().Result;
}
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述