【问题标题】:Moving Basic Authentication project to Oauth将基本身份验证项目移至 Oauth
【发布时间】:2022-12-22 22:31:56
【问题描述】:

由于 Microsoft 禁用了基本身份验证,我需要更改此项目以使用 OAuth,但我无法使其正常工作。任何帮助将不胜感激。

旧代码:

    // expose our config directly to our application using module.exports
module.exports = {
  // this user MUST have full access to all the room accounts
  'exchange' : {
    'username'  : process.env.USERNAME || 'SVCACCT_EMAIL@DOMAIN.COM',
    'password'  : process.env.PASSWORD || 'PASSWORD',
    'uri'       : 'https://outlook.office365.com/EWS/Exchange.asmx'
  },
  // Ex: CONTOSO.COM, Contoso.com, Contoso.co.uk, etc.
  'domain' : process.env.DOMAIN || 'DOMAIN.COM'
};


    module.exports = function (callback) {

  // modules -------------------------------------------------------------------
  var ews = require("ews-javascript-api");
  var auth = require("../../config/auth.js");

  // ews -----------------------------------------------------------------------

  var exch = new ews.ExchangeService(ews.ExchangeVersion.Exchange2016);
  exch.Credentials = new ews.ExchangeCredentials(auth.exchange.username, auth.exchange.password);
  exch.Url = new ews.Uri(auth.exchange.uri);

  // get roomlists from EWS and return sorted array of room list names
  exch.GetRoomLists().then((lists) => {
    var roomLists = [];

    lists.items.forEach(function (item, i, array) {
      roomLists.push(item.Name);
    });
    callback(null, roomLists.sort());
  }, (err) => {
    callback(err, null);
  });

};

