I already read and tried this, this, and many other resources, without success.
I have a UWP app that calls an AAD-protected HTTP-triggered Azure Function. I created the two app registrations on the AAD section of the Azure portal. The API app registration specifies a scope and has an application ID URI of api://5e6b2b53-...
. On the “Authentication” blade, I set https://login.microsoftonline.com/common/oauth2/nativeclient
as redirect URI. I already set the same value as the redirect URI of the UWP app registration (I don’t know if it’s correct). I also set:
On the Function app registration. I also set the following redirect URI for the Function app registration, but I don’t understand if it’s required:
The UWP app registration uses the right scope I defined on the Function app registration. Both the app registrations are multi-tenant. The code I use on the UWP app to call the protected Azure Function is:
namespace ClientApplication
{
public partial class MainPage
{
private readonly HttpClient _httpClient;
private const string ClientId = "..."; // Client ID of the UWP app registration
private const string Tenant = "..."; // My Azure tenant ID
private const string Authority = "https://login.microsoftonline.com/" + Tenant;
private readonly string[] _scopes = { "api://5e6b2b53-.../user_impersonation2" };
public MainPage()
{
_httpClient = new HttpClient();
BindingContext = this;
InitializeComponent();
}
private async void Button_OnClicked(object sender, EventArgs e)
{
var app = PublicClientApplicationBuilder.Create(ClientId)
.WithAuthority(Authority)
.WithRedirectUri("https://login.microsoftonline.com/common/oauth2/nativeclient")
.WithLogging((level, message, containsPii) =>
{
Debug.WriteLine($"MSAL: {level} {message} ");
}, LogLevel.Warning, false, true)
.Build();
AuthenticationResult result;
var accounts = await app.GetAccountsAsync();
try
{
result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault()).ExecuteAsync();
}
catch (MsalUiRequiredException)
{
try
{
result = await app.AcquireTokenInteractive(_scopes).ExecuteAsync();
}
catch (Exception exception)
{
Console.WriteLine(exception);
throw;
}
}
if (result == null) return;
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken);
var response = _httpClient.GetAsync("URL of my HTTP-triggered Azure Function").Result;
var jsonResponseContent = await response.Content.ReadAsStringAsync();
}
}
}
On the Azure Function page, I set:
and
where the issuer URL is made of my Azure Tenant ID, as stated here:
Can you help me understand why I get a 401 when I call the Azure Function with the access token I obtained from the identity provider? This is the significant part of the access token I get