Problem with connecting to Outlook via IMAP using OAuth2 authentication

Serhii Bezkostnyi 5 Reputation points
2024-06-04T13:35:46.83+00:00

We are building a solution where we connect to email mailboxes via IMAP, fetch and store some relevant emails, so that later we can display them in the web UI. Later on we plan to add support for replying to the relevant emails directly from web UI.

We have implemented OAuth2 for authenticating an IMAP connection to Outlook mailboxes via OAuth2 identity platform using authorization code flow. It was working during the initial testing using personal Outlook mailboxes (the ones from outlook.live.com) back in ~January/February 2024, but it doesn't work anymore. We also need it to work with enterprise Outlook mailboxes, but we didn't test if it worked back in ~January/February 2024.

Nowadays it fails when trying to authenticate IMAP connection to Outlook mailbox, even the personal one. The authorization code flow itself works fine and we are able to get access tokens without any problems, but these access tokens not working as expected.

Error we are getting:

DEBUG IMAP: AUTHENTICATE XOAUTH2 command result: A1 NO AUTHENTICATE failed.

Some technical details about our solution:

  • It's written in Java and we are using Java Mail library to establish IMAP connection, fetch and store some relevant emails
  • We are using SASL XOAUTH2 authentication mechanism for IMAP
  • We have an application registered in Microsoft Entra ID with the following settings:
    • Supported account types: Accounts in any organizational directory (Any Microsoft Entra ID tenant - Multitenant) and personal Microsoft accounts (e.g. Skype, Xbox)
    • Configured permissions:
      • Microsoft Graph (delegated)
        • IMAP.AccessAsUser.All
        • SMTP.Send
        • User.Read
        • offline_access

During the OAuth2 authorization code flow we request IMAP.AccessAsUser.All, SMTP.Send, User.Read, offline_access scopes (without any prefixes), and use https://login.microsoftonline.com/common/oauth2/v2.0/authorize as authorization endpoint.

If we try to change scopes to be https://outlook.office.com/IMAP.AccessAsUser.All, SMTP.Send, User.Read, offline_access (as per documentation here), it expectedly fails during authorization code flow with invalid_scope error.

We have read documentation from here https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth, but it asks to use deprecated scopes that we cannot configure for our application anymore (they are not on the list), and later part of the document talks about using client credentials grant flow, which is not what we need (we want to access mailboxes on behalf of the user).

We would like to get help how to make it work. Thanks in advance!

EDIT:

We were able to make it work using the idea described in https://stackoverflow.com/a/48584417/25413714.

What we are doing now is the following:

  • Acquire access & refresh tokens using Microsoft Graph scopes (IMAP.AccessAsUser.All, SMTP.Send, User.Read, offline_access)
  • Immediately after that request a new access token using refresh token from the previous step, but this time with Outlook scopes (https://outlook.office.com/IMAP.AccessAsUser.All https://outlook.office.com/SMTP.Send)

This new access token works and allows an IMAP connection to Outlook. But this "solution" does not look like something intended and we are not sure how long it would continue to work.

Outlook
Outlook
A family of Microsoft email and calendar products.
3,427 questions
Microsoft Graph
Microsoft Graph
A Microsoft programmability model that exposes REST APIs and client libraries to access data on Microsoft 365 services.
11,458 questions
{count} vote