用于 IMAP 和 SMTP 身份验证的 Office 365 XOAUTH2 失败 [英] Office 365 XOAUTH2 for IMAP and SMTP Authentication fails

查看:349
本文介绍了用于 IMAP 和 SMTP 身份验证的 Office 365 XOAUTH2 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近

范围,来自代码的请求:

final List范围 = Arrays.asList(离线访问",电子邮件",openid",个人资料",用户.读取",邮件.读写",https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",https%3A%2F%2Foutlook.office365.com%2FSMTP.Send");

我成功收到访问和刷新令牌:

{token_type":承载",范围":电子邮件 IMAP.AccessAsUser.All Mail.ReadWrite openid profile SMTP.Send User.Read",expires_in":3599,ext_expires_in":3599,access_token":编辑",refresh_token":编辑",id_token":已编辑";}

这是用于连接到 IMAP 的代码:

Properties props = new Properties();props.put("mail.imap.ssl.enable", "true");props.put("mail.imaps.sasl.enable", "true");props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");props.put("mail.imap.auth.login.disable", "true");props.put("mail.imap.auth.plain.disable", "true");props.put("mail.debug", "true");props.put("mail.debug.auth", "true");Session session = Session.getInstance(props);session.setDebug(true);String userEmail = "user@domain.onmicrosoft.com";String accessToken = "access_token_received_on_previous_step";final Store store = session.getStore(imaps");store.connect(outlook.office365.com", 993, userEmail, accessToken);

生成以下输出:

调试:JavaMail 1.6.2 版调试:成功加载资源:/META-INF/javamail.default.address.map调试:setDebug:JavaMail 1.6.2 版调试:getProvider() 返回 javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle]调试 IMAPS:mail.imap.fetchsize:16384调试 IMAPS:mail.imap.ignorebodystructuresize:false调试 IMAPS:mail.imap.statuscachetimeout:1000调试 IMAPS:mail.imap.appendbuffersize:-1调试 IMAPS:mail.imap.minidletime:10调试 IMAPS:启用 SASL调试 IMAPS:允许的 SASL 机制:XOAUTH2调试 IMAPS:closeFoldersOnStoreFailure调试 IMAPS:尝试连接到主机outlook.office365.com",端口 993,isSSL true* OK Microsoft Exchange IMAP4 服务已准备就绪.[QQBNADc...]A0能力* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+A0 OK 能力完成.调试 IMAP: 身份验证: 平原调试 IMAP:授权:XOAUTH2调试 IMAPS:protocolConnect 登录,host=outlook.office365.com,user=user@domain.onmicrosoft.com,password=调试 IMAPS:SASL 机制:调试 IMAP:XOAUTH2调试 IMAP:调试 IMAPS:SASL 客户端 XOAUTH2调试 IMAPS:SASL 回调长度:2调试 IMAPS:SASL 回调 0:javax.security.auth.callback.NameCallback@17046283调试 IMAPS:SASL 回调 1:javax.security.auth.callback.PasswordCallback@5bd03f44A1 认证 XOAUTH2 dXNlcj1o...A1 NO AUTHENTICATE 失败.线程main"中的异常javax.mail.AuthenticationFailedException: 认证失败.在 com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:732)在 javax.mail.Service.connect(Service.java:366)

以下代码用于连接到SMTP:

Properties props = new Properties();props.put("mail.smtp.auth", "true");props.put("mail.transport.protocol", "smtp");props.put("mail.smtp.starttls.enable", "true");props.put("mail.smtp.auth.mechanisms", "XOAUTH2");props.put(mail.smtp.auth.login.disable",true");props.put(mail.smtp.auth.plain.disable",true");props.put("mail.debug.auth", "true");Session session = Session.getInstance(props);session.setDebug(true);String userEmail = "user@domain.onmicrosoft.com";String accessToken = "access_token_received_on_previous_step";传输传输 = session.getTransport(smtp");transport.connect(smtp.office365.com", 587, userEmail, accessToken);

提供以下输出:

