0
votes

I am developing a daemon application. I have downloaded the sample application to try to see if it would work, but get the same error from that app too. My admin has checked as much as possible on his end, revealing nothing. The desired end result is to have a program that can send emails on behalf of users and read mail from certain mailboxes. I also need to be able to confirm in a quick way that my application is configured correctly.

This program will not have user interactivity and will be operating on behalf of the company.

What I've done:

  1. Created app registration at aad.portal.azure.com.
  2. Created a client secret.
  3. Admin has given consent for 11 Microsoft Graph permissions: Mail.Read (Application), Mail.ReadBasic (Application), Mail.ReadBasic.All (Application), Mail.ReadWrite (Application), Mail.Send (Application), User.Export.All (Application), User.Invite.All (Application), User.ManageIdentities.All (Application), User.Read (Delegated), User.Read.All (Application), User.ReadWrite.All (Application)
  4. Integration Assistant (preview) shows all green except for 1 item, which is "Use certificate credentials instead of password credentials (client secrets).". This particular one is acceptable to me.
  5. On the Authentication page, this is not treated as a public client.

Nuget packages used:

  • Microsoft.Identity.Client 4.13.0
  • Microsoft.Graph 3.5.0

My sandbox code:

async void Main()
{
    var graphFacade = new MsGraphFacade();

    Console.WriteLine(await graphFacade.ValidateCredentialsAsync());
}

class MsGraphFacade 
{

    private static async Task<GraphServiceClient> GetGraphApiClient()
    {
        var clientId = "(Redacted)";
        var secret = "(Redacted)";

        var app = ConfidentialClientApplicationBuilder
        .CreateWithApplicationOptions(new ConfidentialClientApplicationOptions{
        ClientId = clientId,
        ClientSecret = secret,
        AadAuthorityAudience = AadAuthorityAudience.AzureAdMultipleOrgs,
        })
        .Build();

        Console.WriteLine("Getting token");
        var token = await app
        .AcquireTokenForClient(new[] { "https://graph.microsoft.com/.default" })
        .ExecuteAsync();

        Console.WriteLine("Got token");
        var accessToken = token.AccessToken;

        var graphServiceClient = new GraphServiceClient(
            new DelegateAuthenticationProvider((requestMessage) =>
        {
            requestMessage
                .Headers
                .Authorization = new AuthenticationHeaderValue("bearer", accessToken);

            return Task.CompletedTask;
        }));

            Console.WriteLine("New client returned.");

            return graphServiceClient;
    }

    public async Task<bool> ValidateCredentialsAsync()
    {
        try
        {
            Console.WriteLine("Attempting something simple");

            var client = await GetGraphApiClient();

            var user = await client.Users
                .Request()
                .Top(1)
                .Select(x => x.DisplayName)
                .GetAsync();

            if (user != null)
            {
                return true;
            }
            return false;
        }
        catch (Exception e)
        {
            Console.WriteLine("2");
            Console.WriteLine(e);
            return false;
        }
    }
} 

Output of code:

Attempting something simple 
Getting token 
Got token 
New client returned. 
2

Code: Authorization_IdentityNotFound Message: The identity of the calling application could not be established. 
    Inner error:
        AdditionalData:
            request-id: f31bc340-1cdf-485f-b852-f1e2822201ef
            date: 2020-05-15T20:24:38
False

Any ideas of what to check next or tweak will be greatly appreciated.

Thanks in advance for any help.

1
Did you do the admin consent as this post suggested? stackoverflow.com/questions/49522572/…Allen Wu

1 Answers

0
votes

I'm guessing the issue is you have not specified the target tenant.

You've defined it like this:

AadAuthorityAudience = AadAuthorityAudience.AzureAdMultipleOrgs

You need to instead specify Azure public cloud + tenant guid. I'm on my phone right now so I can't look up the exact syntax :/