0
votes

I have been following this resource to create an application on azure that authenticates itself with the azure active directory. We want to use the token from this auth interaction with exchange and the EWS managed API to impersonate everyone in our organization, without them having to login.

I have registered an app with our organization on azure and gave it permission to exchange. After creating a certificate and setting up our azure application with it, I can get an app-only access token using the ADAL via the following code...

string authority = "https://login.windows.net/{tenant}/oauth2/authorize";
AuthenticationContext authenticationContext = new AuthenticationContext(authority, false);
var certPath = @"C:\path\to\cert\Cert.pfx";
var certfile = System.IO.File.OpenRead(certPath);
var certificateBytes = new byte[certfile.Length];
certfile.Read(certificateBytes, 0, (int)certfile.Length);
var cert = new X509Certificate2(
    certificateBytes,
    PRIVATE_KEY_PASSWORD,
    X509KeyStorageFlags.Exportable |
    X509KeyStorageFlags.MachineKeySet |
    X509KeyStorageFlags.PersistKeySet);

ClientAssertionCertificate cac = new ClientAssertionCertificate(CLIENT_ID, cert);

var token = await authenticationContext.AcquireTokenAsync("https://outlook.office365.com/", cac);

With this token the code to interact with the Ews managed API looks like this..

ServicePointManager.ServerCertificateValidationCallback = CertificateValidationCallBack;
_ExchangeService = new ExchangeService(ExchangeVersion.Exchange2013_SP1) {
    Credentials = new OAuthCredentials(token),
    Url = new Uri("https://outlook.office365.com/ews/exchange.asmx"),
    ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.PrincipalName, "[email protected]"),
};

_ExchangeService.HttpHeaders.Add("X-AnchorMailbox", "[email protected]");

This appears to be the correct way to set up impersonation via the managed api, though every request returns a 401 unauthorized error.

My question boils down to, am I doing something wrong here? Or is there something else that I need to do to give my application access to the exchange server?

The article I was following did mention a client consent flow, but the details around that section aren't clear. Can I not give my app permission for everyone without prompting them for consent initially.

2

2 Answers

2
votes

It is working on my side , please firstly confirm you have set Use Exchange Web Services with full access to all mailboxes application permission for Office 365 Exchange Online to your app which protected by Azure AD : enter image description here For testing , you could try below code :

        ExchangeService exchangeService = new ExchangeService(ExchangeVersion.Exchange2013);
        exchangeService.Url = new Uri("https://outlook.office365.com/ews/exchange.asmx");
        exchangeService.ImpersonatedUserId = new ImpersonatedUserId(ConnectingIdType.SmtpAddress, "[email protected]");
        exchangeService.HttpHeaders.Add("X-AnchorMailbox", "[email protected]");
        exchangeService.TraceEnabled = true;
        exchangeService.TraceFlags = TraceFlags.All;
        exchangeService.Credentials = new OAuthCredentials(token.AccessToken);
        Folder newFolder = new Folder(exchangeService);
        newFolder.DisplayName = "TestFolder";

        newFolder.Save(WellKnownFolderName.Inbox);

Which will create a new folder in the target account's Inbox .

0
votes

I have a working solution with almost the same code.

Only difference that I can ascertain is the authentication context URL, which is https://login.microsoftonline.com/*tenant-id* .

Also, I use new ImpersonatedUserId(ConnectingIdType.SmtpAddress, email);

Are you sure that [email protected] is the full sign-in name, or is it just the e-mail address?