azure-functionsazure-ad-msalmicrosoft.identity.web

Securing ASPNET Core Web API for calls from Azure Function


We have an exisiting ASP.NET Core Web Api in Azure that has endpoints that support Azure AD and Azure AD secured users

I want to create a new Azure Function with a Timed trigger that will call this same Web Api. The call will obviously not be in the context of a user but in the context of the Function App.

The AF is AzureFunctionsVersion "v3" with a TargetFramework of "netcoreapp3.1"

I have added an App Role to the App registration for the existing Web API

App Role exposed from Web Api

I have then requested access to the that API from the Azure Functions "Api Permissions" blade in Azure Portal

API's App Role granted

I am only running this Azure Function locally as yet so here are the values from local.settings.json. I've removed the real values

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "AzureAd:Instance": "https://login.microsoftonline.com/",
    "AzureAd:Domain": "ourdomain.co.uk",
    "AzureAd:TenantId": "aaaaaaaa-92eb-430b-b902-aaaaaaaaaaaa",
    "AzureAd:ClientId": "aaaaaaaa-bd17-4e69-bdf6-aaaaaaaaaaaa",
    "AzureAd:Audience": "https://ourdomain.co.uk/appid,
    "AzureAd:ClientSecret": "THESECRET",
    "PatientApi:BaseAddress": "https://myapi.com/api/",
    "PatientApi:Scopes": "https://my-api-appiduri/.default"
  },
}  

I then try an get a token for the Azure Function by calling GetAccessTokenForAppAsync

 var accessToken = await this.tokenAcquisition.GetAccessTokenForAppAsync(this.patientScope);
            
 this.httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
 this.httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

When I call GetAccessTokenForAppAsync I get the following Exception

Microsoft.Identity.Client.MsalServiceException: 'A configuration issue is preventing authentication - check the error message from the server for details. You can modify the configuration in the application registration portal. See https://aka.ms/msal-net-invalid-client for details. Original exception: AADSTS7000215: Invalid client secret provided. Ensure the secret being sent in the request is the client secret value, not the client secret ID, for a secret added to app '{CLIENTID_FOR_AZUREFUNCTION}'.

Is this AzureAd config and calling GetAccessTokenForAppAsync the right approach?


Solution

  • TL;DR

    Whilst I had correctly configured the AzureAd values I must at some point have chosen to "Manage User Secrets" in the VS IDE. That had created a different ClientSecret and that was overriding the correct value in local.settings.json.

    Thanks to this GitHub issue and comment from the MSAL team, https://github.com/AzureAD/microsoft-identity-web/issues/379#issuecomment-666526566