我们正在尝试使用 OAUTH2 身份验证将 javamail (1.6) 客户端连接到托管在 Office365 上的 Office365 邮箱。
无论我们做什么,我们都会不断收到 A1 NO AUTHENTICATE failed。
我们已通过
注册了我们的申请API权限
我们遵循了
中所述的所有说明包括运行 powershell 命令来使用应用程序 ID 和对象 ID 创建主体,并且我们授予应用程序对我们想要访问的电子邮件箱的完全访问权限。
对于身份验证,我们执行如下 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 和redirectUri,脚本会提示我批准并且成功
但是如果我们使用clientsecret授权失败
更新2
我可以通过 powershell 脚本生成的访问令牌成功使用 javamail。
显然,使用 clientsecret 创建的令牌没有足够的权限来访问 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": ["IMAP.AccessAsApp"]
解决了!
查看访问令牌,我们注意到客户端凭据流主题(子)是我们未设置的 ID。
这里有一个问题:在使用 powershell 在线交换创建服务主体时,对于 serviceid,您必须使用企业应用程序的 objectid。
New-ServicePrincipal -AppId {clientid} -ServiceId {企业应用程序对象id} -组织{tenantid}
创建应用程序注册 Azure AD 时,您还创建了企业应用程序
应用程序对象 ID 与企业应用程序对象 ID 不同。
客户端凭证流使用企业应用程序对象 ID 作为请求授权的用户。
使用 powershell 授予对邮箱的访问权限也是如此
Add-MailboxPermission -Identity {电子邮件} -User -ServiceId {企业应用程序对象 ID} -AccessRights FullAccess
不幸的是认证过程如此繁琐
我的两分钱,如果您仍然面临 javamail 尝试连接到邮箱和阅读电子邮件的身份验证失败,首先确保 azure Active Directory 中的应用程序设置具有以下权限。
IMAP.AccessAsApp
邮件.阅读
Mail.Send(用于发送)
其次,使用原帖中提到的企业应用程序 ID 创建服务主体。 完成后,在此处检查您生成的令牌是否具有您分配的所有角色。
即使您分配了必要的角色并且可以通过 powershell 连接到邮箱,您仍然可能会从 javamail 收到AUTHENTICATE failed,因为您可能错误地使用了此属性(mail.imap.auth.mechanisms),请将 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)
祝你好运!!