DEBUG: setDebug: JavaMail version 1.6.2调试:getProvider() 返回 javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]调试 SMTP:useEhlo 真,useAuth 真调试 SMTP:尝试连接到主机smtp.office365.com",端口 587,isSSL false220 AM5PR0701CA0005.outlook.office365.com Microsoft ESMTP MAIL 服务于 2020 年 5 月 4 日星期一 15:52:28 +0000 准备就绪DEBUG SMTP:连接到主机smtp.office365.com",端口:587EHLO ubuntu-B450-AORUS-M250-AM5PR0701CA0005.outlook.office365.com 你好[我的ip在这里]250 尺码 157286400250-流水线250-DSN250 增强状态代码250-STARTTLS250-8BITMIME250-BinaryMIME250 块250 SMTPUTF8调试 SMTP:找到扩展名SIZE",参数157286400";调试 SMTP:找到扩展名PIPELINING",参数"调试 SMTP:找到扩展名DSN",参数"调试 SMTP:找到扩展名ENHANCEDSTATUSCODES",参数"调试 SMTP:找到扩展名STARTTLS",参数"调试 SMTP:找到扩展名8BITMIME",参数"调试 SMTP:找到扩展名BINARYMIME",参数"调试 SMTP:找到扩展名CHUNKING",参数"调试 SMTP:找到扩展名SMTPUTF8",参数"开始TLS220 2.0.0 SMTP 服务器准备就绪EHLO ubuntu-B450-AORUS-M250-AM5PR0701CA0005.outlook.office365.com 你好[我的ip在这里]250 尺码 157286400250-流水线250-DSN250 增强状态代码250-AUTH 登录 XOAUTH2250-8BITMIME250-BinaryMIME250 块250 SMTPUTF8调试 SMTP:找到扩展名SIZE",参数157286400";调试 SMTP:找到扩展名PIPELINING",参数"调试 SMTP:找到扩展名DSN",参数"调试 SMTP:找到扩展名ENHANCEDSTATUSCODES",参数"调试 SMTP:找到扩展名AUTH",参数LOGIN XOAUTH2";调试 SMTP:找到扩展名8BITMIME",参数"调试 SMTP:找到扩展名BINARYMIME",参数"调试 SMTP:找到扩展名CHUNKING",参数"调试 SMTP:找到扩展名SMTPUTF8",参数"调试 SMTP:protocolConnect 登录,host=smtp.office365.com,user=user@domain.onmicrosoft.com,password=调试 SMTP:尝试使用机制进行身份验证:XOAUTH2调试 SMTP:使用机制 XOAUTH2AUTH XOAUTH2 dXNlcj1obW9kaUB...535 5.7.3 认证不成功【AM5PR0701CA0005.eurprd07.prod.outlook.com】线程main"中的异常javax.mail.AuthenticationFailedException: 535 5.7.3 身份验证失败 [AM5PR0701CA0005.eurprd07.prod.outlook.com]在 com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:965)在 com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:876)在 com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:780)在 javax.mail.Service.connect(Service.java:366)

我也尝试过的:

  • 将范围指定为 https://graph.microsoft.com/SMTP.SendSMTP.Send
  • 使用 https://login.microsoftonline.com/common/ url 进行身份验证

结果总是一样的.

是我做错了什么还是微软方面对此的支持存在错误?

更新 1:

从命令行尝试,但结果相同:

$ openssl s_client -crlf -connect Outlook.office365.com:993...省略连接部分* OK Microsoft Exchange IMAP4 服务已准备就绪.[QQBNADYAUAAxADkAMgBDAEEAMAAwADkAMQAuAEUAVQBSAFAAMQA5ADIALgBQAFIATwBEAC4ATwBVAFQATABPAE8ASwAuAEMATwBNAA==]C01 能力* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+C01 OK 能力完成.A01 验证 XOAUTH2 dXNlcj1obW9kaUBjb...A01 NO AUTHENTICATE 失败.* BYE 连接已关闭.13读:错误= 0

更新 2:

尝试使用以下权限在 Azure 门户中创建全新的应用程序:

并在尝试同意范围时收到以下屏幕:

这很奇怪,因为 Azure 门户的权限没有指定需要管理员同意,而且我之前的应用注册在请求 IMAP 和 SMTP 范围时没有显示这样的屏幕.

更新 3:

感谢对这篇文章的评论,我尝试了以下范围:

