JavaMail connecting to Office 365 XOAUTH2 for IMAP Authentication fails
Asked Answered
S

1

7

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 = "[email protected]";
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, [email protected], 
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.

Scalar answered 3/7, 2020 at 12:14 Comment(4)
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?Edging
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.Scalar
Encoding is performed in JavaMail library " String resp = "user=" + u + "\001auth=Bearer " + p + "\001\001"; byte[] ba = BASE64EncoderStream.encode( resp.getBytes(StandardCharsets.UTF_8)); "Scalar
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. :(Edging
D
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

Danieldaniela answered 6/7, 2020 at 20:23 Comment(11)
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 outlook.office365.com/IMAP.AccessAsUser.All 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.Scalar
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 github.com/eino-makitalo/vesa-mailtest.Danieldaniela
And I have no idea what the difference is between 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 outlook.office365.com/IMAP.AccessAsUser.All scope, it will not give me the token anymore, so this is the permission corresponding to this scope.Danieldaniela
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":"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 hereScalar
I have added request I'm making while getting Auth Code and Access token "Requesting Access token Image". Please have a look in it.Scalar
If I try to request access token with resource as outlook.office365.com/IMAP.AccessAsUser.All , I get error : The resource principal named 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 outlook.office365.com/IMAP.AccessAsUser.All since in your access token "scope":"outlook.office365.com/IMAP.AccessAsUser.All is displayedScalar
I had similar problem - #61597763. In the Azure app registration you need to have IMAP.AccessAsUser.All, SMTP.Send, but the app should request the following scopes - outlook.office365.com/IMAP.AccessAsUser.All outlook.office365.com/SMTP.SendOlivarez
My post parameters look like this: "client_id=5007f...&" + "scope=outlook.office365.com/SMTP.Send" + " outlook.office365.com/IMAP.AccessAsUser.All&" + "client_secret=GqR2...&" + "username=******&" + "password=****&" + "grant_type=password"; i think you need to use scope instead of resourceDanieldaniela
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 learn.microsoft.com/en-us/azure/active-directory/develop/…Danieldaniela
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. @Olivarez , I Saw your comments in stackoverflow.com/questions/61597263/… , You found the work around or still waiting for reply from MS team membersScalar
@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.Olivarez

© 2022 - 2024 — McMap. All rights reserved.