SharePoint Add-Ins automatisch vertrauen

Mithilfe der SharePoint Management Shell bzw. dem Client-Side Object Model (CSOM) können SharePoint Add-Ins automatisch bereitgestellt werden. Allerdings muss dem Add-In über dieses Vorgehen manuell vertraut werden, was bei vielen Instanzen äußerst aufwendig ist. Dieser Beitrag zeigt exemplarisch wie man Add-Ins unter SharePoint On-Premise sowie SharePoint Online vertrauen kann.

SharePoint On-Premise

In einer On-Premise Umgebung können einzelne Berechtigungen mithilfe die SharePoint Management Shell über das Cmdlet Set-SPAppPrincipalPermission gesetzt werden.

$clientID = "f63a6baf-5d74-4268-ae91-94147ae5d845"
$webUrl = "https://mySharePoint.sharepoint.com"
$web = Get-SPWeb -Identity $webUrl -verbose:$false
$site = $web.Site
$authRealm = Get-SPAuthenticationRealm -ServiceContext $site.Url
$identifier = $clientID + "@" + $authRealm
$principal = Get-SPAppPrincipal -Site $site.Url –NameIdentifier $identifier
Set-SPAppPrincipalPermission -Site $web -AppPrincipal $principal -Scope SiteCollection -Right "Read"

Der Prameter Scope gibt an für welche Ebene die Berechtigungen vergeben werden sollen. Es stehen die folgenden Werte zur Auswahl:

  • Site
  • SiteCollection
  • SiteSubscription

Über den Parameter Right können die folgenden Berechtigungen gesetzt werden:

  • Read
  • Write
  • Manage
  • FullControl

Alternativ kann das Vertrauen von dem Add-In auch über eine Automatisierung vom Internet Explorer über PowerShell erfolgen. Dabei wird automatisch die URL „/_layouts/15/appinv.aspx?AppInstanceId={appInstanceId}“ geöffnet und der „Vertrauen“ Button gedrückt. Ein Beispiel hierfür gibt es hier.

Add-In Vertrauen

SharePoint Online

Für SharePoint Online stehen derzeit keine Funktionen zur Verfügung, die man für das automatische Setzen der Add-In Berechtigungen verwenden könnte. Aufgrund der Authentifizierung mit dem Azure AD kommt auch die IE-Automatisierung nicht in Frage. Das folgende exemplarische Beispiel wurde mit C# implementiert und vertraut dem Add-In über die HttpWebRequest Klasse. Die Authentifizierung an dem Azure AD erfolgt über das Authentication Cookie von dem aktuellen SharePoint Context.

Im ersten Schritt wird die URL „/_layouts/15/appinv.aspx?AppInstanceId={appInstanceId}“ abgerufen. Im Anschluss wird das Formular über eine POST Method abgesendet. Das Formular enthält die Standardinformationen, die aus der Rückgabe von dem ersten Aufruf ausgelesen werden. Zusätzlich wird der Wert „&__EVENTTARGET=ctl00%24PlaceHolderMain%24BtnAllow&__EVENTARGUMENT=“ übermittelt, um einen Klick auf den Button Vertrauen zu übergeben.

public void TrustApp(AppInstance appInstance, Web web)
{

var url = string.Format(
"{0}/_layouts/15/AppInv.aspx?AppInstanceId={1}",
web.Url, appInstance.Id);
var uri = new Uri(url);
var credentials = (SharePointOnlineCredentials)web.Context.Credentials;
var authCookie = credentials.GetAuthenticationCookie(uri);
var requestBody = GetRequest(url, authCookie);
PostRequest(url, authCookie, requestBody);
}

public string GetRequest(string url, string authCookie)
{

var request = (HttpWebRequest)WebRequest.Create(url);
request.ContentType = "text/xml; encoding='utf-8'";
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
request.Headers.Add(HttpRequestHeader.Cookie, authCookie);
request.AllowAutoRedirect = true;
request.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";

string result;
using (var response = (HttpWebResponse)request.GetResponse())
{
var stream = response.GetResponseStream();
using (var reader = new StreamReader(stream,
Encoding.GetEncoding("utf-8")))
{
result = reader.ReadToEnd();
}
}
return result;
}

public void PostRequest(string url, string authCookie, string requestBody)
{

var postBody = "__REQUESTDIGEST=" + GetHiddenField(requestBody,
"__REQUESTDIGEST") +
"&__EVENTVALIDATION=" + GetHiddenField(requestBody,
"__EVENTVALIDATION") +
"&__VIEWSTATE=" + GetHiddenField(requestBody, "__VIEWSTATE") +
"&__EVENTTARGET=ctl00%24PlaceHolderMain%24BtnAllow" +
"&__EVENTARGUMENT=";

var request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "application/x-www-form-urlencoded";
request.Proxy.Credentials = CredentialCache.DefaultCredentials;
request.Headers.Add(HttpRequestHeader.Cookie, authCookie);
request.AllowAutoRedirect = true;
request.UserAgent = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)";
var postByte = Encoding.UTF8.GetBytes(postBody);
request.ContentLength = postByte.Length;

using (var postStream = request.GetRequestStream())
{
postStream.Write(postByte, 0, postByte.Length);
postStream.Close();
string result;
using (var response = (HttpWebResponse)request.GetResponse())
{
var stream = response.GetResponseStream();
using (var reader = new StreamReader(stream,
Encoding.GetEncoding("utf-8")))
{
result = reader.ReadToEnd();
}
}
}
}

private static string GetHiddenField(string body, string fieldId)
{

string regex = string.Format("id=\"{0}\".*value=\"(.*)\"", fieldId);
string val = Regex.Match(body, regex,
RegexOptions.IgnoreCase).Groups[1].Value;
return HttpUtility.UrlEncode(val);
}