public static final List范围 = Arrays.asList(离线访问",https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",https%3A%2F%2Foutlook.office365.com%2FSMTP.Send");

这给了我下面的令牌:

{token_type":承载",范围":https://outlook.office365.com/IMAP.AccessAsUser.All https://outlook.office365.com/SMTP.Send",expires_in":3599,ext_expires_in":3599,access_token":eyJ0eXAiOiJKV1....",refresh_token":OAQABAAAAAAAm...."}

IMAP/SMTP 身份验证成功,我能够阅读收件箱 + 发送电子邮件!

但对于我的应用程序,我还需要几个其他范围来使用一些 MS Graph API 端点(读取用户配置文件、消息订阅和消息删除).

所以我尝试了不同的范围:

public static final List范围 = Arrays.asList(离线访问",用户.读取",邮件.读写",https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",https%3A%2F%2Foutlook.office365.com%2FSMTP.Send");

这给了令牌(注意范围值与实际工作的令牌不同,权限没有outlook url):

{token_type":承载",范围":IMAP.AccessAsUser.All Mail.ReadWrite SMTP.Send User.Read profile openid email",expires_in":3599,ext_expires_in":3599,access_token":eyJ0eXAiOiJKV1Q...",refresh_token":OAQABAAAAAAAm..."}

这导致了我之前得到的结果:

A1 NO AUTHENTICATE 失败.

尝试将所有范围作为 URL:

public static final List范围 = Arrays.asList(offline_access"、//或https%3A%2F%2Fgraph.microsoft.com%2Foffline_access"https%3A%2F%2Fgraph.microsoft.com%2FUser.Read"、https%3A%2F%2Fgraph.microsoft.com%2FMail.ReadWrite",https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",https%3A%2F%2Foutlook.office365.com%2FSMTP.Send");

获取token时出现如下错误(同意步骤成功):

{错误":无效请求",error_description":AADSTS28000:为输入参数范围提供的值无效,因为它包含多个资源.范围 offline_access https://graph.microsoft.com/user.read https://graph.microsoft.com/mail.readwrite https://outlook.office365.com/imap.accessasuser.all https://outlook.office365.com/smtp.send 无效.
跟踪 ID:c3282396-6231-4e11-8300-77bc2ca57f00
相关 ID:5f5145bf-7114-4e6c-ab11-30e5605r
08:08:48Z",错误代码":[28000],时间戳":2020-05-06 08:08:48Z",trace_id":c3282396-6231-4e11-8300-77bc2ca57f00",correlation_id":5f5145bf-7114-4e6c-ab11-30e7ff84a056"}

并在尝试所有范围以获取 microsoft graph(从 Azure 门户复制)时

public static final List范围 = Arrays.asList(https%3A%2F%2Fgraph.microsoft.com%2Foffline_access",https%3A%2F%2Fgraph.microsoft.com%2FUser.Read"、https%3A%2F%2Fgraph.microsoft.com%2FMail.ReadWrite",https%3A%2F%2Fgraph.microsoft.com%2FIMAP.AccessAsUser.All"、https%3A%2F%2Fgraph.microsoft.com%2FSMTP.Send");

返回以下令牌(没有刷新令牌,但已请求offline_access)

{token_type":承载",范围":配置文件 openid 电子邮件 https://graph.microsoft.com/IMAP.AccessAsUser.All https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/SMTP.发送 https://graph.microsoft.com/User.Read",expires_in":3599,ext_expires_in":3599,access_token":eyJ0eXAiOiJKV1..."}

没有成功:

A1 NO AUTHENTICATE 失败.

因此,如果您没有为范围指定 Outlook url,则它可能被假定为不允许通过 IMAP 和 SMTP 进行授权的图一.

更新 4:

通过在同意步骤中请求我需要的所有范围,然后获取第一个仅包含 Graph 范围的访问令牌,第二个使用指定 Outlook 范围的刷新令牌端点 - 它起作用了.使用刷新令牌方法获取第二个访问令牌是因为如果您尝试通过身份验证代码获取访问令牌,您将收到以下错误:

{错误":invalid_grant",error_description":AADSTS54005:OAuth2 授权代码已被兑换,请使用新的有效代码或使用现有的刷新令牌重试.
跟踪 ID:09fc80f4-f5fd-4e52-938f-d56b71dd0900 IDCor
:4f35e05c-23c8-4fdc-a5a7-2fcde5a73b44
时间戳:2020-05-08 12:13:30Z",错误代码":[54005],时间戳":2020-05-08 12:13:30Z",trace_id":09fc80f4-f5fd-4e52-938f-d56b71dd0900",correlation_id":4f35e05c-23c8-4fdc-a5a7-2fcde5a73b44"}

所以不,我需要根据我需要管理的资源使用两个单独的令牌.

更新 5:

如果它仍然不起作用 - 检查您的组织是否启用了安全默认值 - 他们禁用了帐户的 POP/IMAP/SMTP 身份验证 - https://techcommunity.microsoft.com/t5/exchange-team-blog/annoucing-oauth-2-0-support-for-imap-and-smtp-auth-protocols-in/bc-p/1544725/highlight/true#M28589

解决方案

IMAP、SMTP 范围针对 Exchange 资源而不是 Graph.而 User.Read、Mail.ReadWrite 用于 Graph 资源.

我们不支持生成用于两种资源的令牌.因此错误为输入参数范围提供的值无效,因为它包含多个资源."

您应该通过两次调用/token 分别生成两个令牌.1. 一种为 Exchange 资源生成的 IMAP、SMTP 范围.2. 另一个具有 Graph 作用域(User.Read、Mail.ReadWrite)的用于 Graph 资源.

Recently the support for OAuth 2.0 for IMAP and SMTP in the Exchange Online has been announced. Following the guide I've set up the application permissions and IMAP and SMTP connection. The application is configured as Accounts in any organizational directory (Any Azure AD directory - Multitenant) and uses authorization code flow.

URLs below are used for authorization:

And the following Delegated Microsoft Graph scopes have been added:

The scopes, requests from code:

final List<String> scopes = Arrays.asList(
    "offline_access",
    "email",
    "openid",
    "profile",
    "User.Read",
    "Mail.ReadWrite",
    "https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
    "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);

I successfully receive the access and refresh tokens:

{
    "token_type": "Bearer",
    "scope": "email IMAP.AccessAsUser.All Mail.ReadWrite openid profile SMTP.Send User.Read",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "edited",
    "refresh_token": "edited",
    "id_token": "edited"
}

Here's the code, used to connect to IMAP:

Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.imap.auth.login.disable", "true");
props.put("mail.imap.auth.plain.disable", "true");
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");

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

String userEmail = "user@domain.onmicrosoft.com";
String accessToken = "access_token_received_on_previous_step";

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

Which generates the following output:

DEBUG: JavaMail version 1.6.2
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: setDebug: JavaMail version 1.6.2
DEBUG: getProvider() returning javax.mail.Provider[STORE,imaps,com.sun.mail.imap.IMAPSSLStore,Oracle]
DEBUG IMAPS: mail.imap.fetchsize: 16384
DEBUG IMAPS: mail.imap.ignorebodystructuresize: false
DEBUG IMAPS: mail.imap.statuscachetimeout: 1000
DEBUG IMAPS: mail.imap.appendbuffersize: -1
DEBUG IMAPS: mail.imap.minidletime: 10
DEBUG IMAPS: enable SASL
DEBUG IMAPS: SASL mechanisms allowed: XOAUTH2
DEBUG IMAPS: closeFoldersOnStoreFailure
DEBUG IMAPS: trying to connect to host "outlook.office365.com", port 993, isSSL true
* OK The Microsoft Exchange IMAP4 service is ready. [QQBNADc...]
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG IMAPS: AUTH: PLAIN
DEBUG IMAPS: AUTH: XOAUTH2
DEBUG IMAPS: protocolConnect login, host=outlook.office365.com, user=user@domain.onmicrosoft.com, password=<non-null>
DEBUG IMAPS: SASL Mechanisms:
DEBUG IMAPS:  XOAUTH2
DEBUG IMAPS: 
DEBUG IMAPS: SASL client XOAUTH2
DEBUG IMAPS: SASL callback length: 2
DEBUG IMAPS: SASL callback 0: javax.security.auth.callback.NameCallback@17046283
DEBUG IMAPS: SASL callback 1: javax.security.auth.callback.PasswordCallback@5bd03f44
A1 AUTHENTICATE XOAUTH2 dXNlcj1o...
A1 NO AUTHENTICATE failed.

Exception in thread "main" javax.mail.AuthenticationFailedException: AUTHENTICATE failed.
    at com.sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.java:732)
    at javax.mail.Service.connect(Service.java:366)

And the following code is used for connecting to SMTP:

Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
props.put("mail.smtp.auth.login.disable","true");
props.put("mail.smtp.auth.plain.disable","true");
props.put("mail.debug.auth", "true");

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

String userEmail = "user@domain.onmicrosoft.com";
String accessToken = "access_token_received_on_previous_step";

Transport transport = session.getTransport("smtp");
transport.connect("smtp.office365.com", 587, userEmail, accessToken);

Which provides the output below:

DEBUG: setDebug: JavaMail version 1.6.2
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to host "smtp.office365.com", port 587, isSSL false
220 AM5PR0701CA0005.outlook.office365.com Microsoft ESMTP MAIL Service ready at Mon, 4 May 2020 15:52:28 +0000
DEBUG SMTP: connected to host "smtp.office365.com", port: 587
EHLO ubuntu-B450-AORUS-M
250-AM5PR0701CA0005.outlook.office365.com Hello [my ip here]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-STARTTLS
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "157286400"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
STARTTLS
220 2.0.0 SMTP server ready
EHLO ubuntu-B450-AORUS-M
250-AM5PR0701CA0005.outlook.office365.com Hello [my ip here]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-AUTH LOGIN XOAUTH2
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "157286400"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN XOAUTH2"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
DEBUG SMTP: protocolConnect login, host=smtp.office365.com, user=user@domain.onmicrosoft.com, password=<non-null>
DEBUG SMTP: Attempt to authenticate using mechanisms: XOAUTH2
DEBUG SMTP: Using mechanism XOAUTH2
AUTH XOAUTH2 dXNlcj1obW9kaUB...
535 5.7.3 Authentication unsuccessful [AM5PR0701CA0005.eurprd07.prod.outlook.com]

Exception in thread "main" javax.mail.AuthenticationFailedException: 535 5.7.3 Authentication unsuccessful [AM5PR0701CA0005.eurprd07.prod.outlook.com]
    at com.sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.java:965)
    at com.sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.java:876)
    at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:780)
    at javax.mail.Service.connect(Service.java:366)