【问题讨论】:

    标签: javascript oauth ews-javascript-api


    【解决方案1】:

    我最近进入了确切的情况,并在花了无数小时后终于让它工作了。希望这篇文章能帮助像我一样迷失的灵魂。

    所以发生了什么事?到 2022 年底,MS Exchange Online 的基本身份验证将被禁用。所有相关应用程序的身份验证都需要更新。

    参考:https://techcommunity.microsoft.com/t5/exchange-team-blog/basic-authentication-deprecation-in-exchange-online-september/ba-p/3609437

    怎么做?我的用例很简单。邮件守护程序应用程序 1) 登录和 2) 下载一些电子邮件附件。后台发生的事情以及您需要做什么都写在下面的文章中。

    参考:https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth

    总之,您需要执行以下步骤:

    1. 向 Azure Active Directory 注册您的应用程序
    2. 获取访问令牌
    3. 为您的应用程序添加所需的权限。如果您的旧项目使用普通密码,您可以参考使用客户端凭据授予流程对 IMAP 和 POP 连接进行身份验证上述文章中的部分。下面是我的简单应用所需的权限列表。我添加了有关电子邮件发送以供将来使用的权限:
      • 微软图表:

        • IMAP.AccessAsUser.All
        • 离线访问
        • openid
        • POP.AccessAsUser.All
        • 简介
        • SMTP.发送
      • Office 365 在线交流:

        • full_access_as_app
        • IMAP.AccessAsApp
        • 邮件.阅读
        • 邮件读写
        • 邮件.发送
      1. 让租户管理员同意你的应用程序(由你的 Azure 管理员完成)。

      2. 在 Exchange 中注册服务主体(由 Azure 管理员完成)。

      本博客将向您介绍上述过程: https://blog.hametbenoit.info/2022/07/01/exchange-online-use-oauth-to-authenticate-when-using-imap-pop-or-smtp-protocol/#.Y6RdVXZBxm7

      认证失败?您可能能够从 Exchange 服务器检索令牌,但在尝试连接到 Exchange 服务器时收到错误消息:“A1 NO AUTHENTICATE failed”。如果您一一执行上述步骤,则很可能是与权限相关的问题,请参阅步骤 3 中的列表。不幸的是,这是我测试时间最长的地方,Exchange 服务器没有提供比“您”更多的信息被搞砸了”,这是一个遗憾。

      最后但是同样重要的...这是我的示例 Java 代码。这个简单的应用程序使用 IMAP 向 Exchange 服务器进行身份验证。需要 Apache HttpCore 和 Jackson 库。

      1 - 访问令牌生成类:

      import org.apache.http.HttpEntity;
      import org.apache.http.HttpResponse;
      import org.apache.http.NameValuePair;
      import org.apache.http.client.ClientProtocolException;
      import org.apache.http.client.HttpClient;
      import org.apache.http.client.entity.UrlEncodedFormEntity;
      import org.apache.http.client.methods.HttpPost;
      import org.apache.http.impl.client.HttpClients;
      import org.apache.http.message.BasicNameValuePair;
      import org.apache.http.util.EntityUtils;
      
      import com.fasterxml.jackson.databind.ObjectMapper;
      import com.fasterxml.jackson.databind.node.ObjectNode;
      
      import java.io.IOException;
      import java.io.UnsupportedEncodingException;
      import java.util.ArrayList;
      import java.util.List;
      
      
      public class OAuthDL {
      
          public String getAuthToken() {
              
              String token = "";
              HttpClient httpClient = HttpClients.createDefault();
              
              String tenant_id = "from Azure portal";
              String client_id = "from Azure portal";
              String client_pw = "created after app was registered";
              String scope = "https://outlook.office365.com/.default";
              
              HttpPost httpPost = new HttpPost("https://login.microsoftonline.com/" + tenant_id + "/oauth2/v2.0/token");
              List<NameValuePair> params = new ArrayList<NameValuePair>();
              params.add(new BasicNameValuePair("grant_type", "client_credentials"));
              params.add(new BasicNameValuePair("client_id", client_id));
              params.add(new BasicNameValuePair("client_secret", client_pw));
              params.add(new BasicNameValuePair("scope", scope));;
              
              try {
                  httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
              } catch (UnsupportedEncodingException e) {
                  e.printStackTrace();
              }
      
              try {
                  HttpResponse response = httpClient.execute(httpPost);
                  HttpEntity respEntity = response.getEntity();
      
                  if (respEntity != null) {
                      String content =  EntityUtils.toString(respEntity);
                      
                      ObjectNode node = new ObjectMapper().readValue(content, ObjectNode.class);
                      if (node.has("access_token")) {
                          token = node.get("access_token").asText();
                      }
                  }
              } catch (ClientProtocolException e) {
                  e.printStackTrace();
              } catch (IOException e) {
                  e.printStackTrace();
              }
              return(token);
          }
      
          public static void main(String[] args) {
              OAuthDL oa = new OAuthDL();
              String token = oa.getAuthToken();
              System.out.println("Token: " + token);
          }
      
      }
      
      1. 配置协议并使用 Exchange 服务器进行身份验证的类。 JavaMail 是必需的:

        导入 java.util.Properties; 导入 javax.mail.Folder; 导入 javax.mail.Session; 导入 javax.mail.Store;

        公共类 ImapMailBoxReader {

         private String host;
         private String username;
         private String password;
        
         public ImapMailBoxReader(String host, String username, String password) {
             this.host = host;
             this.username = username;
             this.password = password;
         }
        
         public void testConnection(String folder) {
             try {
        
                 String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory";
                 Properties props= new Properties();
        
                 props.put("mail.imaps.ssl.enable", "true");
                 props.put("mail.imaps.sasl.enable", "true");
                 props.put("mail.imaps.port", "993");
        
                 props.put("mail.imaps.auth.mechanisms", "XOAUTH2");
                 props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
        
                 props.put("mail.imaps.auth.login.disable", "true");
                 props.put("mail.imaps.auth.plain.disable", "true");
        
                 props.setProperty("mail.imaps.socketFactory.class", SSL_FACTORY);
                 props.setProperty("mail.imaps.socketFactory.fallback", "false");
                 props.setProperty("mail.imaps.socketFactory.port", "993");
                 props.setProperty("mail.imaps.starttls.enable", "true");
        
                 props.put("mail.debug", "true");
                 props.put("mail.debug.auth", "true");
        
                 Session session = Session.getDefaultInstance(props, null);
                 session.setDebug(true);
                 Store store = session.getStore("imaps");
                 store.connect(host, username, password);
        
                 Folder inbox = store.getFolder(folder);
                 inbox.open(Folder.READ_ONLY);
        
                 inbox.close(false);
                 store.close();
        
             } catch (Exception e) {
                 e.printStackTrace();
             }
         }
        
         public static void main(String[] args) {
             String host = "outlook.office365.com";
             String username = "your email address";
             OAuthDL oa = new OAuthDL();
             String password = oa.getAuthToken();
        
             ImapMailBoxReader reader = new ImapMailBoxReader(host, username, password);
             reader.testConnection("inbox");
         }
        

        }

      希望这可以帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-11-21
      • 2020-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-02
      • 2021-05-09
      • 2019-10-07
      相关资源
      最近更新 更多