Authenticating Microsoft EWS using Nodejs over SOAP with x509 certificate

隐身守侯 提交于 2019-12-25 10:19:13

问题


I have had great success with the Microsoft Graph API to access users etc etc within Azure Active Directory, however two things that still require EWS and SOAP are retrieving user photos and adding a mail rule to a users mail account. I'm using Service accounts for everything, and impersonating an account admin to make requests.

After attempting to use the same access token that I am using against the Graph API, I receive the error: 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.

Reading around, I understand that because EWS requires full privileges against the accounts, you can't just pass the access token, but you also have to "do something" with an x509 certificate.

In my registered app, within Azure, I have adjusted the manifest so to include a self signed certificate so that I have:

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

My understanding is the customKeyIdentifier is the Base64 of the key, from the command: echo $(openssl x509 -in cert.pem -fingerprint -noout) | sed 's/SHA1 Fingerprint=//g' | sed 's/://g' | xxd -r -ps | base64

the value is literally the key content, with the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- removed, and all new lines removed too (otherwise in the manifest, the json isn't valid).

The keyId is a GUID I just generated on the terminal with the uuidgen command, I don't think its related directly to the certificate in any way.

What I'm not sure then, is what I have to change within my code, that is going to try to auth against EWS.

I have started out with the node-ews library, my configuration looks like:

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 is the same token that I receive when accessing the Microsoft Graph API.

So, in conclusion, my questions are:

  1. What do I need to do to my request so that I am telling the server to also auth the x509 certificate, I read that I may need to convert it to a PKCS12 certicificate also?
  2. Can I use the same accessToken that I am successfully using to access the graph api?
  3. Is there a code snippet anywhere for Nodejs doing this?
  4. Is the keyId ok to be any identifier I want to give it?

The response I get back contains:

{ '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' } }

Thanks, much appreciated


回答1:


I followed this article to generate access_token https://blogs.msdn.microsoft.com/arsen/2015/09/18/certificate-based-auth-with-azure-service-principals-from-linux-command-line/, did have some issues with jwt signing, I had to use openssl rsa -check -in key.pem to decrypt the key and save it in a text file. then jwt signing worked. You also need to be impersonating, see this https://github.com/CumberlandGroup/node-ews/issues/39

it may help with node-ews. I have not tested this scenario with node-ews. If you are interested in looking at more robust approach with ews managed api like coding, I have ported c# version of ews-managed-api to ews-javascript-api , here is the sample code to achieve same with ews-javascript-api, tested and confirmed working code.

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);
});


来源:https://stackoverflow.com/questions/43744302/authenticating-microsoft-ews-using-nodejs-over-soap-with-x509-certificate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!