What I've also tried:

  • specifying scopes as https://graph.microsoft.com/SMTP.Send and just SMTP.Send
  • using https://login.microsoftonline.com/common/ url for authentication

Result is always the same.

Is it something I do wrong or there's a bug somewhere in the support for this from the Microsoft side?

Update 1:

Tried from the command line, but same result:

$ openssl s_client -crlf -connect outlook.office365.com:993
... connection part omitted
* OK The Microsoft Exchange IMAP4 service is ready. [QQBNADYAUAAxADkAMgBDAEEAMAAwADkAMQAuAEUAVQBSAFAAMQA5ADIALgBQAFIATwBEAC4ATwBVAFQATABPAE8ASwAuAEMATwBNAA==]
C01 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
C01 OK CAPABILITY completed.
A01 AUTHENTICATE XOAUTH2 dXNlcj1obW9kaUBjb...
A01 NO AUTHENTICATE failed.
* BYE Connection is closed. 13
read:errno=0

Update 2:

Tried to create brand new application in the Azure Portal with the following permissions:

And receiving the following screen, when trying to give consent for scopes:

That is odd, because the permissions from Azure Portal don't specify that the Admin consent is required and my previous app registration doesn't show such screen when IMAP and SMTP scopes are requested.

Update 3:

Thanks to comments to this post I tried the following scopes:

