Run the app

Submitted by Erik Wegner on

Now it is time for the application to access the SharePoint server. You can find all files within the repository on GitHub: https://github.com/ErikWegner/hightrust-sharepoint-node.js

The source code of the app

var http = require('http');
var jws = require('jws')
var fs = require('fs');

var options = {
	key: fs.readFileSync('../server.key'),
	cert: fs.readFileSync('../server.crt')
};

function base64urlEscape(str) {
	return str.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}
function base64urlEncode(str) {
	return new Buffer(str).toString('base64');
}

var sharepointhostname = process.argv[2]
var clientid = "927e7578-6a96-4120-be36-495a5bbb989b"
var realm = "5df7ebc5-9401-43fe-93e2-86a07f62c2b2" // equals to SharePoint Farm ID
var issuerid = '2a80398d-800e-44b1-ac67-e34b1207114f' + "@" + realm
var audience = '00000003-0000-0ff1-ce00-000000000000/' + sharepointhostname + '@' + realm
var x5t = "+NgPPAV6+Nm+sqGz/WHYxq1Mp8E" // do not include any "=" at the end
var nameid = "s-1-5-21-1482654976-146172710-446466059-3816" // SID of the acting user
var nii = "urn:office:idp:activedirectory"

var dateref = parseInt((new Date()).getTime() / 1000)
var rs256 = '{"typ":"JWT","alg":"RS256","x5t":"' + x5t + '"}'

var actortoken = {
	aud: audience,
	iss: issuerid,
	nameid : clientid + '@' + realm,
	nbf: (dateref - 21600).toString(),
	exp: (dateref + 21600).toString(),
	trustedfordelegation: true
}

var payload = {
	aud: audience,
	iss: clientid + '@' + realm,
	nbf: (dateref - 21600).toString(),
	exp: (dateref + 21600).toString(),
	nameid: nameid,
	nii: nii,
	actortoken: jws.sign(
		{
			header: JSON.parse(rs256),
			payload: JSON.stringify(actortoken),
			privateKey : options.key
		})
}

var authtoken = base64urlEncode(JSON.stringify({"typ":"JWT", "alg":"none"})) + '.' + base64urlEncode(JSON.stringify(payload)) + '.';
authtoken = authtoken.replace(/=/g, '') // my SharePoint does not accept base64 padding

var headers = {
	'Accept': 'application/json;odata=verbose',
	'Authorization' : 'Bearer ' + authtoken
};
var options = {
	host: sharepointhostname,
	port: 80,
	path: "/sites/hightrustdemo/" + '_api/web/lists',
	method: 'GET',
	headers: headers,
	agent: false,
	ciphers: 'RC4',
	secureOptions: require ('constants').SSL_OP_NO_TLSv1_2
};
var listreq = http.get(options, function(listres) {
	listres.setEncoding('utf8');
	var listdata = "";
	listres.on('data', function(data) {
		listdata += data;
	});
	listres.on('end', function() {
		/* console.log("Response headers");
		console.log(JSON.stringify(listres.headers));
		console.log("Request headers");
		console.log(JSON.stringify(headers));
		console.log("Req fin\n\n");*/
		console.log(listdata);
		listdata = JSON.parse(listdata);
		var lists = [];
		if (listdata.d && listdata.d.results) {
			for (var ri in listdata.d.results) {
				var list = listdata.d.results[ri];
				console.log(list.Title);
			}
		}
	});
}).on('error', function(e) {
	console.log("Error " + e.message);
	console.log(JSON.stringify(e));
});

To run the script, please modify these points:

  1. Line 6: path to the private part of the certificate
  2. Line 18: the App Id
  3. Line 19: The SharePoint farm id
  4. Line 20: The issuer id from the PowerShell script (RegisterCertificate.ps1)
  5. Line 22: The x5t-code for the generated certificate
  6. Line 23: The SID of the acting user
  7. Line 63: The path to the site collection

The first command will install the required node packages. The second command runs the script, use your SharePoint hostname as the third parameter:

npm install
npm index.js sharepointserver

Command line execution

Result: A list of lists

Kommentare

Permalink

Hallo Erik,

vielen Dank für diese ausführliche Anleitung. Ich versuche gerade eine provider hosted App ohne Aspx und ohne TokenHelper.cs zu entwickeln. Deine Lösung würde mir dabei enorm helfen. Gibt es davon auch eine reine Javascript Version? Ich habe in meiner Entwicklungsumgebung leider keine Node.js und es ist leider auch nicht möglich in dieser Umgebung Node.js zu benutzen.

Würde mich auf eine Rückmeldung sehr freuen (nalizadeh@gmx.net)

Vielen Dank!

lg.

Nader

Permalink

Hallo Nader,

verstehe ich dich richtig, dass du wissen möchtest, ob es eine Variante mit clientseitigem JavaScript gibt? Darauf kann ich ganz klar antworten: Jein :-)

Für die clientseitige Kommunikation (also zwischen Browser und SharePoint) gibt es von Microsoft die bekannten Schnittstellen wie JavaScript Object Model und REST.

Wenn du eine provider-hosted App entwickelst, hast du auch einen Provider (sprich Webserver) im Spiel. Dieser kann dann eine bestimmte Sprache (C#, Java, Ruby, Python, PHP, JavaScript, Perl, etc.). Damit dein Server mit dem SharePoint-Server sprechen kann, benötigt er ein Token, dass du entweder (Cloud) per HTTP-Post-Request erhalten kannst oder tatsächlich über selbstgestrickte JavaScript-Ajax-Aufrufe. (On premise) musst du das Token auf Serverseite selbst erstellen (deshalb ja High trust app). Auf der ersten Seite dieses Tutorials findet sich der Verweis auf diesen Blog-Beitrag, der neben JavaScript auch Implementierungen für Java und PHP anzeigt. Beispielhaft ist hier eine Umsetzung für Drupal zu finden.

Am Ende sei noch der Hinweis gestattet: wenn die provider-hosted App läuft, ist es weiterhin möglich, beim Laden der SharePoint-Seite mit dieser provider-hosted App zu interagieren. Dabei wird der Browser veranlasst, ein Script vom Provider zu laden, das sich um Authentifizierung und ggfs. Benutzerschnittstelle (also Anzeige, Schaltflächen, etc.) kümmert. Damit ist für den Benutzer komplett transparent, dass sein Browser sich an der App anmeldet und die Serverseite der App kann mit dem SharePoint Daten austauschen.

Permalink

Hallo Erik

vielen Dank für deine Antwort.

Das bedeuted für High trust Apps das AccessToken kann nur auf dem Server erstellt werden (zb. auf dem Provider)

Aber wie macht denn die Cross-domain Libraries von SharePoint? oder wird dort ebenfalls ein serverseitiger Service aufgerufen?

Mein Problem ist, ich habe kein AppWeb, aber für Cross-domain Libraries brauche ich unbedingt AppWeb. Erstellung von AppWeb durch SharePoint Artefakt wäre zwar möglich aber nicht im Sinne des Erfinders.

Permalink

Der Artikel Nahtlose Provider-hosted-App zeigt, wie eine Integration einer Low-Trust-App ablaufen kann. In Kombination mit dem Wissen für die High-Trust-App lassen sich die Aufrufe so ändern, dass eventuell dein Szenario erreicht wird.

Von den Cross-Domain-Libraries kenne ich gerade nur den clientseitigen Teil, der mit den bereits verlinkten JSOM- und REST-Aufrufen arbeitet.