Azure Function with AD auth results in 401 Unauthorized when using Bearer tokens
I managed to get it working through postman using following configuration. Important lesson was setting in "Allowed token audiences" and "resource" name used in postman to acquire token should be same in this case. I used the same code provided here in question. in this case app registered in Azure AD is a client and resource as well. configuration and testing through postman as follows
Acquire token in postman
Calling azure function using Postman .. Authorization header with bearer token
UPDATE 2020-05-12: According to ambrose-leung's answer further below you can now add a custom issuer URL which should potentially enable you to use v2 tokens. I haven't tried this myself, but maybe this will provide useful for someone in the future. (If his answer helped you please give him an upvote and maybe leave a comment ð)
This took forever to figure out, and there is very little information about this in the offical documentations.
But it turns out the problem was/is that Azure Functions don't support Bearer tokens generated by the oauth2/v2.0/ Azure API. Since the portal uses those (if your AD supports them) you are out of luck to be able to run the function in there.
This also explains why my postman requests didn't work, because I was also using the v2 api. After switching to v1 I could access my API (Postman doesn't allow you to add a resource_id when you use the integrated auth feature, so I had to switch to handling everything manually).
After that came the realisation that you can't use MSAL either if you are writing a JS client (Angular in my case). So one alternative is ADAL, where the Angular implementation looks kind of awkward. So I decided to use angular-oauth2-oidc which took another hour of tinkering to get it to play nicely with Azure AD.
But after all that I can finally access my API.
I really don't understand why you wouldn't allow users to access Azure Function Apps with Azure AD v2 tokens, but at least this should be so much better documented. But whatever, I can finally go to sleep.
EDIT: After I opend an issue for this, they added a note that v2 isn't supported by Azure Functions, hopefully making life easier for other people.
https://docs.microsoft.com/en-us/azure/app-service/configure-authentication-provider-aad
You can now use v2.0 tokens!
Instead of choosing 'Express' when you configure AAD, you have to choose 'Advance' and add the /v2.0 part at the end of the URL.
This is the code that I use in my console app to present the user with a login prompt, then take the bearer token for use with the Azure Function.
string[] scopes = new string[] { "profile", "email", "openid" };
string ClientId = [clientId of Azure Function];
string Tenant = [tenantId];
string Instance = "https://login.microsoftonline.com/";
var _clientApp = PublicClientApplicationBuilder.Create(ClientId)
.WithAuthority($"{Instance}{Tenant}")
.WithDefaultRedirectUri()
.Build();
var accounts = _clientApp.GetAccountsAsync().Result;
var authResult = _clientApp.AcquireTokenInteractive(scopes)
.WithAccount(accounts.FirstOrDefault())
.WithPrompt(Prompt.SelectAccount)
.ExecuteAsync().Result;
var bearerTokenForAzureFunction = authResult.IdToken;