Office 365 and Rebex Graph with OAuth 2.0 authentication in unattended (app-only) mode: How to make it work

  |   Alexandr Pleskot

Microsoft 365 (formerly Office 365) supports two kinds of OAuth 2.0 authentication:

  • Delegated authentication is suitable for desktop, mobile or web applications with signed-in user present.
    This mode is described in detail in another article.

  • App-only authentication is suitable for services or daemons with no user present. Instead, these unattended applications authenticate using client secrets (application credentials) to receive an access token, which is then used to gain access to a mailbox using Rebex Graph library.

Before your application can start accessing mailboxes, you have to register it with Microsoft, assign the relevant permissions and configure mailbox access. The guide below describes what needs to be done to enable Graph access for unattended apps (app-only mode). For other protocols, see EWS article or IMAP and POP3 article.

Register yourself and your company

  1. Log into Azure Portal. If you don't have an account there yet, create it. You also have to set up a tenant that represents your company.

  2. If you administer more than one tenant, use Directories + subscriptions filter to select the tenant for whom to register an application.

    Create new app registration

Register your application

  1. In Azure Portal ⇒ expand the left menu ⇒ select Microsoft Entra ID ⇒ select App registrations ⇒ click + New registration. (Azure Portal is constantly evolving, so if you cannot find this page, use the search bar.)

    Creating app registration 1
  2. Name your application, choose which kind of accounts are going to use it, and click Register.

    Note: This guide is suitable for single tenant account types. For other types, further steps might be different.

    Creating app registration 2
  3. You successfully registered your application and you can view its associated IDs. Some of them will be needed later to obtain an OAuth 2.0 token.

    Creating app registration 3

Set up client secret (application password)

  1. In the left menu, select Certificates & secrets ⇒ click + New client secret.

    Adding client secret 1
  2. Provide some description for this secret, choose expiration period, and click Add.

    Adding client secret 2
  3. Immediately copy and save the newly created client secret's Value (not Secret ID). You will not be able to view the Value later anymore.

    Adding client secret 3

Add app permissions

  1. In the left menu, select API permissions ⇒ click + Add a permission.

    Adding app permissions 1
  2. Navigate to Microsoft Graph.

    Adding app permissions 2
  3. Click Application permissions ⇒ type Mail ⇒ check Mail.Read ⇒ click Add permissions.

    Note: Consider adding Mail.ReadWrite and Mail.Send as well, but these are not needed for this demo.

    Adding app permissions 2
  4. The newly-added Mail.Read permission has to be approved by your organization's administrator. Ask them to grant consent to your application by clicking Grant admin consent for [organization].

    Note: This grants read access to all Microsoft 365 Online mailboxes in your organization. To restrict this, read How to restrict mailbox access of Azure applications in app-only mode article.

    Adding app permissions 4
  5. Application permissions have been granted. Optionally, you can remove the delegated User.Read permission which is not needed for app-only application - click the context menu on the right side of the permission and select Remove permission.

    Adding app permissions 5
  6. Congratulations! Now you have registered an application for accessing Office 365 mailboxes via Microsoft Graph API and received its Application (client) ID, Client secret and Directory (tenant) ID.

    These strings are going to be used by your application to authenticate to Microsoft 365 via OAuth 2.0 and receive an OAuth token. This token is then used to authenticate to Exchange Online using Rebex Graph.

Let's write some code!

  1. In your application, add reference to Microsoft.Identity.Client package, and specify your IDs, the secret, and the e-mail address. Specify the scope to request a token as well (use https://graph.microsoft.com/.default in app-only mode).

    // application (client) ID obtained from Azure
    const string ClientId = "cf2207a9-1111-1111-1111-5867ad1cf91e"; // change to your AppId
    
    // application's 'client secret' value (application password)
    const string ClientSecretValue = "ThisIsSomeVerySecretValue"; // change to your secret value
    
    // your organization's directory (tenant) ID
    const string TenantId = "fb561382-2222-2222-2222-06ab992d36b7"; // change to your TenantId
    
    // mailbox to access (not an alias)
    const string MailAddress = "someone@example.org"; // change this
    
    // default scope of permissions to request
    private static readonly string[] Scopes = new[] {
        "https://graph.microsoft.com/.default", // for accessing Exchange Online with app-only auth
    };
    
  2. Before your application connects to Office 365's Graph service, it has to request an OAuth 2.0 access token using the Microsoft's authentication API.

    using Microsoft.Identity.Client;
    
    ...
    
    // get an instance of 'CCA' API
    var cca = ConfidentialClientApplicationBuilder
        .Create(ClientId)
        .WithClientSecret(ClientSecretValue)
        .WithTenantId(TenantId)
        .Build();
    
    // acquire OAuth 2.0 access token from Microsoft 365
    AuthenticationResult result = await cca.AcquireTokenForClient(Scopes).ExecuteAsync();
    string accessToken = result.AccessToken;
    
  3. Then, connect to graph.microsoft.com using Rebex Graph package and use the acquired token to start accessing your organization's mailboxes.

    using Rebex.Net;
    
    ...
    
    // connect to Office 365 
    var client = new GraphClient();
    client.Connect();
    
    // specify mailbox to access
    client.Settings.Impersonation = new GraphImpersonation(MailAddress);
    
    // authenticate using the access token
    client.Login(accessToken);
    
    // start working with the mailbox
    ...
    

    To give this a try before adding the code to your application, try our GraphOAuthAppOnlyConsole sample.

Documentation for Rebex Graph .NET library

Any issues?