I've got a Blazor WASM app with .NET 7 and I'm using Azure AD with a public (multi-tenant) app registration. I'm trying to request a scope so that I can authenticate against an API. But it doesn't request include the requested scopes during authentication.
Here is my appsettings.json:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/common",
"ClientId": "[My Balzor app client ID]",
"ValidateAuthority": true,
"Scopes": "openid email profile offline_access api://[My API app client ID]/user_read"
}
}
In Program.cs I'm configuring this here:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
});
I've also tried adding it explicitly:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
options.ProviderOptions.AdditionalScopesToConsent.Add("api://[My API app clinet ID]/user_read");
});
However, these scopes are never requested from AAD. The URI only ever includes openid, profile, and offline_access.

Why is my additional scope not requested? How do I fix this?
Your Scopes property is being ignored, because you are binding your "AzureAd" appsettings section to options.ProviderOptions.Authentication.
And options.ProviderOptions.Authentication is of type Microsoft.Authentication.WebAssembly.Msal.MsalAuthenticationOptions which does not include the property DefaultAccessTokenScopes or Scopes.
The DefaultAccessTokenScopes property (of type IList string) is a sibling to the Authentication property on the Microsoft.Authentication.WebAssembly.Msal.Models.MsalProviderOptions class.
Thus if you restructure your AzureAd section slightly to take into account the MsalProviderOptions structure, it should all bind correctly without having to call options.ProviderOptions.DefaultAccessTokenScopes.Add() manually in the Program.cs.
{
"AzureAd": {
"Authentication": {
"Authority": "https://login.microsoftonline.com/common",
"ClientId": "[My Balzor app client ID]",
"ValidateAuthority": "true"
},
"DefaultAccessTokenScopes": ["api://[My API app client ID]/user_read", "..."]
}
}
And then your Program.cs can be updated as follows:
builder.Services.AddMsalAuthentication(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions);
});
I created an Azure AD Application and granted Admin consent for the API permissions like below:

Make sure to grant Admin consent to all the API permissions.
I generated access token via Postman using the below parameters:
https://login.microsoftonline.com/TenantID/oauth2/v2.0/authorize?
&client_id=ClientID
&response_type=code
&redirect_uri=https://jwt.ms
&response_mode=query
&scope=openid email profile offline_access api://ab0d71e6-1263-48cf-967b-ef0ce7422639/user_read
&state=12345

When I decoded the token, I got the scopes same as you:

Now, I generated access token using the scope as below:
scope=api://ClientID/user_read openid email profile offline_access

When I decoded the token, I got the API scope successfully like below:

To resolve the error, modify appsettings.json and try:
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/common",
"ClientId": "[My Balzor app client ID]",
"ValidateAuthority": true,
"Scopes": "api://[My API app client ID]/user_read openid email profile offline_access"
}
}
The user will get the consent screen:

If still the issue persists, try creating class for each Api and generate access token. Refer the below link:
How to handle tokens for multiple resources in blazor webassembly MSAL - Stack Overflow by Greg Grater.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With