8

Facing connectivity issue with Office365 online with OAuth2.0 I have set up the application permissions and IMAP and SMTP connection.Basic authentication seems to be work fine. I believe IMAP is enabled. My application is configured as Accounts in any organizational directory (Any Azure AD directory - Multitenant) and uses grant type authorization code.

And Delegated Microsoft Graph scopes https://graph.microsoft.com/IMAP.AccessAsUser.All have been added: Client scopes added

Requested Auth code with https://login.microsoftonline.com/{tenantID}/oauth2/v2.0/authorize?response_type=code&client_id=1223&redirect_uri=http://localhost:5555 Access Token request https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token Requested Access token with resource as "https://graph.microsoft.com"

Requesting Access token Image

Successfully received access token with scopes as IMAP.AccessAsUser.All SMTP.Send

{
    "token_type": "Bearer",
    "scope": "IMAP.AccessAsUser.All SMTP.Send",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "access_token",
    "refresh_token": "refresh_token",
    "id_token": "id_token"
} 

So here is the Java Code (JavaMail jar 1.6.2 used)

Properties properties= new Properties();
properties.put("mail.imap.ssl.enable", "true");
properties.put("mail.imap.auth.mechanisms", "XOAUTH2");
//properties.put("mail.imap.sasl.enable", "true"); un-commented still results are same
properties.put("mail.imap.auth.login.disable", "true");
properties.put("mail.imap.auth.plain.disable", "true");
properties.put("mail.debug", "true");
properties.put("mail.debug.auth", "true");

Session session = Session.getInstance(props);
session.setDebug(true);

String userEmail = "emailuser@domain.onmicrosoft.com";
String accessToken = "accessToken";

final Store store = session.getStore("imap");
store.connect("outlook.office365.com","993",userEmail, accessToken);

Following output :

DEBUG: JavaMail version 1.6.2
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: getProvider() returning javax.mail.Provider[STORE,imap,com.sun.mail.imap.IMAPStore,Oracle]
DEBUG IMAP: mail.imap.appendbuffersize: -1
DEBUG IMAP: mail.imap.minidletime: 10
DEBUG IMAP: closeFoldersOnStoreFailure
DEBUG IMAP: trying to connect to host "outlook.office365.com", port 993, isSSL true
* OK The Microsoft Exchange IMAP4 service is ready. [TQBB]
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE 
NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG IMAP: AUTH: PLAIN
DEBUG IMAP: AUTH: XOAUTH2
DEBUG IMAP: protocolConnect login, host=outlook.office365.com, user=emailuser@domain.onmicrosoft.com, 
password=<non-null>
A1 AUTHENTICATE XOAUTH2 dXNlAQE=
A1 NO AUTHENTICATE failed.
Could not connect to the message store
javax.mail.AuthenticationFailedException: AUTHENTICATE failed.
at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:731)
at javax.mail.Service.connect(Service.java:366)
at myproject.EmailReceiver.downloadEmails(EmailReceiver.java:79)
at myproject.EmailReceiver.main(EmailReceiver.java:179)

Following other posts could not able to find scopes https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send in my Azure. May be they are legacy scopes.

Is there any other scopes other then "https://graph.microsoft.com/IMAP.AccessAsUser.All" and "https://graph.microsoft.com/SMTP.send" required to connect to Exchange online through IMAP. Or any problem with existing code.

Issue has been resolved my using scopes offline_access%20https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Foutlook.office365.com%2FSMTP.Send It provides permission to access Mail and also provides refresh token to re-generate the access token.