public static final List<String> SCOPES = Arrays.asList(
    "offline_access",
    "https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
    "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);

Which gave me the token below:

{
    "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": "eyJ0eXAiOiJKV1....",
    "refresh_token": "OAQABAAAAAAAm...."
}

IMAP/SMTP auth was successful and I was able to read the inbox + send an email!

But for my application I need also couple of other scopes to use some MS Graph API endpoints (read user profile, messages subscription and messages deletion).

So I tried different scopes:

public static final List<String> SCOPES = Arrays.asList(
        "offline_access",
        "User.Read",
        "Mail.ReadWrite",
        "https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
        "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);

This gave the token (note that scope value differs from the token that actually worked, the permissions don't have outlook url):

{
    "token_type": "Bearer",
    "scope": "IMAP.AccessAsUser.All Mail.ReadWrite SMTP.Send User.Read profile openid email",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "eyJ0eXAiOiJKV1Q...",
    "refresh_token": "OAQABAAAAAAAm..."
}

Which led to the result I got previously:

A1 NO AUTHENTICATE failed.

Trying all the scopes to be as URLs:

public static final List<String> SCOPES = Arrays.asList(
        "offline_access", // or "https%3A%2F%2Fgraph.microsoft.com%2Foffline_access"
        "https%3A%2F%2Fgraph.microsoft.com%2FUser.Read",
        "https%3A%2F%2Fgraph.microsoft.com%2FMail.ReadWrite",
        "https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
        "https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);

Leads to the following error when obtaining the token (the consent step passed successfully):

{
    "error": "invalid_request",
    "error_description": "AADSTS28000: Provided value for the input parameter scope is not valid because it contains more than one resource. Scope offline_access https://graph.microsoft.com/user.read https://graph.microsoft.com/mail.readwrite https://outlook.office365.com/imap.accessasuser.all https://outlook.office365.com/smtp.send is not valid.
Trace ID: c3282396-6231-4e11-8300-77bc2ca57f00
Correlation ID: 5f5145bf-7114-4e6c-ab11-30e7ff84a056
Timestamp: 2020-05-06 08:08:48Z",
    "error_codes": [
        28000
    ],
    "timestamp": "2020-05-06 08:08:48Z",
    "trace_id": "c3282396-6231-4e11-8300-77bc2ca57f00",
    "correlation_id": "5f5145bf-7114-4e6c-ab11-30e7ff84a056"
}

And when trying all the scopes to have microsoft graph (as copied from the Azure Portal)

public static final List<String> SCOPES = Arrays.asList(
    "https%3A%2F%2Fgraph.microsoft.com%2Foffline_access",
    "https%3A%2F%2Fgraph.microsoft.com%2FUser.Read",
    "https%3A%2F%2Fgraph.microsoft.com%2FMail.ReadWrite",
    "https%3A%2F%2Fgraph.microsoft.com%2FIMAP.AccessAsUser.All",
    "https%3A%2F%2Fgraph.microsoft.com%2FSMTP.Send"
);

Return the following token (without a refresh token althout offline_access has been requested)

{
    "token_type": "Bearer",
    "scope": "profile openid email https://graph.microsoft.com/IMAP.AccessAsUser.All https://graph.microsoft.com/Mail.ReadWrite https://graph.microsoft.com/SMTP.Send https://graph.microsoft.com/User.Read",
    "expires_in": 3599,
    "ext_expires_in": 3599,
    "access_token": "eyJ0eXAiOiJKV1..."
}

No success:

A1 NO AUTHENTICATE failed.

So it appears that if you don't specify Outlook url for scope it's assumed probably as Graph one which doesn't allow authorization through IMAP and SMTP.

Update 4:

By requesting all the scopes I need at consent step, then getting first access token with only Graph scopes and the second one using refresh token endpoint specifying Outlook scopes - it worked. Refresh token method for getting second access token is used because if you try to obtains access token by auth code you'll get get the following error:

{
    "error": "invalid_grant",
    "error_description": "AADSTS54005: OAuth2 Authorization code was already redeemed, please retry with a new valid code or use an existing refresh token.
Trace ID: 09fc80f4-f5fd-4e52-938f-d56b71dd0900
Correlation ID: 4f35e05c-23c8-4fdc-a5a7-2fcde5a73b44
Timestamp: 2020-05-08 12:13:30Z",
    "error_codes": [
        54005
    ],
    "timestamp": "2020-05-08 12:13:30Z",
    "trace_id": "09fc80f4-f5fd-4e52-938f-d56b71dd0900",
    "correlation_id": "4f35e05c-23c8-4fdc-a5a7-2fcde5a73b44"
}

So no I'll need to use two separate tokens depending on what resource I'll need to manage.

Update 5:

If it still doesn't work - check if your organization has Security Default enabled - they disable POP/IMAP/SMTP auth for accounts - https://techcommunity.microsoft.com/t5/exchange-team-blog/announcing-oauth-2-0-support-for-imap-and-smtp-auth-protocols-in/bc-p/1544725/highlight/true#M28589

解决方案

IMAP, SMTP scopes are targeted for Exchange resource and not Graph. Whereas User.Read, Mail.ReadWrite are meant for Graph resource.

We do not support generation of tokens that are meant for two resources. Hence the error "Provided value for the input parameter scope is not valid because it contains more than one resource."

You should generate two tokens separately by two calls to /token. 1. One with the IMAP, SMTP scopes generated for the Exchange resource. 2. The other with Graph scopes (User.Read, Mail.ReadWrite) meant for Graph resource.

这篇关于用于 IMAP 和 SMTP 身份验证的 Office 365 XOAUTH2 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