Skip to content

Authenticating to Microsoft Graph

Ivan Franjic edited this page Aug 12, 2019 · 3 revisions

This article assumes that application has been registered in Azure. See this link for more information -> Registering application

Once Azure Application has been setup and configured for consuming Graph Api, easiest was to authenticate is by implementing IAuthorizationProvider interface from Microsoft.Graph.CoreAuth namespace.

IAuthorizationProvider have following definition:

/// <summary>
/// Authorization provider interface.
/// </summary>
public interface IAuthorizationProvider
{
    /// <summary>
    /// Create authentication header which will be used for authenticating requests.
    /// </summary>
    /// <returns></returns>
    Task<AuthenticationHeaderValue> GetAuthenticationHeader();

    /// <summary>
    /// Name of the provider.
    /// </summary>
    string Name { get; }
}

AuthenticationHeaderValue from your implementation will be used as Authorization header passed to Graph API.

Simplest way to implement that interface is by consuming ADAL library -> https://www.nuget.org/packages/Microsoft.IdentityModel.Clients.ActiveDirectory/

Once nuget package has been installed in your project you can create custom IAuthorizationProvider for use against Exchange REST Api:

internal class TestAuthenticationProvider : IAuthorizationProvider
{
    private string ResourceUri
    {
        get { return "https://graph.microsoft.com"; }
    }

    public async Task<AuthenticationHeaderValue> GetAuthenticationHeader()
    {
        string token = await this.GetToken();
        return new AuthenticationHeaderValue(
            "Bearer",
            token);
    }

    public string Name
    {
        get { return nameof(TestAuthenticationProvider); }
    }

    private async Task<string> GetToken()
    {
        string authority = $"https://login.microsoftonline.com/{AppConfig.TenantId}";
        AuthenticationContext context = new AuthenticationContext(authority);

        X509Certificate2 certFromStore = null;
        using (X509Store store = new X509Store(StoreLocation.CurrentUser))
        {
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection collection = store.Certificates.Find(
                X509FindType.FindByThumbprint,
                AppConfig.CertThumbprint,
                false);

            if (collection.Count == 1)
            {
                certFromStore = collection[0];
            }
        }

        if (certFromStore == null)
        {
            throw new ArgumentNullException("Certificate");
        }

        ClientAssertionCertificate cert = new ClientAssertionCertificate(
            AppConfig.ApplicationId.ToString(),
            certFromStore);

        AuthenticationResult token = await context.AcquireTokenAsync(
            this.ResourceUri,
            cert);

        return token.AccessToken;
    }
}

These should be values for AppConfig keys:

  1. AppConfig.TenantId -> Guid of your Office 365 tenant,
  2. AppConfig.CertThumbprint -> Certificate thumbprint retrieved while configuring Application manifest in Azure,
  3. AppConfig.ApplicationId -> Guid of your application on Azure (Application ID)

Below is simple example of AppConfig.cs:

internal static class AppConfig
{
    public static string TenantId { get => ConfigurationManager.AppSettings["TenantId"]; }
    public static string CertThumbprint { get => ConfigurationManager.AppSettings["CertThumbprint"]; }
    public static string ApplicationId { get => ConfigurationManager.AppSettings["ApplicationId"]; }
}

// App.config

<appSettings>
  <add key="TenantId" value="ac3d022d-e4ba-410f-ab36-778a04de6833"/>
  <add key="CertThumbprint" value="FFFFFB302774DBCF0587F827FC746FD2FEE506FB"/>
  <add key="ApplicationId" value="aaaaaaaa-aacf-4087-a101-759eb732dcdf"/>
</appSettings>

Once interface implemented it can be used to provide authorization to the service:

ExchangeServiceContext context = new ExchangeServiceContext(
  new TestAuthenticationProvider(), 
  "MyUserAgent");

ExchangeService exchangeService = context["testmailbox@domain.com"];