0

I have an ASP.NET Core Web Api in Azure that supports Azure AD authentication. I have an Azure TimerTrigger function that is attempting to retrieve a token using the ITokenAcquisition .GetAccessTokenForAppAsync() method.

code snipit

private async Task PrepareAuthenticatedClient()
    {
        var scope = "api://ClientId-Guid/.default";

        try
        {
            var accessToken = await _tokenAcquisition.GetAccessTokenForAppAsync(scope);
            
            _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
            _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
            throw;
        }
    }

When I do this the function app stops running with an Access Violation code.

console log message

Between my appsettings.json and secrets.json I believe I have the necessary AzureAd parameters necessary.

appsettings.json secrets.json

What would cause an Access Violation in this case? Is there a reason why a more meaningful message isn't returned?

I have tried running locally using Azurite and against a valid storage account.

I have attempted inputting the scope parameter in different forms:

api:///ReadAccess

api:///ReadAccess/.default

ReadAccess

It was proposed that the _tokenAcquisition maybe null which could be causing the violation. Here is what is in that object at the time of requesting the token.

_tokenAcquisition

msilkwood
  • 1
  • 2
  • "Access Violation" may be misleading. These error codes, as you may already have discovered, relate to the [NTSTATUS enumeration](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55). STATUS_ACCESS_VIOLATION means that a memory address that your code tried to read was invalid; in .net terms, a null reference exception. It has nothing to do with being denied access to a remote resource. The most likely candidate I can see from your code sample is `_tokenAcquisition` being null – Tom W Jan 05 '23 at 15:07
  • ....but we would need to see an [MCVE](https://stackoverflow.com/help/minimal-reproducible-example) to be certain. – Tom W Jan 05 '23 at 15:07
  • Thank you for the quick response Tom. I considered _tokenAcquisition being null, but I do not believe that is the case. I'll add a snipit in the question to show what is in that object at the time the token is requested. – msilkwood Jan 05 '23 at 15:54
  • paste as code , not pics . please – Giovanni Contreras Jan 06 '23 at 02:50
  • @GiovanniContreras I added the code as requested. – msilkwood Jan 06 '23 at 13:10
  • have you seen this answer https://stackoverflow.com/a/68947741/14973743 ? – Anand Sowmithiran Jan 06 '23 at 13:53

1 Answers1

0

To fix this issue I changed the method I was using to retrieve the auth token. Since I am requesting authentication for the application itself, I updated to .AcquireTokenForClient().

 private async Task GetAuthenticationToken()
    {
        string[] scope = { $"{_configuration["AzureAd:ApiAppIdUri"]}/.default" };
        
        IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.CreateWithApplicationOptions(
            new ConfidentialClientApplicationOptions
            {
                TenantId = _configuration["AzureAd:TenantId"],
                ClientId = _configuration["AzureAd:ClientId"],
                RedirectUri = "",
                ClientSecret = _configuration["AzureAd:ClientSecret"]
            })
            .Build();

        AuthenticationResult authResult = await app.AcquireTokenForClient(scope).ExecuteAsync();

        _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
        _httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    }

Something important to note is that the app requesting auth must be registered in Azure Ad and be granted access to appropriate scopes. In the code above the scope would be the Audience Uri from the API, the ClientId and ClientSecret would be from the registration of this application which is requesting auth.

msilkwood
  • 1
  • 2