Skip to content

Instantly share code, notes, and snippets.

@watahani
Last active August 10, 2020 08:20
Show Gist options
  • Save watahani/f09e17bae35730af5a3729952fe29d74 to your computer and use it in GitHub Desktop.
Save watahani/f09e17bae35730af5a3729952fe29d74 to your computer and use it in GitHub Desktop.
Azure AD Client Credential Flow sample using JWT Bearer Assertion
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Security.Cryptography.X509Certificates;
using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
namespace console
{
class Program
{
private static readonly HttpClient client = new HttpClient();
private static readonly string clientId = "<client_id>";
private static readonly string authority = "https://login.microsoftonline.com/<tenantid>";
private static readonly string certThumbprint = "<thumbprint>";
static async Task Main(string[] args)
{
var clientAssertion = GenerateClientAssertion();
var req = new HttpRequestMessage();
var res = await client.PostAsync( $"{authority}/oauth2/v2.0/token", new FormUrlEncodedContent(new Dictionary<string, string>(){
{"scope", "https://graph.microsoft.com/.default"},
{"client_id", clientId},
{"client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"},
{"client_assertion", clientAssertion},
{"grant_type", "client_credentials"}
}));
var body = await res.Content.ReadAsStringAsync();
System.Console.WriteLine(body);
}
private static String GenerateClientAssertion()
{
// https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/blob/edafefa8f6f96bdd8b654dd83fb34cd17e9ab1e2/tests/Microsoft.Identity.Test.Integration.net45/HeadlessTests/ConfidentialClientIntegrationTests.cs#L511
var aud = $"{authority}/oauth2/token";
var claims = new Dictionary<string, object>(){
{ "aud", aud },
{ "iss", clientId },
{ "jti", Guid.NewGuid().ToString() },
{ "sub", clientId }
};
var signingCert = LoadCertificateByThumbprintFromCurrentCertMy(certThumbprint);
var signingCredentials = new X509SigningCredentials(signingCert);
var securityTokenDescriptor = new SecurityTokenDescriptor
{
Claims = claims,
SigningCredentials = new X509SigningCredentials(signingCert)
};
var handler = new JsonWebTokenHandler();
var signedClientAssertion = handler.CreateToken(securityTokenDescriptor);
return signedClientAssertion;
}
private static X509Certificate2 LoadCertificateByThumbprintFromCurrentCertMy(String thumbprint)
{
X509Store store = new X509Store(StoreLocation.CurrentUser);
try
{
store.Open(OpenFlags.ReadOnly);
// Place all certificates in an X509Certificate2Collection object.
X509Certificate2Collection certCollection = store.Certificates;
// If using a certificate with a trusted root you do not need to FindByTimeValid, instead:
// currentCerts.Find(X509FindType.FindBySubjectDistinguishedName, certName, true);
X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindByThumbprint, thumbprint, false);
if (signingCert.Count == 0)
return null;
// Return the first certificate in the collection, has the right name and is current.
return signingCert[0];
}
finally
{
store.Close();
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment