Question:
You have an application registered in Microsoft Entra ID and you have configured appsettings.json as follows:
{
"clientId": "your-client-id",
"tenantId": "your-tenant-id"
}
Your application is currently configured to perform requests to Microsoft Graph API on behalf of a user. Here is the relevant code snippet:
private static IAuthenticationProvider CreateAuthorizationProvider(string authType)
{
var config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true).Build();
List<string> scopes = new List<string>();
scopes.Add(clientId + "/.default");
IPublicClientApplication client;
string authority = $"https://login.microsoftonline.com/{config.tenantId}/v2.0";
client = PublicClientApplicationBuilder.Create(config.clientId)
.WithAuthority(new Uri(authority))
.Build();
return MsalAuthenticationProvider.GetInstance(client, scopes.ToArray());
}
However, your application is evolving into a service application (daemon) that needs to access Microsoft Graph API on behalf of itself, not on behalf of a user. Additionally, due to varying security requirements across different environments, your application needs to support both client secret and client certificate for authentication. The authType parameter in the CreateAuthorizationProvider function is intended to determine the authentication method, but it is currently unused. Certificate must by obtained by name (MyCertificate.pfx - stored in configuration) from KeyVault account cert-holder.
How should you modify the appsettings.json and the code to meet these new requirements?
Answer:
You should modify appsettings.json to include the client secret, path, and password of your client certificate:
{
"clientId": "your-client-id",
"tenantId": "your-tenant-id",
"clientSecret": "your-client-secret",
"certificateName": "MyCertificate.pfx"
}
The code should be modified as follows:
private static IAuthenticationProvider CreateAuthorizationProvider(string authType)
{
var config = new ConfigurationBuilder()
.SetBasePath(System.IO.Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false, true).Build();
List<string> scopes = new List<string>();
scopes.Add(clientId + "/.default");
IConfidentialClientApplication client;
string authority = $"https://login.microsoftonline.com/{config.tenantId}/v2.0";
ConfidentialClientApplicationBuilder builder = ConfidentialClientApplicationBuilder.Create(config.clientId)
.WithAuthority(new Uri(authority));
if (authType == "secret")
client = builder.WithClientSecret(config.clientSecret).Build();
else if (authType == "certificate")
{
var client = new CertificateClient(new Uri("https://cert-holder.vault.azure.net"), new DefaultAzureCredential());
var certificate = await client.GetCertificateAsync(config.certificateName);
// Alt: X509Certificate2 certificate = new X509Certificate2(config.certificatePath, config.certificatePassword);
client = builder.WithCertificate(certificate).Build();
}
else
throw new ArgumentException("Invalid authentication type");
return MsalAuthenticationProvider.GetInstance(client, scopes.ToArray());
}