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



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

尝试使用我对图形 API 使用的相同访问令牌后,我收到错误: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.

四处阅读,我了解到,由于 EWS 需要对帐户的完全权限,因此您不能只传递访问令牌,还必须使用 x509 证书"做某事"。

在我注册的 Azure 应用中,我已调整清单以包含自签名证书,以便:

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

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

value实际上是关键内容,删除了-----BEGIN CERTIFICATE----------END CERTIFICATE-----,并删除了所有新行(否则在清单中,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图形 API 时收到的相同令牌。

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

  1. 我需要对我的请求做什么,以便我告诉服务器也对 x509 证书进行身份验证,我读到我可能还需要将其转换为 PKCS12 证书?
  2. 我是否可以使用成功用于访问图形 API 的相同访问令牌?
  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来解密密钥并将其保存在文本文件中。 然后 JWT 签名起作用了。您还需要冒充,请参阅此 https://github.com/CumberlandGroup/node-ews/issues/39

它可能有助于节点 EWS。我还没有用节点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, "user@domain.com");
exch.HttpHeaders = { "X-AnchorMailbox": "user@domain.com" };
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);
});

最新更新