microsoft-identity-web: IDW10502: An MsalUiRequiredException
Microsoft.Identity.Web Library
Microsoft.Identity.Web
Microsoft.Identity.Web version
1.25.1
Web app
Sign-in users and call web APIs
Web API
Not Applicable
Token cache serialization
Distributed caches
Description
To me, it seems to be a bug that
var res = await _api.CallWebApiForUserAsync(ServiceName, options => { options.RelativePath = "/api/getsomething"; //options.Scope = config.Scope //injected via config }, user: user);
throws “IDW10502: An MsalUiRequiredException => inner: An error occured during token acquisition: No account or login hint was passed to the AcquireTokenSilent call”
while at the same time this works:
var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new string[] { config.Scope }, user: user);
Reproduction steps
- Setup AddMicrosoftIdentityWebApp(b2cConfig) .EnableTokenAcquisitionToCallDownstreamApi(new string[] { config.Scope }) .AddDownstreamWebApi(“MyApi”, builder.Configuration.GetSection(“MyApi”)) .AddDistributedTokenCaches();//I do use redis
- Within Oidc’s OnTokenValidated event call -tokenAcquisition.GetAccessTokenForUserAsync //success -_api.CallWebApiForUserAsync both with “user: context.Principal”
Error message
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.35.1.0.MsalUiRequiredException: ErrorCode: user_null Microsoft.Identity.Client.MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.
Id Web logs
fail: Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler[17]
Exception occurred while processing message.
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.35.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.Silent.SilentRequest.ExecuteAsync(CancellationToken cancellationToken)
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, IEnumerable1 scopes, String authority, 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(IEnumerable1 scopes, String authenticationScheme, String tenantId, String userFlow, ClaimsPrincipal user, TokenAcquisitionOptions tokenAcquisitionOptions) at Microsoft.Identity.Web.DownstreamWebApi.CallWebApiForUserAsync(String serviceName, String authenticationScheme, Action
1 calledDownstreamWebApiOptionsOverride, ClaimsPrincipal user, StringContent content)
at STPv2.Infrastructure.UrmApi.Me(ClaimsPrincipal user) in C:\Users\mlproe\source\repos\STPv2\STPv2\Infrastructure\UrmApi.cs:line 24
at STPv2.Program.UrmAuthentication(TokenValidatedContext ctx) in C:\Users\mlproe\source\repos\STPv2\STPv2\Program.cs:line 154
at STPv2.Program.<>c.<<ConfigureServices>b__2_7>d.MoveNext() in C:\Users\mlproe\source\repos\STPv2\STPv2\Program.cs:line 103
— End of stack trace from previous location —
at Microsoft.Identity.Web.MicrosoftIdentityWebAppAuthenticationBuilder.<>c__DisplayClass11_1.<<WebAppCallsWebApiImplementation>b__2>d.MoveNext()
— End of stack trace from previous location —
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.RunTokenValidatedEventAsync(OpenIdConnectMessage authorizationResponse, OpenIdConnectMessage tokenEndpointResponse, ClaimsPrincipal user, AuthenticationProperties properties, JwtSecurityToken jwt, String nonce)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync()
Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler: Error: Exception occurred while processing message.
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.35.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.Silent.SilentRequest.ExecuteAsync(CancellationToken cancellationToken)
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, IEnumerable1 scopes, String authority, 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(IEnumerable1 scopes, String authenticationScheme, String tenantId, String userFlow, ClaimsPrincipal user, TokenAcquisitionOptions tokenAcquisitionOptions) at Microsoft.Identity.Web.DownstreamWebApi.CallWebApiForUserAsync(String serviceName, String authenticationScheme, Action
1 calledDownstreamWebApiOptionsOverride, ClaimsPrincipal user, StringContent content)
at STPv2.Infrastructure.UrmApi.Me(ClaimsPrincipal user) in C:\Users\mlproe\source\repos\STPv2\STPv2\Infrastructure\UrmApi.cs:line 24
at STPv2.Program.UrmAuthentication(TokenValidatedContext ctx) in C:\Users\mlproe\source\repos\STPv2\STPv2\Program.cs:line 154
at STPv2.Program.<>c.<<ConfigureServices>b__2_7>d.MoveNext() in C:\Users\mlproe\source\repos\STPv2\STPv2\Program.cs:line 103
— End of stack trace from previous location —
at Microsoft.Identity.Web.MicrosoftIdentityWebAppAuthenticationBuilder.<>c__DisplayClass11_1.<<WebAppCallsWebApiImplementation>b__2>d.MoveNext()
— End of stack trace from previous location —
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.RunTokenValidatedEventAsync(OpenIdConnectMessage authorizationResponse, OpenIdConnectMessage tokenEndpointResponse, ClaimsPrincipal user, AuthenticationProperties properties, JwtSecurityToken jwt, String nonce)
at Microsoft.AspNetCore.Authentication.OpenIdConnect.OpenIdConnectHandler.HandleRemoteAuthenticateAsync()
Relevant code snippets
var res = await _api.CallWebApiForUserAsync(ServiceName, options =>
{
options.RelativePath = "/api/getsomething";
//options.Scope = config.Scope //injected via config
}, user: user);
//AND
var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(new string[] { config.Scope }, user: user);
Regression
Expected behavior
_api.CallWebApiForUserAsync get the required access token just as tokenAcquisition.GetAccessTokenForUserAsync does
About this issue
- Original URL
- State: open
- Created 2 years ago
- Comments: 16
This discussion is going into a complete wrong direction. The initial question was “why CallWebApiForUserAsync is not able to get a token while GetAccessTokenForUserAsync does”. It’s still not clear why they behave differently.