Reputation: 2472
I have a situation where there is a .net Core Web API that we use to manage some "machines". One of the exposed API is a simulation of the operation of such machines. The machines have different versions, each different versions have a different internal behavior but same interface.
We have, then, developed a series of different .net Core Web API to simulate each different versions of the machines.
I need therefore to call an API from an API, it's sound pretty straightforward as I'm doing it already with Microsoft Graph.
In startup.cs, I have:
public void ConfigureServices(IServiceCollection services)
{
// To protect the API with Azure AD
services
.AddProtectedWebApi(Configuration);
// To have ITokenAcquisition when calling the specific simulation API
services
.AddMicrosoftIdentityPlatformAuthentication(Configuration)
.AddMsal(Configuration, new string[] { Configuration["SimulationAPIv411:Scope"] })
.AddInMemoryTokenCaches();
I'm testing it with Postman with this flow in mind:
What I'm experiencing is:
If I leave it like this, in postman I get as result a login page
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html dir="ltr" class="" lang="en">
<head>
<title>Sign in to your account</title>
[...]
If I remove the line .AddMicrosoftIdentityPlatformAuthentication(Configuration)
then I can reach the SimulationDispatcherController but when it tries to call the other API I get the error:
MSAL.NetCore.4.8.1.0.MsalUiRequiredException:
ErrorCode: user_null
Microsoft.Identity.Client.MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.
[...]
I try to get the token with the ITokenAcquisition
object, calling GetAccessTokenOnBehalfOfUserAsync(_Scopes);
where the scope is the required one for the specific API.
Do you have any suggestion or link to documentation that explain better how to configure the MSAL in an API that is protected by Azure AD?
EDIT: As suggested in the answer, the only change required was:
.AddMsal(Configuration, new string[] { Configuration["SimulationAPIv411:Scope"] })
to
.AddProtectedApiCallsWebApis(Configuration)
Upvotes: 0
Views: 3760
Reputation: 23141
If you want to call .net Core Web API from other .net Core Web API projected by Azure AD, you use the OAuth 2.0 On-Behalf-Of flow. The detailed steps are as below
Regarding how to configure it, please refer to the following steps:
Register the web api app
Register the client app
Configure known client applications for web API application
In the Azure portal, navigate to your Web api app registration and click on the Manifest section.
Find the property knownClientApplications and add the Client IDs of the client applications
Configure project
Add the reference Microsoft.Identity.Web to your project
add the following code in appsettings.json
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "<your tenant id>",
"ClientId": "<app id of Web API A>",
"ClientSecret": "<app secret of Web API A>"
},
public void ConfigureServices(IServiceCollection services)
{
services.AddProtectedWebApi(Configuration)
.AddProtectedApiCallsWebApis(Configuration)
.AddInMemoryTokenCaches();
[Authorize]
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
private readonly ITokenAcquisition _tokenAcquisition;
private readonly ILogger<WeatherForecastController> _logger;
public WeatherForecastController(ILogger<WeatherForecastController> logger, ITokenAcquisition tokenAcquisition)
{
_logger = logger;
_tokenAcquisition = tokenAcquisition;
}
[HttpGet]
public async Task<string> Get()
{
string[] scopes = { "user.read" }; // the scope of Web API B
string accessToken = await _tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes);
// you use the accessToken to call the Web API B
GraphServiceClient client = new GraphServiceClient(new DelegateAuthenticationProvider(
async (requestMessage) =>
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
}));
User user =await client.Me.Request().GetAsync();
return user.UserPrincipalName;
}
}
Test in the Postman
For more details, please refer to the document and the sample
Upvotes: 4
Reputation: 27578
That seems other specific simulation APIs are also protected by Azure AD , you can use OAuth 2.0 On-Behalf-Of flow which works in scenario where an application invokes a service/web API, which in turn needs to call another service/web API.
Here is code sample for using OBO flow in asp.net core web api with MSAL 2.3 and later.
Upvotes: 2