Note : Changing scope to offline_access https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send resolved the issue.

  • Did you redact some of the base64 in `A1 AUTHENTICATE XOAUTH2 dXNlAQE=` ? This is missing much of the login information (which might be a security feature of the library). It decodes to just "use\x01\x01" which is not a valid XOAUTH2 string. Also: did you use your access token within an hour? – Max Jul 03 '20 at 15:19
  • Hi Max , Since "A1 AUTHENTICATE XOAUTH2 dXNlAQE=" was security information I removed remaining string . Also: did you use your access token within an hour? Yes , I'm using access token within an hour. – Vinayak Mulgund Jul 06 '20 at 06:19
  • Encoding is performed in JavaMail library " String resp = "user=" + u + "\001auth=Bearer " + p + "\001\001"; byte[] ba = BASE64EncoderStream.encode( resp.getBytes(StandardCharsets.UTF_8)); " – Vinayak Mulgund Jul 06 '20 at 12:39
  • Okay, just wanted to make sure you redacted it and that you didn't break the library some how ;). MS's OAUTH2 is fairly new, so there's not a lot of collective knowledge on how or why it breaks, and they dont' seem to give very useful error messages. :( – Max Jul 06 '20 at 14:25

1 Answers1

2

I think your problem is related to the access token scopes. I am working on a similar app but i am using the scopes https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send to obtain access tokens and it seems not to work if I try to use SMTP.Send and IMAP.AccessAsUserAll.

My access token looks like this: {"token_type":"Bearer", "scope":"https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send", "expires_in":3599, "ext_expires_in":3599, "access_token":"eyJ0eXAiOi..."}

In the azure app config, I just have the Microsoft Graph permissions for IMAP and SMTP. enter image description here

Teodor d
  • 56
  • 4
  • Thanks a lot for the answer. Even I think problem relies on access token scopes which I'm using. But unfortunately for some reason I'm not able to add scopes https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send in my application. I had communication with support team , they informed me that these were legacy scope and have been removed. So by any chance are you able to add those scopes now ? Are you able to see them now in Exchange? I'm asking this question just to make sure that I may be having some permission issue while adding those scopes. – Vinayak Mulgund Jul 07 '20 at 05:16
  • I'm not sure what you mean about adding the scopes. The only permissions I have for the registered application are the ones from the screenshot and it works like this. This project helped me a lot https://github.com/eino-makitalo/vesa-mailtest. – Teodor d Jul 07 '20 at 07:58
  • And I have no idea what the difference is between https://outlook.office365.com/IMAP.AccessAsUser.All and IMAP.AccessUserAsAll... I think they are the same thing after all... I tried removing the IMAP.AccessUserAsAll permission from the app registration and if I try to request an access token with https://outlook.office365.com/IMAP.AccessAsUser.All scope, it will not give me the token anymore, so this is the permission corresponding to this scope. – Teodor d Jul 07 '20 at 08:13
  • It would be very helpful if you post the request you are making while getting access token. { "token_type": "Bearer", "scope": "IMAP.AccessAsUser.All SMTP.Send", "expires_in": 3599, "ext_expires_in": 3599, "access_token": "access_token", "refresh_token": "refresh_token", "id_token": "id_token" } but you have "scope":"https://outlook.office365.com/IMAP.AccessAsUser.All" I'm trying to understand what may be wrong here. I will attach(AccessTokenRequest) request that I'm making. Please let me know if I'm doing some wrong here – Vinayak Mulgund Jul 07 '20 at 10:43
  • I have added request I'm making while getting Auth Code and Access token "Requesting Access token Image". Please have a look in it. – Vinayak Mulgund Jul 07 '20 at 10:51
  • If I try to request access token with resource as https://outlook.office365.com/IMAP.AccessAsUser.All , I get error : The resource principal named https://outlook.office365.com/IMAP.AccessAsUser.All was not found in the tenant named 57* . This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. And also I'm curious to know how did you manage to add permission https://outlook.office365.com/IMAP.AccessAsUser.All since in your access token "scope":"https://outlook.office365.com/IMAP.AccessAsUser.All is displayed – Vinayak Mulgund Jul 07 '20 at 12:36
  • I had similar problem - https://stackoverflow.com/questions/61597263/office-365-xoauth2-for-imap-and-smtp-authentication-fails/. In the Azure app registration you need to have IMAP.AccessAsUser.All, SMTP.Send, but the app should request the following scopes - https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send – ledniov Jul 07 '20 at 12:44
  • My post parameters look like this: "client_id=5007f...&" + "scope=https://outlook.office365.com/SMTP.Send" + " https://outlook.office365.com/IMAP.AccessAsUser.All&" + "client_secret=GqR2...&" + "username=******&" + "password=****&" + "grant_type=password"; i think you need to use scope instead of resource – Teodor d Jul 07 '20 at 12:54
  • https://login.microsoftonline.com/{tenant}/oauth2/v2.0/authorize? client_id=6731de76-14a6-49ae-97bc-6eba6914391e &response_type=code &redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F &response_mode=query &scope=openid%20offline_access%20https%3A%2F%2Fgraph.microsoft.com%2Fmail.read &state=12345 This is the example given by Microsoft for the flow you are using. Check this https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow – Teodor d Jul 07 '20 at 12:57
  • Thanks a lot ledniov and Teodor . Seems like I have partially resolved the issue. It is working now. One last question , what would be best way to obtain refresh token , since refresh token are only given for offline_access scopes Note: Only provided if offline_access scope was requested . Because I want my Email client to be connect 24/7 to download the mails. @ledniov , I Saw your comments in stackoverflow.com/questions/61597263/… , You found the work around or still waiting for reply from MS team members – Vinayak Mulgund Jul 07 '20 at 16:22
  • @VinayakMulgund, in my tests I used both refresh tokens. One obtained after code exchange, and the second one for outlook scopes using token refresh to obtain the second refresh token for outlook scopes only. I didn't have much tests, but t first glance it worked, so just wanted to get confirmation from MSFT. – ledniov Jul 08 '20 at 19:37