简体   繁体   中英

Secure ASP.Net Core 3.1 API with Bearer Tokens from Azure AD

I have a .net core 3.1 web API. I want to secure the endpoints using bearer tokens from Azure AD.

I have followed This guide . I have a registered an app for the API and an app for the client.

In my API, I have added a registration for the jwt (as outlined in the code)

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

And my configuration section for the API looks like this

"AzureAd": {
    "ResourceId": "api://<client-id-guid>",
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "<tenant-id-guid>"
}

where the client-id-guid is the client id of the api application (used the default configuration for the api:// address).

Then, for my client, I implemented a test in a new solution to get the token and call a secured endpoint.

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);
}

And the configuration for this test

{
    "Instance": "https://login.microsoftonline.com/{0}",
    "TenantId": "<tenant-id-guid>",
    "ClientId": "<client-id-guid>",
    "ClientSecret": "<client-secret>",
    "ResourceId": "api://<api-client-id-guid>/.default"
}

Tenant Id is the sale for both the API and the test application

The client ID is the client id for the client app registration, and its secret

The resource Id is the API's application id, which is the api:// with the api's client Id

I can retrieve the access token just fine. However, when I call an endpoint using the access token I am given, I get the following error:

Couldn't find a valid certificate with subject 'CN=TODO.azurewebsites.net' on the 'CurrentUser\My'

I'm not sure why my authentication is failing when I have followed the steps in the document.

I can retrieve the access token just fine. However, when I call an endpoint using the access token I am given, I get the following error:

I follow the guide and test in my site which works very well.

After getting access token, you can try to use it in postman to send request to core api. While the core api is 3.1 version, so it do not have /api to route it.

在此处输入图像描述

And you can use HttpClient to call core 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;
}

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM