Search code examples
c#azuremicrosoft-graph-api

How can I use client certificates for Graph authentification with TokenAcquirerFactory inside of a console application?


I've used this official guide to build an console application which runs as a daemon client and automatically acquirers an Graph AccessToken using the credentials provided in appsettings.json. My console app must also modify DistributionLists and as you can only modify them using the ExchangeOnlineManagement PowerShell Module . I use the C# PowerShell package to call these functions.

For the ExchangeOnline part I can easily use a client certificate:

using var ps = PowerShell.Create(runspace);

ps.AddCommand("Connect-ExchangeOnline");
ps.AddParameters(new Dictionary<string, object>
{
    ["Organization"] = azureDomain,
    ["CertificateThumbprint"] = certThumbprint,
    ["AppID"] = clientId
});

Now I would like to configure my appsettings.json that TokenAcquirerFactory also uses a certificate. Currently my appsettings.json follows this schema:

{
    "AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "TenantId": "[Enter here the tenantID or domain name for your Azure AD tenant]",
        "ClientId": "[Enter here the ClientId for your application]",
        "ClientCredentials": [
            {
                "SourceType": "ClientSecret",
                "ClientSecret": "[Enter here a client secret for your application]"
            }
        ]
    }
}

which needs an ClientSecret.

I want to use certificate authentification for my daemon app, because then I could use the certificate, which is already configured in the azure portal for the ExchangeOnline part, for my deamon app too. So I would just need to reset one certificate every year, instead of one certificate and one token.

Does anybody know how I can achieve this?

Edit: You can find a project which is using the SecretToken, as I currently do, here.


Solution

  • Okay with the help of @jdweng and a lot of trial and error I was able to come up with this config scheme which works now:

    {
        "AzureAd": {
            "Instance": "https://login.microsoftonline.com/",
            "TenantId": "[Enter here the tenantID or domain name for your Azure AD tenant]",
            "ClientId": "[Enter here the ClientId for your application]",
            "ClientCredentials": [
                {
                    "SourceType": "StoreWithThumbprint",
                    "CertificateStorePath": "LocalMachine/Root",
                    "CertificateThumbprint": "<My Thumbprint>"
                }
            ]
        }
    }
    

    Now TokenAcquirerFactory uses the installed certificate with the thumbprint specified in the appsettings.json to get the AccessToken and GraphServiceClient from the Graph API.

    If you are now using a TokenAcquirerFactory

    var tokenAcquirerFactory = TokenAcquirerFactory.GetDefaultInstance();
    tokenAcquirerFactory.Services.AddMicrosoftGraph();
    ServiceProvider = tokenAcquirerFactory.Build();
    

    you can simply make API calls by using the ServiceProvider:

    var graphClient = ServiceProvider.GetRequiredService<GraphServiceClient>();
    var me = await graphClient.Me.GetAsync();
    

    I found the main parts for my config here and here.