0

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:

enter image description here

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:

enter image description here

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:

enter image description here

and

enter image description here

where the issuer URL is made of my Azure Tenant ID, as stated here:

enter image description 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

enter image description here

Pine Code
  • 2,466
  • 3
  • 18
  • 43

2 Answers2

0

I've done some test and hope it could help, if I misunderstood in some place, pls point it out.

First I created a http trigger function, when I called GET https://xxx.azurewebsites.net/api/HttpTrigger1?name=asdfg, I would get the response like hello asdfg.

Then I followed this doc to enable authentication via azure ad. That means I create a new azure ad app, expose an api like this. enter image description here

After this step, when I call the GET request, it asks me to sign in then I can get the same response. Next I created another azure ad app and add api permission of the api I exposed just now, and via this application, I can generate access token with the scope of that api, and with this access token in the Authorization request header, I can access the GET request directly.

enter image description here

Tiny Wang
  • 10,423
  • 1
  • 11
  • 29
  • 1
    Why do you hard-code the access token? Where does it come from? – Pine Code Apr 08 '21 at 07:38
  • I wrote a demo, so I generate the access toke from postman, did you have trouble to generate the access token in code? – Tiny Wang Apr 08 '21 at 07:47
  • I found the solution; I provided it as an answer to this SO question. – Pine Code Apr 08 '21 at 09:27
  • Thanks for your response sir, and congratulations to you. I also tried to add authentication(classic) in 'Express' but not 'Advance', so I didn't do so many configurations as you indeed. Anyway, it's good :) – Tiny Wang Apr 08 '21 at 09:36
0

I found that changing the issuer URL (specified in the Azure Function app registration) from

https://login.microsoftonline.com/[tenant ID]

to

https://login.microsoftonline.com/[tenant ID]/v2.0

resolved the issue. I still don’t understand why it didn’t work since the docs said to omit the /v2.0.

Pine Code
  • 2,466
  • 3
  • 18
  • 43