I have implemented Oauth 2.0 Azure API Authentication by creating a token with Client Secret. I am trying to use a Client certificate instead of a Client secret for creating OAuth 2.0 token. Could you please guide me on how to use the Client certificate to get a token? C# Code needed for implementing same.
Try to see here. It shows how to get an access token with a certificate by the HTTP request.
POST https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&client_id=<client-id>
&client_assertion_type=urn:ietf:params:oauth:client-assertion-type:jwt-bearer
&client_assertion=<An assertion (a JSON web token) that you need to create and sign with the certificate you registered as credentials for your application. >
&grant_type=client_credentials
C#:
1. Use Azure.Identity
// Authenticate a service principal with a certificate
using Azure.Identity;
var certificate = new X509Certificate2("./app/certs/certificate.pfx");
var credential = new CertificateCredential(tenantId, clientId, certificate);
2. Use WithCertificate
in MSAL.NET
The blog: https://cmatskas.com/create-a-net-core-deamon-app-that-calls-msgraph-with-a-certificate/
using Microsoft.Graph;
using Microsoft.Identity.Client;
using System;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
namespace DaemonConsole
{
public class ClientCredentialsAuthProvider : IAuthenticationProvider
{
private readonly IConfidentialClientApplication msalClient;
private readonly string[] scopes;
public ClientCredentialsAuthProvider(AuthenticationConfig config)
{
scopes = new string[] { config.Scopes };
msalClient = ConfidentialClientApplicationBuilder
.Create(config.ClientId)
.WithCertificate(ReadCertificateLocal(config.CertificateName))
.WithAuthority(AadAuthorityAudience.AzureAdMyOrg, true)
.WithTenantId(config.Tenant)
.Build();
}
public async Task<string> GetAccessTokenAsync()
{
try
{
var result = await msalClient.AcquireTokenForClient(scopes)
.ExecuteAsync();
return result.AccessToken;
}
catch (Exception exception)
{
Console.WriteLine($"Error getting access token: {exception.Message}");
return null;
}
}
// This is the required function to implement IAuthenticationProvider
// The Graph SDK will call this function each time it makes a Graph
// call.
public async Task AuthenticateRequestAsync(HttpRequestMessage requestMessage)
{
requestMessage.Headers.Authorization =
new AuthenticationHeaderValue("bearer", await GetAccessTokenAsync());
}
private X509Certificate2 ReadCertificateLocal(string certificateName)
{
X509Certificate2 cert = null;
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = store.Certificates;
X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certificateName, false);
cert = signingCert.OfType<X509Certificate2>().OrderByDescending(c => c.NotBefore).FirstOrDefault();
}
return cert;
}
}
}