oauth2.0 无法使用JavaMail验证到office365上的IMAP

mitkmikd  于 2023-02-03  发布在  Java
关注(0)|答案(1)|浏览(390)

我们正在尝试使用OAUTH2身份验证将javamail(1.6)客户端连接到托管在office365上的office365邮箱。
无论我们做什么,我们总是得到A1 NO AUTHENTICATE失败。
我们已将申请注册到
API权限

我们遵循了
https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth
包括运行powershell命令以使用appid和objectid创建主体,并且我们授予应用对我们想要访问的emailbox的完全访问权限。
对于身份验证,我们执行如下HTTPPOST,它将生成一个访问令牌
这是具有共享密钥的客户端凭据流,如此处所述https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
https://login.microsoftonline.com/{our租户ID}/oauth2/v2.0/令牌

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代码中,我们用从上述HTTPPOST获得的访问令牌连接存储

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和redirectUri,提示我批准,并成功
但如果我们使用clientsecret授权失败

    • 更新2**

我可以成功地将JavaMail与PowerShell脚本生成的访问令牌一起使用。
显然,使用clientsecret创建的令牌没有足够的权限访问IMAP或邮箱
我开始怀疑使用客户端密码的令牌请求是否不起作用,因为我们的Azure Active Directory启用了"安全默认值"。
可能强制执行MFA,因此阻止任何非交互式请求

    • 更新3**

https://jwt.ms允许解码访问令牌
仅使用clientid(代码授权流)创建的令牌与使用client_secret(客户端凭据流)创建的令牌有很大不同。
在"code grant interactive"的令牌中,有一个名为"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。
新建-服务主体-应用程序ID {客户端ID}-服务ID {企业应用程序对象ID}-组织{租户ID}
创建应用程序注册Azure AD时,还将创建企业应用程序
应用程序对象ID与企业应用程序对象ID不同。
客户端凭据流使用企业应用程序对象id作为请求授权的用户。
使用powershell授予对邮箱的访问权限也是如此
添加-邮箱权限-身份{电子邮件}-用户**-服务ID {企业应用程序对象ID}**-访问权限完全访问
不幸的是,认证过程是如此麻烦

csga3l58

csga3l581#

我对此的两分钱,如果你仍然面临身份验证失败,从javamail试图连接到邮箱和阅读电子邮件,首先也是最重要的确保应用程序设置在azure活动目录有以下权限。

IMAP.访问为应用程序
邮件。已阅读
邮件.发送(用于发送)

其次,创建服务主体,使用企业应用程序id,如原帖子中所述。一旦完成,如果生成的令牌具有您分配的所有角色,则为check here
即使您分配了必要的角色,并且您可以通过PowerShell连接到邮箱,您仍然可能会从javamail获得AUTHENTICATE failed,因为您可能错误地使用了此属性(mail.imap.auth.机制),请将mail. imaps替换为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)

祝你好运!

相关问题