Martin's Blog - Developer Infos zu SharePoint, ASP.NET, BI und anderen Technologien




powered by Component Software GmbH

RunWithElevatedPrivilege für SharePoint Apps

Seit längeren ist es im SharePoint Server API möglich, Code mit mehr Rechten auszuführen als der Benutzer der den Code ausführt eigentlich hat. Dadurch können z.B. in Webparts dem Benutzer Aktionen angeboten werden zu denen er keine Berechtigungen hat.

Unter SharePoint 2013 gibt es nun das Appmodel in dem kein Server-Seitiger Code vorkommt. Alles wird nur mit ClientObject Model programmiert. In der App-Entwicklung kann es vorkommen, dass eine App mehr Rechte  benötigt als der Benutzer hat. Bei der Installation einer App kann ein Benutzer der App aber immer nur soviel Rechte zubilligen als er selbst hat.

Wenn nun eine App eine WebSite erstellen soll, so muss der Benutzer der diese App verwendet auch das Recht zur Anlage einer WebSite haben. Zum Glück hat Microsoft hier Vorkehrung getroffen. App können mehr Rechte bekommen, als der Benutzer der sie ausführt.

App-only Security policy

Eine App kann entweder User+app policy verwenden oder app-only. Bei User+app muss sowohl der User als auch die App die notwendigen Berechtigungen haben. Bei App-Only hat nur die App die Berechtigungen zu haben. Der Benutzer benötigt diese Rechte nicht.

Im SharePoint Umfeld können nur Auto Hosted oder Provider Hosted Apps die App-Only Policy nutzen. Die SharePoint-Hosted Apps können immer nur das User+App Model verwenden.

Möchte man nun eine App schreiben, die WebSites anlegen darf, obwohl der Benutzer nur Lese-Rechte hat, muss eine Provider Hosted App erstellt werden. unter “App Dev Umgebung” habe ich beschrieben wie eine Entwicklungsmaschine konfiguriert werden muss um Provider Hosted Apps zu entwickeln.

Im App Manifest muss eingestellt werden, dass die App sogenannte “App-only calls” absetzen darf. Dies wird auf der Permissions Seite eingestellt.

image

In der XML Ansicht des Manifests ist dann er Eintrag AllowAppOnlyPolicy=”true” zu finden.

image

Apps die mit AppOnlyPolicy arbeiten können nur von Site-Collections Administratoren installiert werden.

 

Der richtige ClientContext

Im nächsten Schritt ist der Code zu bearbeiten. Die Visual Studio Vorlage einer App startet im Page Load mit Code, der einen ClientContext mit User+App Policy erstellt.

var clientContext = TokenHelper.GetS2SClientContextWithWindowsIdentity(hostWeb, Request.LogonUserIdentity)

Um jedoch einen ClientContext mit App-Only Policy zu erstellen sind folgende zwei Zeilen notwendig:

   1:  string accessToken = TokenHelper.GetS2SAccessTokenWithWindowsIdentity(hostWeb, null);
   2:  ClientContext ctx = TokenHelper.GetClientContextWithAccessToken(hostWeb.ToString(), accessToken);

Hiermit wird zuerst aus einer Server2Server Verbindung das AccessToken abgefragt und dieses zur Erstellung des ClientContext herangezogen. Spannend ist hier, dass die Angabe der Windows Identiy unterbleibt und nur Null übergeben wird. Dies bedeutet dass das Token für die App abgefragt wird.

WebSite anlegen ohne Rechte als Beispiel

Die oben genannten Punkte, habe ich zu einer Mini App zusammengestellt, die eine WebSite anlegt obwohl der Benutzer dazu keine Berechtigung hat.

   1:  private ClientContext GetClientContext()
   2:  {
   3:      Uri hostWeb = new Uri(Request.QueryString["SPHostUrl"]);
   4:      string accessToken = TokenHelper.GetS2SAccessTokenWithWindowsIdentity(hostWeb, null);
   5:      ClientContext ctx = TokenHelper.GetClientContextWithAccessToken(hostWeb.ToString(), accessToken);
   6:      return ctx;
   7:  }
   8:          
   9:  protected void btAnlegen_Click(object sender, EventArgs e)
  10:  {
  11:      string projektName = ProjektNameTextBox.Text;
  12:      using (ClientContext ctx = GetClientContext())
  13:      {
  14:          WebCreationInformation wci = new WebCreationInformation();
  15:          wci.Url = projektName;
  16:          wci.Title = projektName;
  17:          wci.WebTemplate = "STS#0";
  18:          wci.UseSamePermissionsAsParentSite = true;
  19:   
  20:          Web nWeb = ctx.Web.Webs.Add(wci);
  21:          ctx.Load(nWeb, webSite => webSite.Url);
  22:          ctx.ExecuteQuery();
  23:   
  24:          linkNewWeb.Text = "Web für " + projektName + " wurde angelegt";
  25:          linkNewWeb.NavigateUrl = nWeb.Url;
  26:          linkNewWeb.Visible = true;
  27:      }
  28:  }
Kommentare sind geschlossen

Copyright © 2024 Martin Groblschegg - Impressum