Reputation: 459
I have a web application and an orchestrator API, along with several backend APIs. The web app and orchestrator API are both registered with Azure AD B2C app registrations, while the WebApp and backend APIs are registered with Microsoft Entra Azure AD app registrations.
Here’s the flow I’m working with:
The WebApp need to communicate with downstream orchestrator API and has to generate the token to send it over to orchestrator API which will validate this token using Azure AD B2C. No issues with app registrations since it has worked before when there is only #1 scenario.
The WebApp also needs to communicate with downstream backend APIs, which use Azure AD to generate their tokens.
I’m facing difficulties in configuring the middleware to handle multiple authentication schemes, including Azure AD B2C and Azure AD, in this scenario. How should I approach configuring the middleware to support both authentication schemes?
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
configuration.Bind("WebApp:AzureAdB2C", options);
options.Events = new OpenIdConnectEvents
{
...
};
});
services.AddMicrosoftIdentityWebApiAuthentication(configuration, "orchestrator:AzureAdB2C", "AzureAdB2CScheme")
.EnableTokenAcquisitionToCallDownstreamApi(options => configuration.Bind("orchestrator:AzureAdB2C", options))
.AddInMemoryTokenCaches();
services.AddMicrosoftIdentityWebApiAuthentication(configuration, "AzureAd", "AzureAdScheme")
.EnableTokenAcquisitionToCallDownstreamApi(options => configuration.Bind("AzureAd", options))
.AddInMemoryTokenCaches();
Following is what I'm using to get token
public TokenController(ITokenAcquisition tokenAcquisition, IConfiguration configuration)
{
this.tokenAcquisition = tokenAcquisition;
this.configuration = configuration;
}
[HttpGet("GetOrchestratorApiTokenAsync")]
public async Task<IActionResult> GetOrchestratorApiTokenAsync()
{
var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync([configuration.GetValue<string>("WebApp:ApiScopes")]);
return new JsonResult(accessToken);
}
Tried this overload of GetAccessTokenForUserAsync
if (User.Identity.IsAuthenticated)
{
var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(
[configuration.GetValue<string>("WebApp:ApiScopes")]
,authenticationScheme: "AzureAdB2CScheme"
,user: User);
return new JsonResult(accessToken);
}
Do I need to use schemes to build this ITokenAcquisition tokenAcquisition
instance in a different way, right now it is injected by the DI.
Problem: Communication with Orchestrator Api does not work.
Following is the error
Microsoft.Identity.Web.MicrosoftIdentityWebChallengeUserException: IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent.
---> MSAL.NetCore.4.66.1.0.MsalUiRequiredException:
ErrorCode: user_null
Microsoft.Identity.Client.MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.
at Microsoft.Identity.Client.Internal.Requests.Silent.SilentRequest.ExecuteAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.<>c__DisplayClass11_1.<<RunAsync>b__1>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.Identity.Client.Utils.StopwatchService.MeasureCodeBlockAsync(Func`1 codeBlock)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.ApiConfig.Executors.ClientApplicationBaseExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenSilentParameters silentParameters, CancellationToken cancellationToken)
at Microsoft.Identity.Web.TokenAcquisition.GetAuthenticationResultForWebAppWithAccountFromCacheAsync(IConfidentialClientApplication application, ClaimsPrincipal claimsPrincipal, IEnumerable`1 scopes, String tenantId, MergedOptions mergedOptions, String userFlow, TokenAcquisitionOptions tokenAcquisitionOptions)
at Microsoft.Identity.Web.TokenAcquisition.GetAuthenticationResultForUserAsync(IEnumerable`1 scopes, String authenticationScheme, String tenantId, String userFlow, ClaimsPrincipal user, TokenAcquisitionOptions tokenAcquisitionOptions)
StatusCode: 0
ResponseBody:
Headers:
--- End of inner exception stack trace ---
at Microsoft.Identity.Web.TokenAcquisition.GetAuthenticationResultForUserAsync(IEnumerable`1 scopes, String authenticationScheme, String tenantId, String userFlow, ClaimsPrincipal user, TokenAcquisitionOptions tokenAcquisitionOptions)
at Microsoft.Identity.Web.TokenAcquisition.GetAccessTokenForUserAsync(IEnumerable`1 scopes, String authenticationScheme, String tenantId, String userFlow, ClaimsPrincipal user, TokenAcquisitionOptions tokenAcquisitionOptions)
at PoS.WebApp.Controllers.TokenController.GetFrontEndApiTokenAsync() in C:\Users\shrav\source\repos\Pol.Apps\PoS.WebApp\Controllers\TokenController.cs:line
Note: At the time of the call user is signed in to the app. And there is a guard rail User.Identity.IsAuthenticated
which is true, this placed before the call to token acquisition.
Any help would be greatly appreciated!
Upvotes: 0
Views: 28