Skip to content

Instantly share code, notes, and snippets.

@rogueai
Forked from lstak/main.js
Created February 27, 2019 08:09
Show Gist options
  • Select an option

  • Save rogueai/b9581fbdee3bcdb424a28280648a1217 to your computer and use it in GitHub Desktop.

Select an option

Save rogueai/b9581fbdee3bcdb424a28280648a1217 to your computer and use it in GitHub Desktop.
Example using SharePoint CSOM on Node
/* Example using CSOM code on Node */
XMLHttpRequest = require('./xmlhttprequest').XMLHttpRequest;
var window = global;
var navigator = {
userAgent: "Node"
};
var formdigest = {
value: 'DUMMY VALUE',
tagName: 'INPUT',
type: 'hidden'
};
var document = {
documentElement: {},
URL: 'http://yourdomain.sharepoint.com/',
getElementsByName: function (name) {
//console.log('getElementByName: ', name);
if (name == '__REQUESTDIGEST') {
return [formdigest]
}
},
getElementsByTagName: function (name) {
//console.log('getElementByTagName: ', name);
return []
}
};
/***** Insert init.DEBUG.js here ***************/
/***** Insert microsoftajax.DEBUG.js here ***************/
/***** Insert sp.core.DEBUG.js here ***************/
/***** Insert sp.runtime.DEBUG.js here ***************/
/***** Insert sp.DEBUG.js here ***************/
// fix function reference
window.escapeUrlForCallback = escapeUrlForCallback;
/* SharePoint claims based authentication code (see https://github.com/lstak/node-sharepoint) */
var fs = require('fs'),
qs = require('querystring'),
xml2js = require('xml2js'),
http = require('http'),
https = require('https'),
urlparse = require('url').parse,
samlRequestTemplate = fs.readFileSync(__dirname + '/SAML.xml', 'utf8');
var buildSamlRequest = function (params) {
var key,
saml = samlRequestTemplate;
for (key in params) {
saml = saml.replace('[' + key + ']', params[key])
}
return saml;
}
var parseXml = function (xml, callback) {
var parser = new xml2js.Parser({
emptyTag: '' // use empty string as value when tag empty
});
parser.on('end', function (js) {
callback && callback(js)
});
parser.parseString(xml);
};
var parseCookie = function (txt) {
var properties = txt.split('; '),
cookie = {};
properties.forEach(function (property, index) {
var idx = property.indexOf('='),
name = (idx > 0 ? property.substring(0, idx) : property),
value = (idx > 0 ? property.substring(idx + 1) : undefined);
if (index == 0) {
cookie.name = name,
cookie.value = value
} else {
cookie[name] = value
}
})
return cookie;
};
var parseCookies = function (txts) {
var cookies = []
if (txts) {
txts.forEach(function (txt) {
var cookie = parseCookie(txt);
cookies.push(cookie)
})
};
return cookies;
}
var getCookie = function (cookies, name) {
var cookie,
i = 0,
len = cookies.length;
for (; i < len; i++) {
cookie = cookies[i]
if (cookie.name == name) {
return cookie
}
}
return undefined;
}
function requestToken(params, callback) {
var samlRequest = buildSamlRequest({
username: params.username,
password: params.password,
endpoint: params.endpoint
});
var options = {
method: 'POST',
host: params.sts.host,
path: params.sts.path,
headers: {
'Content-Length': samlRequest.length
}
};
var req = https.request(options, function (res) {
var xml = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
xml += chunk;
})
res.on('end', function () {
parseXml(xml, function (js) {
// extract token
var token = js['S:Body']['wst:RequestSecurityTokenResponse']['wst:RequestedSecurityToken']['wsse:BinarySecurityToken']['#'];
// Now we have the token, we need to submit it to SPO
submitToken({
token: token,
endpoint: params.endpoint
}, callback)
})
})
});
req.end(samlRequest);
}
function submitToken(params, callback) {
var token = params.token,
url = urlparse(params.endpoint);
var options = {
method: 'POST',
host: url.hostname,
path: url.path
}
var req = http.request(options, function (res) {
var xml = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
xml += chunk;
})
res.on('end', function () {
var cookies = parseCookies(res.headers['set-cookie'])
callback(null, {
FedAuth: getCookie(cookies, 'FedAuth').value,
rtFa: getCookie(cookies, 'rtFa').value
})
})
})
req.end(token);
}
function signin(username, password, callback) {
var self = this;
var options = {
username: username,
password: password,
sts: self.sts,
endpoint: self.url.protocol + '//' + self.url.hostname + self.login
}
requestToken(options, function (err, data) {
self.FedAuth = data.FedAuth;
self.rtFa = data.rtFa;
requestDigest(data, callback);
})
}
// get Digest vale using sites.asmx web service
function requestDigest(params, callback) {
var payload =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
"<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
" <soap:Body>" +
" <GetUpdatedFormDigest xmlns=\"http://schemas.microsoft.com/sharepoint/soap/\" />" +
" </soap:Body>" +
"</soap:Envelope>";
var options = {
method: 'POST',
host: 'yourdomain.sharepoint.com',
path: '/_vti_bin/sites.asmx',
headers: {
'Content-type': 'text/xml',
'Cookie': 'FedAuth=' + params.FedAuth + '; rtFa=' + params.rtFa,
'Content-length': payload.length
}
}
var req = http.request(options, function (res) {
var responseText = '';
res.setEncoding('utf8');
res.on('data', function (chunk) {
responseText += chunk;
})
res.on('end', function () {
//console.log('XML: ', responseText);
if ((responseText == null) || (responseText.length <= 0)) {
return;
}
var startTag = '<GetUpdatedFormDigestResult>';
var endTag = '</GetUpdatedFormDigestResult>';
var startTagIndex = responseText.indexOf(startTag);
var endTagIndex = responseText.indexOf(endTag, startTagIndex + startTag.length);
var newFormDigest = null;
if ((startTagIndex >= 0) && (endTagIndex > startTagIndex)) {
var newFormDigest = responseText.substring(startTagIndex + startTag.length, endTagIndex);
}
if ((newFormDigest == null) || (newFormDigest.length <= 0)) {
return;
}
formdigest.value = newFormDigest;
callback();
})
})
req.end(payload);
}
// constructor for SharePoint Online client
SPO = function (url) {
this.url = urlparse(url);
this.host = this.url.host;
this.path = this.url.path;
// External Security Token Service for SPO
this.sts = {
host: 'login.microsoftonline.com',
path: '/extSTS.srf'
};
// Form to submit SAML token
this.login = '/_forms/default.aspx?wa=wsignin1.0';
};
SPO.prototype = {
signin: signin
};
var client = new SPO('http://yourdomain.sharepoint.com/yoursite');
client.signin("yourusername", "yourpassword", function () {
// make sure the XMLHtpRequest includes the authentication cookies
XMLHttpRequest.authcookies = 'FedAuth=' + client.FedAuth + '; rtFa=' + client.rtFa;
// as of this point, you can use the CSOM service as if you are in a browser......
// for example, we will request the properties of the site 'teamsite'.
var ctx = new SP.ClientContext("/teamsite"),
web = ctx.get_web();
ctx.load(web);
ctx.executeQueryAsync(function () {
var properties = web.get_objectData().get_properties();
console.log(properties);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment