Reputation: 16567
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.
Upvotes: 5
Views: 7000
Reputation: 20127
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;
}
Upvotes: 5