java - 如何使用 OAUTH2 从 Java 访问 Outlook.office365.com IMAP?

标签 java oauth-2.0 outlook imap

由于 Microsoft 宣布很快将不再能够使用基本身份验证访问 Outlook IMAP 邮箱,因此我正在尝试找出如何在 Java 中使用 OAUTH2 正确打开 IMAP 邮箱。但我总是收到错误代码“A1 NO AUTHENTICATE failed。”

我正在做的事情如下:

我有一种生成 OAUTH2 访问 token 的方法:

public String getAuthToken(String tanantId,String clientId,String client_secret) throws ClientProtocolException, IOException {
    CloseableHttpClient client = HttpClients.createDefault();
    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));
    loginPost.addHeader(new BasicHeader("cache-control", "no-cache"));
    CloseableHttpResponse loginResponse = client.execute(loginPost);
    InputStream inputStream = loginResponse.getEntity().getContent();
    byte[] response = readAllBytes(inputStream);
    ObjectMapper objectMapper = new ObjectMapper();
    JavaType type = objectMapper.constructType(
            objectMapper.getTypeFactory().constructParametricType(Map.class, String.class, String.class));
    Map<String, String> parsed = new ObjectMapper().readValue(response, type);
    return parsed.get("access_token");
}

生成的 token 似乎有效为 jwt.ms允许我解码 token 。

我尝试使用如下访问 token 通过 XOAUTH2 访问邮箱:

        Properties props = new Properties();

        props.put("mail.store.protocol", "imap");
        props.put("mail.imap.host", "outlook.office365.com");
        props.put("mail.imap.port", "993");
        props.put("mail.imap.ssl.enable", "true");
        props.put("mail.imap.starttls.enable", "true");
        props.put("mail.imap.auth", "true");
        props.put("mail.imap.auth.mechanisms", "XOAUTH2");
        props.put("mail.imap.user", mailAddress);
        props.put("mail.debug", "true");
        props.put("mail.debug.auth", "true");
    
        // open mailbox....
        String token = getAuthToken(tanantId,clientId,client_secret);
        Session session = Session.getInstance(props);
        session.setDebug(true);
        Store store = session.getStore("imap");
        store.connect("outlook.office365.com", mailAddress, token);

但结果始终是 AuthenticationFailedException:

* OK The Microsoft Exchange IMAP4 service is ready. [...............AA==]
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG IMAP: AUTH: PLAIN
DEBUG IMAP: AUTH: XOAUTH2
DEBUG IMAP: protocolConnect login, host=outlook.office365.com, <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="0a7f796f78377272724a73737324696567" rel="noreferrer noopener nofollow">[email protected]</a>, password=<non-null>
A1 AUTHENTICATE XOAUTH2 ....E=
A1 NO AUTHENTICATE failed.
javax.mail.AuthenticationFailedException: AUTHENTICATE failed.

来自this similar question我现在怀疑我的访问 token 实际上访问邮箱的权限太少。

我该如何澄清这一点?例如,当我解码 token 时,我可以看到它不包含 scproles 属性。 这是否表明 token 错误?

最佳答案

代码示例是正确的。问题是所提供的 servicePrincipal 缺少权限。 为了在office365中创建servicePrincipal,需要使用objectId。这些任务只能由管理员使用 PowerShell 脚本执行。这些都与Java无关。 Java API 非常简单。

关于java - 如何使用 OAUTH2 从 Java 访问 Outlook.office365.com IMAP?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74157939/

相关文章:

html - css max-width 属性和外观

java - java调度器还有其他方法比Quartz更容易理解吗?

java - 为什么Spring在找不到默认构造函数时抛出异常

node.js - 我们可以从 Passport js中的授权码获取访问 token 吗

vba - Outlook 自动转发将回复设置为原始发件人而不是转发者

linux - 基于 Linux 的解决方案初学者指南,用于从 MS Outlook 的 .pst 文件中读取邮件内容(包括附件)

java - 干扰者 : setting the sequence on startup

java - Android Studio 上不显示的项目

c# - 如何在没有 OWIN 的情况下在 .net Framework 中实现 OpenId Provider

java - 如何使用 gmail OAuth 验证 IMAP?