Skip to content

Instantly share code, notes, and snippets.

@Sn3akyP3t3
Created July 8, 2020 15:52
Show Gist options
  • Save Sn3akyP3t3/e84d451e63845d0e566b2127f7e1e45f to your computer and use it in GitHub Desktop.
Save Sn3akyP3t3/e84d451e63845d0e566b2127f7e1e45f to your computer and use it in GitHub Desktop.
Files For [Bug] AcquireTokenForClient Causes Application To Terminate With Code 0 Without Any Explanation
using System.Security.Cryptography.X509Certificates;
namespace TestingGetEwsToken
{
/// <summary> An incomplete data Model for authentication modded for testing acquisition of a token. </summary>
public class AuthenticationConfigModel
{
/// <summary> (Required) Also known as the Application ID in Microsoft Azure.
/// Gets or sets the identifier of the client. </summary>
/// <value> The identifier of the client. </value>
public string ClientId { get; set; }
/// <summary> (Required) Also known as Directory ID in Microsoft Azure.
/// Gets or sets the identifier of the tenant. </summary>
/// <value> The identifier of the tenant. </value>
public string TenantId { get; set; }
/// <summary> (Required) Gets or sets the certificate thumbprint. </summary>
/// <value> The certificate thumbprint. </value>
public string CertificateThumbprint { get; set; }
/// <summary> Gets or sets the certificate. </summary>
/// <value> The certificate. </value>
internal X509Certificate2 Certificate { get; set; }
}
}
using System;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
namespace TestingGetEwsToken
{
/// <summary> Authentication configuration provisioning logic. </summary>
internal class AuthenticationConfigProvider
{
internal readonly AuthenticationConfigModel _authenticationModel;
/// <summary> Constructor requiring full path to the json configuration file. </summary>
public AuthenticationConfigProvider()
{
_authenticationModel = new AuthenticationConfigModel
{
ClientId = "ChangeMe",
CertificateThumbprint = "ChangeMe-GetFromCertificateManager",
TenantId = "ChangeMe"
};
_authenticationModel.Certificate = ReadCertificate(_authenticationModel.CertificateThumbprint);
}
/// <summary> Reads a certificate installed on the current server given the cert thumbprint. </summary>
/// <exception cref="ArgumentException"> Thrown when one or more arguments have unsupported or illegal values. </exception>
/// <param name="certificateThumbprint"> The certificate thumbprint matching one installed on the server. </param>
/// <returns> The matching certificate. </returns>
private static X509Certificate2 ReadCertificate(string certificateThumbprint)
{
if (string.IsNullOrWhiteSpace(certificateThumbprint))
{
throw new ArgumentException("certificateThumbprint should not be empty. Please set the certificateThumbprint", "certificateThumbprint");
}
X509Certificate2 cert = null;
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser))
{
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certCollection = store.Certificates;
// Find unexpired certificates.
X509Certificate2Collection currentCerts = certCollection.Find(X509FindType.FindByTimeValid, DateTime.Now, false);
// From the collection of unexpired certificates, find the ones with the correct name.
X509Certificate2Collection signingCert = currentCerts.Find(X509FindType.FindByThumbprint, certificateThumbprint, false);
// Return the first certificate in the collection, has the matching thumbprint and is current.
cert = signingCert.OfType<X509Certificate2>().OrderByDescending(c => c.NotBefore).FirstOrDefault();
}
return cert;
}
}
}
using Microsoft.Exchange.WebServices.Data;
using Microsoft.Identity.Client;
using System;
namespace TestingGetEwsToken
{
class Program
{
private static AuthenticationConfigProvider _authenticationConfigProvider;
static void Main(string[] args)
{
_authenticationConfigProvider = new AuthenticationConfigProvider();
_ = AttemptToGetToken();
}
private static async System.Threading.Tasks.Task AttemptToGetToken()
{
// Configure the MSAL client to get tokens
var ewsScopes = new string[] { "https://outlook.office.com/.default" };
var app = ConfidentialClientApplicationBuilder.Create(_authenticationConfigProvider._authenticationModel.ClientId)
.WithAuthority(AzureCloudInstance.AzurePublic, _authenticationConfigProvider._authenticationModel.TenantId)
.WithCertificate(_authenticationConfigProvider._authenticationModel.Certificate)
.Build();
AuthenticationResult result = null;
try
{
// Make the interactive token request. This is where the bug seems to occur.
result = await app.AcquireTokenForClient(ewsScopes).ExecuteAsync();
// Configure the ExchangeService with the access token
var ewsClient = new ExchangeService();
ewsClient.Url = new Uri("https://outlook.office365.com/EWS/Exchange.asmx");
ewsClient.Credentials = new OAuthCredentials(result.AccessToken);
}
catch (MsalException ex)
{
Console.WriteLine($"Error acquiring access token: {ex.ToString()}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.ToString()}");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment