无论我们做什么,我们都会收到A1 NO AUTHENTICATE失败的消息。
我们已经注册了我们的应用程序,并且在API权限下进行了设置,如下图所示: 我们按照以下链接中说明的所有说明进行操作,包括使用应用程序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
遗憾的是,认证过程如此繁琐。
-User -ServiceId
是正确的语法吗? - Apostolos