Reputation: 2305
I am trying to make a simple call with the Microsoft Graph API SDK using the Microsoft.Identity.Web library from within a web api project.
The user is already logged in and is calling protected controllers from a SPA and everything is working fine - but now, these controlles should make a call to the Graph API and I don't get it up and running...
I found a perfect sample that shows how easy it is with a wep app here. And it is really as easy as this:
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
As I want to use this functionality within a web api project, I created a new project of that type, copied the code and got:
MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.
and
MicrosoftIdentityWebChallengeUserException: IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent.
Then I thought, ok, as this is now api related, I will change the code from
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi(new string[] { "user.read" })
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
to
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(Configuration.GetSection("DownstreamApi"))
.AddInMemoryTokenCaches();
but I get the same error.
I navigated to https://aka.ms/ms-id-web/ca_incremental-consent as mentioned in the exception message and found Handling incremental consent or conditional access in web APIs:
public async Task<string> CallGraphApiOnBehalfOfUser()
{
string[] scopes = { "user.read" };
// we use MSAL.NET to get a token to call the API On Behalf Of the current user
try
{
string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);
dynamic me = await CallGraphApiOnBehalfOfUser(accessToken);
return me.UserPrincipalName;
}
catch (MicrosoftIdentityWebChallengeUserException ex)
{
await _tokenAcquisition.ReplyForbiddenWithWwwAuthenticateHeaderAsync(scopes, ex.MsalUiRequiredException);
return string.Empty;
}
catch (MsalUiRequiredException ex)
{
await _tokenAcquisition.ReplyForbiddenWithWwwAuthenticateHeaderAsync(scopes, ex);
return string.Empty;
}
}
I tried this and get the same error:
IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent.
When later finding the sample Web API calling downstream web API, I thought now everything gets easy but although, a WebAPI is calling Microsoft Graph, they are using a Windows application to sign in the user first.
On stackoverflow, I found How to access Graph API from Web API in SPA application but unfortunately, this question is hopefully out-dated.
Has anyone an idea how to get the sample code for the web app up and running in a web api only project? (No windows application involved)
I am using
Microsoft.Graph 3.21.0
Microsoft.Identity.Web version 1.4.0
Upvotes: 3
Views: 3354
Reputation: 9830
I think that instead of using AddMicrosoftGraph
, you need to use AddMicrosoftGraphAppOnly.
So in your example this will be like:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraphAppOnly(authenticationProvider => new GraphServiceClient(authenticationProvider))
.AddInMemoryTokenCaches();
Upvotes: 5
Reputation: 3495
2. Web API now calls Microsoft Graph is that one that you're looking for. The fact that the client is a windows application is not relevant. Try it and let me know how it goes.
Upvotes: 0