node.js - 使用 Nodejs over SOAP 和 x509 证书对 Microsoft EWS 进行身份验证

标签 node.js azure soap exchangewebservices x509certificate

我使用 Microsoft Graph API 访问 Azure Active Directory 中的用户等取得了巨大成功,但是仍然需要 EWS 和 SOAP 的两件事是检索用户照片并向用户邮件帐户添加邮件规则。 我使用服务帐户来处理所有事情,并冒充帐户管理员来提出请求。

尝试使用与 Graph API 相同的访问 token 后,我收到错误: 访问 token 是使用身份验证方法获取的,该身份验证方法太弱,无法允许此应用程序访问。提供的身份验证强度为 1,所需的身份验证强度为 2

通过阅读,我了解到,由于 EWS 需要对帐户的完全权限,因此您不能只传递访问 token ,还必须使用 x509 证书“执行某些操作”。

在我注册的应用程序中,在 Azure 中,我调整了 list 以包含自签名证书,这样我就可以:

 "keyCredentials": [{
  "customKeyIdentifier": "lhbl...../w0bjA6l1mQ8=",
  "keyId": "774D2C35-2D58-.....-AC34B15472BA",
  "type": "AsymmetricX509Cert",
  "usage": "Verify",
  "value": "MIIFtTCCA52gAwIB.....mmgufQ2rW5GSjEEXOlO1c7qw=="
}],

我的理解是 customKeyIdentifier 是 key 的 Base64,来自命令:echo $(openssl x509 -in cert.pem -fingerprint -noout) | sed 's/SHA1 指纹=//g' | sed 's/://g' | xxd -r -ps | xxd -r -ps | Base64

实际上是关键内容,包含-----BEGIN CERTIFICATE----------END CERTIFICATE ----- 已删除,所有新行也已删除(否则在 list 中,json 无效)。

keyId 是我刚刚使用 uuidgen 命令在终端上生成的 GUID,我不认为它与任何方式的证书。

然后我不确定的是,我必须在代码中更改什么,即尝试针对 EWS 进行身份验证。

我从 node-ews 开始库,我的配置如下:

var ewsConfig = {
username: userEmail,
token: self.accessToken,
host: 'https://outlook.office365.com/EWS/Exchange.asmx',
auth: 'bearer'
};
var ews = new EWS(ewsConfig);
var ewsFunction = 'UpdateInboxRules';
ews.run(ewsFunction, ewsArgs)
  .then(result => {
    cb(null, result)
  })
  .catch(err => {
    cb(err);
  });
};

self.accessToken 与我访问 Microsoft Graph API 时收到的 token 相同。

所以,总而言之,我的问题是:

  1. 我需要对我的请求执行什么操作,以便告诉服务器也对 x509 证书进行身份验证,我了解到我可能还需要将其转换为 PKCS12 证书?
  2. 我可以使用与我成功访问图形 API 相同的 accessToken 吗?
  3. 是否有 Nodejs 执行此操作的代码片段?
  4. keyId 可以是我想要提供的任何标识符吗?

我收到的回复包含:

{ 'content-length': '0',
        server: 'Microsoft-IIS/8.5',
        'request-id': '9b0d7a1b-85e6-40f6-9af0-7f65fc6669dc',
        'x-calculatedfetarget': 'MM1P123CU001.internal.outlook.com',
        'x-backendhttpstatus': '401, 401',
        'set-cookie': [Object],
        'x-feproxyinfo': 'MM1P123CA0026.GBRP123.PROD.OUTLOOK.COM',
        'x-calculatedbetarget': 'MM1P123MB1337.GBRP123.PROD.OUTLOOK.COM',
        'x-ms-diagnostics': '2000001;reason="The access token is acquired using an authentication method that is too weak to allow access for this application. Presented auth strength was 1, required is 2.";error_category="invalid_token"',
        'x-diaginfo': 'MM1P123MB1337',
        'x-beserver': 'MM1P123MB1337',
        'x-feserver': 'MM1P123CA0026, VI1PR0701CA0059',
        'x-powered-by': 'ASP.NET',
        'www-authenticate': 'Bearer client_id="00000002-0000-0ff1-ce00-000000000000", trusted_issuers="00000001-0000-0000-c000-000000000000@*", token_types="app_asserted_user_v1 service_asserted_app_v1", authorization_uri="https://login.windows.net/common/oauth2/authorize", error="invalid_token",Basic Realm="",Basic Realm="",Basic Realm=""',
        date: 'Tue, 02 May 2017 18:08:54 GMT',
        connection: 'close' } }

谢谢,非常感谢

最佳答案

我按照这篇文章生成了access_token https://blogs.msdn.microsoft.com/arsen/2015/09/18/certificate-based-auth-with-azure-service-principals-from-linux-command-line/ ,确实存在 jwt 签名的一些问题,我必须使用 openssl rsa -check -in key.pem 来解密 key 并将其保存在文本文件中。然后 jwt 签名就起作用了。你还需要冒充,看这个https://github.com/CumberlandGroup/node-ews/issues/39

它可能对 Node-ews 有帮助。我还没有使用 node-ews 测试过这个场景。如果您有兴趣通过 ews 托管 api 等编码寻找更强大的方法,我已经移植了 ews-managed-api 的 c# 版本至 ews-javascript-api ,这里是使用 ews-javascript-api 实现相同功能的示例代码,经过测试并确认了工作代码。

var ews = require("ews-javascript-api");
ews.EwsLogging.DebugLogEnabled = false;
var exch = new ews.ExchangeService(ews.ExchangeVersion.Exchange2013);
exch.Credentials = new ews.OAuthCredentials("oauth access_token");
exch.Url = new ews.Uri("https://outlook.office365.com/Ews/Exchange.asmx");
exch.ImpersonatedUserId = new 
ews.ImpersonatedUserId(ews.ConnectingIdType.SmtpAddress, "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="186d6b7d6a587c7775797176367b7775" rel="noreferrer noopener nofollow">[email protected]</a>");
exch.HttpHeaders = { "X-AnchorMailbox": "<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cdb8bea8bf8da9a2a0aca4a3e3aea2a0" rel="noreferrer noopener nofollow">[email protected]</a>" };
var rule = new ews.Rule();
rule.DisplayName = "MoveInterestingToJunk";
rule.Priority = 1;
rule.IsEnabled = true;
rule.Conditions.ContainsSubjectStrings.Add("Interesting");
rule.Actions.MoveToFolder = new ews.FolderId(ews.WellKnownFolderName.JunkEmail);
var ruleop = new ews.CreateRuleOperation(rule);
exch.UpdateInboxRules([ruleop], true)
    .then(function (response) {
    console.log("success - update-inboxrules");
    ews.EwsLogging.Log(response, true, true);
}, function (err) {
    debugger;
    console.log("error in update-inboxrules");
    ews.EwsLogging.Log(err, true, true);
});

关于node.js - 使用 Nodejs over SOAP 和 x509 证书对 Microsoft EWS 进行身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43744302/

相关文章:

php - 如何使用 php Soap 库向 SoapHeader 节点添加属性

javascript - 如何设置 webpack 以支持 Node 中的 ES6 模块

javascript - Jade 中的过滤器嵌套失败

c# - Azure 存储队列 - 消息 ID

postgresql - Azure PostgreSql,扩展 postgis

python - 如何添加带有泡沫的新对象?

javascript - webview.executeJavascript 不是函数

node.js - 使用 TLS 协议(protocol)运行 NodeJS

database - 如何在 Azure postgresql 和 Prem oracle DB 之间进行双向数据同步

web-services - 尝试使用ironpython和soap调用Web服务