无法使用JavaMail在office365上进行IMAP身份验证

11
我们正在尝试使用OAUTH2身份验证将javamail(1.6)客户端连接到托管在office365上的office365邮箱。
无论我们做什么,我们都会收到A1 NO AUTHENTICATE失败的消息。
我们已经注册了我们的应用程序,并且在API权限下进行了设置,如下图所示: 1 我们按照以下链接中说明的所有说明进行操作,包括使用应用程序ID和对象ID创建主体的powershell命令,并授予应用程序访问所需电子邮箱的完全访问权限。 https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth 对于身份验证,我们执行以下HTTP POST,生成访问令牌:
这是一个共享密钥的客户端凭据流程,如下面的链接所述: https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow 请使用以下网址进行身份验证: https://login.microsoftonline.com/{我们的租户ID}/oauth2/v2.0/token
client_id=...
client_secret=...
grant_type=client_credentials
scope=https://outlook.office365.com/.default

我们的Javamail配置

mail.store.protocol="imap"
mail.imap.host="outlook.office365.com"
mail.imap.port="993"
mail.imap.ssl.enable="true"
mail.imap.starttls.enable="true"
mail.imap.auth="true"
mail.imap.auth.mechanisms="XOAUTH2"
mail.imap.user="<email box>"

然后在我们的Java代码中,我们使用上述HTTP POST获得的访问令牌连接存储。

store.connect(host, user, oauth2_access_token);

我们还尝试了这个PowerShell脚本,但返回了相同的错误。 https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1 我不认为这个问题是特定于JavaMail的。
确定访问令牌是否具有正确的权限或者是否有其他阻止身份验证的因素是非常困难的。
我们还能尝试什么? 更新1 如果我们使用PowerShell脚本 https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1 只传递客户端ID和重定向URI,脚本会提示我进行批准并成功通过身份验证。
但是,如果我们使用客户端密码,授权将失败。 更新2 我可以成功地使用javamail和由powershell脚本生成的访问令牌。
显然,使用客户端密码创建的令牌没有足够的权限来访问IMAP或邮箱。
我开始怀疑使用客户端密码的令牌请求是否不起作用,因为我们的Azure Active Directory启用了“安全默认值”。
可能强制执行MFA,因此阻止了任何非交互式请求。 更新3

https://jwt.ms 可以解码访问令牌。

仅使用 clientid(代码授权流)创建的令牌与使用 client_secret(客户端凭据流)创建的令牌非常不同。

在“代码授权交互”中创建的令牌中有一个名为“scp”的属性,它列出了作用域集,而不管我在客户端应用程序 API 权限中拥有哪些权限?

"scp": "IMAP.AccessAsUser.All Mail.Read Mail.Read.All Mail.Read.Shared Mail.ReadBasic User.Read"

客户端凭据流程的第二个令牌具有“roles”属性,但不具有范围。
"roles": ["IMAP.AccessAsApp"]

解决!

查看访问令牌时,我们注意到客户端凭据流主题(sub)是一个我们没有设置的id。

这里有个问题:在Exchange Online中使用PowerShell创建服务主体时,对于ServiceID,您必须使用企业应用程序的ObjectID。

New-ServicePrincipal -AppId {clientid} -ServiceId {enterprise application objectid} -Organization {tenantid}

在Azure AD中创建应用程序注册时,还会创建企业应用程序。

应用程序对象ID与企业应用程序对象ID不同。

客户端凭据流使用企业应用程序对象ID作为请求授权的用户。

使用PowerShell授予对邮箱的访问权限也是如此。

Add-MailboxPermission -Identity {email} -User -ServiceId {enterprise application objectid} -AccessRights FullAccess

遗憾的是,认证过程如此繁琐。


你能解释一下在哪里使用objectID吗? 我正在使用Java中的以下代码:`HttpPost loginPost = new HttpPost("https://login.microsoftonline.com/" + tanantId + "/oauth2/v2.0/token");String scopes = "https://outlook.office365.com/.default";String encodedBody = "client_id=" + clientId + "&scope=" + scopes + "&client_secret=" + client_secret
  • "&grant_type=client_credentials";
loginPost.setEntity(new StringEntity(encodedBody, ContentType.APPLICATION_FORM_URLENCODED));`在这里应该在哪里使用objectID?
- Ralph
Ralph,objectId 用于在office365中创建servicePrincipal。这些任务只能由您的office365帐户的管理员执行。有PowerShell脚本需要执行来创建servicePricipal,这些用户是在Azure Active Directory中定义的应用程序的模拟用户。 - Ivan Pedruzzi
@IvanPedruzzi,-User -ServiceId 是正确的语法吗? - Apostolos
Add-MailboxPermission -Identity {email} -ServiceId {企业应用程序对象ID} -AccessRights FullAccess - Ivan Pedruzzi
1个回答

0

关于这个问题,我想提供我的建议。如果您仍然面临javamail身份验证失败的问题,尝试连接邮箱并读取电子邮件,首先确保Azure Active Directory中应用程序设置具有以下权限。

IMAP.AccessAsApp

Mail.Read

Mail.Send (用于发送)

其次,使用原始帖子中提到的企业应用程序 ID创建服务主体。 完成后,在此处检查生成的令牌是否具有您分配的所有角色。

即使您已分配必要的角色并且可以通过 PowerShell 连接到邮箱,但由于可能错误地使用了此属性(mail.imap.auth.mechanisms),您仍可能从 javamail 中获得AUTHENTICATE failed。请将 mail.imap 替换为 mail.imaps,问题就会得到解决。

"mail.imaps.auth.mechanisms"="XOAUTH2"
"mail.imap.host"="outlookoffice365.com"
"mail.smtp.port"=993
"mail.store.protocol"="imaps"

session.getStore("imaps")
store.connect(host,port,user,token)

祝你好运!!


我们实际上遇到了相反的问题,无论我们做什么,都会出现“A1 NO AUTHENTICATE”错误,但将“imaps”更改为“imap”解决了这个问题。 - runholen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接