Not able to access Outlook365 mailbox

We’re trying to access and manage emails in an Outlook 365 mailbox from a Windows service application. We’re using Aspose.Email to provide functionality in the app that previously accessed a local Exchange server. We’re looking to migrate the code to work with Outlook 365 and are running into problems.

Here’s what we’ve got set up so far.

  • We have an application registered in Azure with tenantID and clientID. It’s set up with an account type as ‘Accounts in this organizational directory only’ (only our single tenant). We have the application enabled, and the ‘Visible to users’ flag set to Yes.
    o We have the platform settings configured as a ‘Mobile and desktop application’.
    o Not sure how the ‘Redirect URI’ needs to be set, but following the recommendations, we have it set to http://localhost
  • For the credentials we created a client secret and have that string available for our application.
  • We have created an application owner, but there wasn’t much guidance on requirements for that assignment. We picked the IT manager.
  • There is an app role created, and we used our own values/descriptions, but again, not sure if there was something that needed to be set specifically to allow access.
  • That allows the API to show as registered.
  • We’ve added a scope which lists an ‘Application ID URI:’ as ‘api://~our client id~’, ‘Who can consent’ as Admins and users, with a ‘State’ as Enabled.
    o The scope shows as in the Expose an API panel
  • We have an API/Permission set up for Office 365 Exchange Online, set for Application permissions with the Status set to Granted for our domain.

As far as I can see from the MS documentation, this should allow us to access the O365 Exchange from our Windows service application.

On our application side we have the following code:
private class AccessParameters
{
public string TenantId { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string[] Scopes { get; set; } = { “Sign in to Outlook” };
}

            private static async Task<string> GetAccessToken(AccessParameters accessParameters)
            {
                var cca = ConfidentialClientApplicationBuilder
                .Create(accessParameters.ClientId)
                .WithClientSecret(accessParameters.ClientSecret)
                .WithTenantId(accessParameters.TenantId)
                .Build();

                var result = cca.AcquireTokenForClient(accessParameters.Scopes).ExecuteAsync().Result;

                return result.AccessToken;
            }

            IEWSClient client = null;

            AccessParameters exchangeAccess = new AccessParameters();
            exchangeAccess.TenantId = "~ our tenant ID ~";
            exchangeAccess.ClientId = "~ our client ID ~";
            exchangeAccess.ClientSecret = "~ our secret ~";

            string accessToken = GetAccessToken(exchangeAccess).Result;

            NetworkCredential credentials = new OAuthNetworkCredential("~ mailbox ~", accessToken);

            client = EWSClient.GetEWSClient("https://outlook.office365.com/EWS/Exchange.asmx", credentials);

Using this code, it comes back with a valid accessToken and NetworkCredential telling me it can properly authenticate against Azure. If I change one of the ID values it does fail, so this seems to work ok. But when it tries to get the EWSClient, it comes back with this error:
ifa: ‘The impersonation principal name is invalid.’

If I try this simplified alternative code:
string clientId = “~ our client ID ~”;
string clientSecret = “~ our secret ~”;
string refreshToken = “~ our tenant ID ~”;
string mailboxUri = “https://outlook.office365.com/EWS/Exchange.asmx”;

        IEWSClient client = EWSClient.GetEWSClient(mailboxUri, clientId, clientSecret, refreshToken);

I get the following error:
System.Net.WebException: ‘The request failed with HTTP status 401: Unauthorized’

These are from the sample code on how to access Exchange on O365.

Other than any other comments on the above setup/code, these are the questions I had:

  • Do we really need the ‘Redirect URI’ if we’re accessing from a Windows service application where we’re using a client secret credential?
    o If we do, what does it need to be set as and does that mean we need to implement a local web server to handle the redirect? Examples?
  • Are there any other requirements for the application owner or the app role?
    o Does the mailbox owner for the account we want to manipulate need to be an application owner?
  • Are there other requirements on defining the scope we need to implement?
  • Is there something missing from the code samples?
  • Any other guidance on how to make this work?

Thanks for any help you can provide.
James

Hello @jdunnEdupoint,

Thank you for contacting our support forum.

  • When using client credentials flow (which involves a client secret), you typically don’t need a redirect URI. Redirect URIs are more relevant for interactive flows where a user needs to authenticate and authorize access. Since you’re using a service application, you’re likely fine without it.

  • An application owner needs to have permissions to register applications in Azure AD and configure API permissions for MS 365. A mailbox owner doesn’t necessarily need to be an application owner. The app role you need would depend on what actions you want to perform with the mailbox.

  • The scope you define should align with the permissions your app needs to perform its tasks. For MS 365, you might need scopes related to mail, calendars, or contacts depending on the operations you want to perform.

Please refer to our guidelines and check out our example of a simple app to connect to MS 365.

Feel free to contact us if you encounter any additional issues.