remote event handlers in o365 & azure part 5: setup the ... web viewthe app permission policy to...

29
Provider Hosted App for Windows Azure A) Create Windows Azure Service Bus Remote Event Handlers in O365 & Azure Part 5: Setup the Windows Azure Service Bus (Post-August 2014) The overall objective is to create a Remote Event Receiver (RER) for SharePoint Online so that when list items are added to a list, an event is triggered that allows us as developers to react to this. We must be able to debug this so we can understand how it works. So this blog post has been split in to the following sections: 1. Setup Windows Azure – this involves creating a new subscription with a trial license to remotely host our code. 2. Setup the Windows Azure Website – we need this as a location to deploy our code to, so that SharePoint Online can access. 3. Setup the Windows Azure Service Bus (Pre-August 2014) – this is via the Azure interface, which is now considered the wrong way as it doesn’t create the ACS connection string. Skip this section and do section 5 instead if you want to get this up and running quickly. 4. Setup the RER Project – Visual Studio 2013 will be used to install and debug our code, using a reference to the Azure Service Bus created in the previous stage. 5. Setup the Windows Azure Service Bus (Post-August 2014) – this is via PowerShell, which is now considered the correct way (or the only way that works!) due to changes in Azure and should work on all Post-August 2014 projects… Read more below Part 5: Setup the Windows Azure Service Bus (Post-August 2014)

Upload: vuphuc

Post on 01-Feb-2018

217 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Provider Hosted App for Windows Azure

A) Create Windows Azure Service Bus

Remote Event Handlers in O365 & Azure Part 5: Setup the Windows Azure Service Bus (Post-August 2014)

The overall objective is to create a Remote Event Receiver (RER) for SharePoint Online so that when list items are added to a list, an event is triggered that allows us as developers to react to this. We must be able to debug this so we can understand how it works. So this blog post has been split in to the following sections:

1. Setup Windows Azure – this involves creating a new subscription with a trial license to remotely host our code.

2. Setup the Windows Azure Website – we need this as a location to deploy our code to, so that SharePoint Online can access.

3. Setup the Windows Azure Service Bus (Pre-August 2014) – this is via the Azure interface, which is now considered the wrong way as it doesn’t create the ACS connection string. Skip this section and do section 5 instead if you want to get this up and running quickly.

4. Setup the RER Project – Visual Studio 2013 will be used to install and debug our code, using a reference to the Azure Service Bus created in the previous stage.

5. Setup the Windows Azure Service Bus (Post-August 2014) – this is via PowerShell, which is now considered the correct way (or the only way that works!) due to changes in Azure and should work on all Post-August 2014 projects… Read more below

Part 5: Setup the Windows Azure Service Bus (Post-August 2014)

If like me, you notice the code still doesn’t hit your breakpoints. When pressing F5 to debug I noticed the following error in the Output window of Visual Studio:

“Cannot register Services/AppEventReceiver.svc on Microsoft Azure Service Bus: The remote server returned an error: (500) Internal Server Error.”

“Cannot register Services/RemoteEventReceiver1.svc on Microsoft Azure Service Bus: The remote server returned an error: (500) Internal Server Error.”

Page 2: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Dammit! Ok so after a quick message to Microsoft complaining that the Azure Service Bus was broken, Charls Tom Jacob from MS informed me of this breaking change to the Service Bus Authentication from Microsoft. So thankfully I was able to recreate my Service Bus the right way in the following steps:

1. Launch “Microsoft Azure PowerShell”. If you don’t have it installed, open the “Web Platform Installer” and download it to your machine:

2. Run the following PowerShell to begin downloading the publish settings file: “Get-AzurePublishSettingsFile”

3. This then launches the following window in your browser:

4. Click “Save” to save this to your downloads folder:

5. Now let’s import that file into our PowerShell session so we can create that Service Bus. Run the following script: “Import-AzurePublishSettingsFile -PublishSettingsFile C:\Users\svc_eu_dspfarmadmin\Downloads\Free Trial-10-28-2014-credentials.publishsettings”

6. You should then be presented with basic info about your Azure tenant:

7. Now Charls’ article states we need to use the following script to create the Service Bus: “New-AzureSBNamespace myServiceBusName ‘West Europe’ -CreateACSNamespace 1”

Page 3: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

8. Within a minute or so the Service Bus is created and the following connection information is displayed:

9. Now if we head back to http://manage.windowsazure.com and click on “SERVICE BUS” we can see our new service bus:

10. If you click on “CONNECTION INFORMATION” at the bottom of the page, we should now see the “ACS CONNECTION STRING” which is what we can use for Visual Studio:

11. So copy that “ACS CONNECTION STRING” to the SharePoint tab of your App project properties, remember where it is still?

12. Then hit “F5”, watch the output window and you should see the services registered successfully:

Page 4: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

13. And then boooom!

References:-

1. http://nickwilliams.net/2014/10/30/remote-event-handlers-in-o365-azure-part-5-setup-the- windows-azure-service-bus-post-august-2014/

B) Create Provider Hosted App

Step1:- go to VS2012, select App for SharePoint 2013 under App Tab then give name of the Project and click OK. See as in below screen

Page 5: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Step2:- click OK then it will give another window for fill site url for where this app deployed, and check Provider Hosted App.

Step3:- next another window appear for which type of web application. Select “ASP.Net Web Forms Application” and click next.

Page 6: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Step4:- Next need to fill Configuration Authentication setting by using below screen. Click on Finish.

Step5:- the project is created.it have 2 projects, one is deployed on Office 365 and other is Azure.

Page 7: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Step6:- Before going to publish this solution, import your Azure publish profile using from windows azure site url (your reference site URL) and client Id and secret using office365 dev site url.

Open Azure site and download the Publish Profile using “Download Publish Profile” link.

Create Client Id and client Secret from office365 online site using the following url

<https://<Your site>/_layouts/15/appregnew.aspx.Ex:-https://magna123.sharepoint.com/sites/MyDevSite/_layouts/15/appregnew.aspx

Step7:-after completion of the above process, go to visual studio and right click on solution then select Publish. As shown in below .

Page 8: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Step8:- it shows another window for select publishing profile through browsing. Click on arrow button, it gives <New> from Dropdown and click on that then another window is appear. In that select Import publishing profile using browse button. Select file path from your local system.

Page 9: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Next need to provide client id and client secret. These values created in above. Click on Finish

Came back to VS2012,right click on solution and select Publish. after select current profile then click on “Deployed your web app”. See the below screen

Page 10: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Next click on Publish

Page 11: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Open web.config file, change the AppSettings, see the below screen.

Open AppManifest.xml file changed the start page and RemotewebApplication client ID.see the below screen.

Then click on Deploy Solution. After deploy the solution check in your developer site under Apps in Testing.

Click on your web app, then click on Trust it button. Your site is opened in Azure site.

Page 12: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Solution:-

RER.svc.cs file:-

using System;using System.Collections.Generic;using System.Linq;using System.Net;using System.Text;using Microsoft.SharePoint.Client;using Microsoft.SharePoint.Client.EventReceivers;

namespace RERAzureWeb.Services{ public class rajugsRER : IRemoteEventService { public SPRemoteEventResult ProcessEvent(SPRemoteEventProperties properties) { SPRemoteEventResult result = new SPRemoteEventResult();

using (ClientContext clientContext = TokenHelper.CreateRemoteEventReceiverClientContext(properties)) { if (clientContext != null) { clientContext.Load(clientContext.Web); clientContext.ExecuteQuery(); } }

return result; }

public void ProcessOneWayEvent(SPRemoteEventProperties properties) {

// obtain web URL somehow - line below is fine for a list item RER, but you'll need another approach elsewhere.. string webUrl = properties.ItemEventProperties.WebUrl;

Page 13: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Uri webUri = new Uri(webUrl);

string realm = TokenHelper.GetRealmFromTargetUrl(webUri); string accessToken = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, webUri.Authority, realm).AccessToken; using (var clientContext = TokenHelper.GetClientContextWithAccessToken(webUrl, accessToken)) { // do CSOM stuff here.. // On Item Added event, the list item creation executes if (clientContext != null) { try {

clientContext.Load(clientContext.Web); clientContext.ExecuteQuery(); List imageLibrary = clientContext.Web.Lists.GetByTitle("Employee"); ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation(); ListItem oListItem = imageLibrary.AddItem(itemCreateInfo); oListItem["Title"] = "TITLE CHANGED BY RER"; oListItem.Update(); clientContext.ExecuteQuery(); } catch (Exception ex) { } } }

}

}}

Elements.xml:-

<?xml version="1.0" encoding="utf-8"?><Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <Receivers ListUrl="Lists/Employee"> <Receiver> <Name>rajugsRERItemAdding</Name> <Type>ItemAdded</Type> <SequenceNumber>10000</SequenceNumber> <!--<Url>https://rajugs.azurewebsites.net/Services/AppEventReceiver.svc</Url>--> <Url>~remoteAppUrl/Services/rajugsRER.svc</Url> </Receiver> </Receivers></Elements>

Page 14: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Create list on App page:-

<%@ Page language="C#" MasterPageFile="~masterurl/default.master" Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage, Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %><%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=15.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>

<asp:Content ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server"> <SharePoint:ScriptLink name="sp.js" runat="server" OnDemand="true" LoadAfterUI="true" Localizable="false" /></asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server"> <WebPartPages:WebPartZone runat="server" FrameType="TitleBarOnly" ID="full" Title="loc:full" /> <WebPartPages:WebPartZone runat="server"FrameType="TitleBarOnly" ID="WebPartZone1" Title="loc:full" ><WebPartPages:XsltListViewWebPart ID="XsltListViewWebPart2"runat="server" ListUrl="Lists/Employee" IsIncluded="True"NoDefaultStyle="TRUE" Title="Slideshow Images"PageType="PAGE_NORMALVIEW" Default="False"ViewContentTypeId="0x"></WebPartPages:XsltListViewWebPart></WebPartPages:WebPartZone>

</asp:Content>

Extra Activities:-

Remote Event Receivers on host web gotcha – no context token/ClientContext

I’ve spent quite a bit of time working with Remote Event Receivers in SharePoint

2013/Office 365, and in the early days I hit an issue that initially made me think they didn’t

work properly at all. Now with some help, I realize that mainly the code just has to be

written a certain way - but it’s also true to say that there is a limitation which can affect

some things you might want to do. In any case, this is a gotcha that I’m starting to see

other people hit so I think it’s worth talking about it.

Page 15: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Specifically the issue occurs when:

The event receiver is on the host web (rather than the app web)

The event receiver uses CSOM code to talk to SharePoint (rather than just using

NON-SharePoint code)

Issue symptoms

When you’re trying to use RERs on the host web, what you might see is that whilst your

event receiver always fires (and your remote code does execute), your code fails to

authenticate back to SharePoint. You’ll get a 401 error when trying to obtain or use a

ClientContext object – this could manifest itself with one of these in your code:

System.NullReferenceException: Object reference not set to an instance of an object

..but if you look at the HTTP requests/responses, you’ll see the HTTP 401 (Access Denied).

This means you effectively can’t do anything with SharePoint – and often, of course,

the whole point of your event receiver is that it’s going to do something in SharePoint!

Perhaps you need to create, update or delete an item somewhere, or perform some other

action related to sites, users or data in SharePoint.

Other info:

No context tokeno If you do some debugging, you’ll find that the event receiver does NOT

receive a valid context token from SharePoint/Office 365 -

SPRemoteEventProperties.ContextToken is an empty string. This causes all

the later code to fail. At this point, you probably think there’s a bug with

SharePoint/Office 365 – even at the end of all this, I’m personally not sure

whether there is a bug or it’s just a “by-design” limitation. Fortunately, as we

will see there is a workaround which works for many (most?) scenarios of

this type.

The same code works on the app web

Page 16: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

o If you do some wider testing, perhaps to see if there is a code issue – you’ll

find the very same code works fine in other contexts. For example, if you use

the same code in a RER on the app web (e.g. “ItemAdded” on a list in the app

web), everything works fine. The issue is purely related to RERs on the host

web.

No change if you use ProcessOneWayEvent (asynchronous events such as

added, deleted etc.) or ProcessEvent (synchronous events such as adding,

deleting etc.)o Remote Event Receivers are similar to traditional full-trust event receivers,

in that both async and sync events can be used. An example here would be

the “added” and “adding” events respectively – these correspond to the

ProcessOneWayEvent and ProcessEvent methods in a Remote Event Receiver

class. For reference, the issue we’re discussing here manifests itself in both

cases.

So those are the symptoms. Before we dig into the “Why it happens” and “The workaround”

sections, it’s worth reminding ourselves of some aspects of remote code and authentication

in particular. Feel free to skip forward if you’re familiar with this territory.

A reminder on authentication of remote code

For those just starting out with Remote Event Receivers (or SharePoint apps/remote code

in general), it’s worth noting that an app is required for any form of remote

code. More correctly, we could expand this to say any remote code which runs on the

server-side and uses “app authentication” - as opposed to “user authentication” where

a username/password is specified. In any case, this can seem strange for some things like

Remote Event Receivers, where there isn’t really an “app” (e.g. with some pages) that the

user will enter/click around etc. All we have for a RER is a remote WCF service with no

front-end! But, this is the way the trust model works for remote code – so the first thing to

say is that if you don’t have an app registered and installed/trusted for your remote code, it

will not work.

If we were to summarize common authentication options for remote SharePoint code, we

could break it down like this:

Page 17: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

User authenticationo The username/password of a “named user” is passed – usually a very poor

approach that brings security risks. Effectively this led OAuth to be invented

as an alternative.

App authentication – this breaks down into:o User + app authentication – the default. Permissions of both the user

*and* the app are checked

o App-only authentication – the permissions of just the app are checked

(thus allowing operations that the user themselves does not have permission

to do)

Why it happens

If you’re hitting the issue, your RER most likely has code which instantiates the

ClientContext object in a certain way - specifically, you’ll be using “user + app”

authentication. The vast majority of MSDN and blog samples use this approach. This is

ultimately the problem -  “user + app” authentication does not currently work for

events related to the host web. My testing shows this is the case for both Office

365 and SharePoint 2013 on-premises installations. Along the journey of realising

this, I tried some different coding approaches – and I see other developers perhaps doing

the same (e.g. in forum posts). Since there are various ways the CSOM ClientContext

object can be obtained, you might try different code for this – but several cannot be used in

a RER and will fail. The table below shows some of the “wrong” approaches.

Code approaches which will NOT work:Approa

chCode sample Why not

Using the typical RER approach

ClientContext clientContext = TokenHelper.CreateRemoteEventReceiverClientContext(properties)

This is the approach that “should work” (and the approach that most samples use).However, it only works for events on the app web – NOT events on the host web.

Creating ClientContext

ClientContext clientContext = new ClientContext(properties.ItemEventProperties.WebUrl)

The context is not obtained in a way which deals with authentication. This is what

Page 18: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

using constructor

the TokenHelper methods are for.

Sidenote – it would be possible to authenticate with user authenticationinstead of app authentication, if the username/password of a named account was attached using the SharePointOnlineCredentials object. But that’s lame, and a big security risk! Instead, we want to use OAuth (via app authentication) of course, to avoid storing/passing passwords.

Using the “app event” approach

ClientContext clientContext = TokenHelper.CreateAppEventClientContext(properties, false)

The context is obtained in a way which is only appropriate for app events (e.g. AppInstalled/AppUpgraded/AppUninstalled etc.) Since we are using an event on the host web, authentication does not work.

As the table says, the one that *should* work is the first one

(TokenHelper.CreateRemoteEventReceiverClientContext()) – but this relies on “user +

app” authentication which appears to be the problem. So to work around this we need a

different approach. 

The workaround

Instead of “user + app” authentication we can use “app-only” authentication. This requires

2 things:

1. The app permission policy to specify that app-only calls are allowed (something the

person installing the app must agree to). This is enabled in the app manifest in

Page 19: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Visual Studio: 

2. The code in the app (i.e. in the Remote Event Receiver) to obtain ClientContext

using an app-only access token. The expected way to do this in C# is to use the

correct TokenHelper methods – big thanks to Kirk Evans for helping me with this.

The code should look like this: 

** N.B. There is a code sample here but it will not show in RSS Readers - click here for full article **

1234567891011

// obtain web URL somehow - line below is fine for a list item RER, but you'll need another approach elsewhere.. string webUrl = properties.ItemEventProperties.WebUrl; Uri webUri = new Uri(webUrl); string realm = TokenHelper.GetRealmFromTargetUrl(webUri); string accessToken = TokenHelper.GetAppOnlyAccessToken(TokenHelper.SharePointPrincipal, webUri.Authority, realm).AccessToken; using (var clientContext = TokenHelper.GetClientContextWithAccessToken(webUrl, accessToken)) { // do CSOM stuff here..}

If you ensure these two things are in place, your Remote Event Receiver will work fine.

The limitation – when the workaround is no good

So, that’s the answer then. However, you might hit occasions where the app-only approach

isn’t really what you want. If your remote code writes any data to SharePoint (e.g. adds a

Page 20: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

list item), you’ll notice that the SharePoint user interface makes it clear that the list item

was added/modified by an app. Specifically, the username will be in the following format:

Last modified at [time] by [app name] on behalf of [username]

This is a pretty useful feature for some business requirements, since it makes it clear that

although the named user was involved, they didn't make the change in SharePoint

"directly". Unfortunately, use of the app-only authentication route to solve our problem

changes this – specifically, with app-only authonly the app name is recorded as the user

who made the change. Effectively, we lose the information which tells us which actual

person was involved in the change - in some circumstances, this could be a problem if some

kind of audit trail is required. To make things clear, here are two screenshots which show

the difference:

List item added by "app + user" authentication:

List item added by "app-only" authentication:

Page 21: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

Related sidenote (for the curious!):

If you’re wondering how SharePoint/Office 365 deals with this under the covers, you’ll find

that all lists now have 2 new hidden columns - “App Created By” and “App Modified By”.

These store a reference to an entry in the User Information list in the current site (just like

other Person/Group columns):

So now you know ;)

Summary

It’s pretty easy to get things wrong with Remote Event Receivers, and the pitfall I’ve talked

about concerning authentication and CSOM code is definitely a big gotcha – I certainly see

other people hitting this. If you have remote code which modifies data in SharePoint

somewhere, the way around the problem is to use app-only authentication - by ensuring the

app’s permission policy allows this *and* also writing your CSOM code to authenticate in

this way. This can be done by obtaining an access token using

the TokenHelper.GetAppOnlyAccessToken() method, and then obtaining a ClientContext

object using this token.

However, with this approach comes a trade-off - the loss of user information (in “pseudo-

audit” terms) related to the user behind the change. Developers should bear this in mind

when working with Remote Event Receivers.

Page 22: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

App authorization policy types in SharePoint 2013apps for SharePoint

Learn about the different authorization policies for apps in SharePoint: app-only policy, user+app policy, and user-only policy. It also provides guidelines for using app-only policy.

Get an overview of app authorization policies typesSharePoint provides three types of authorization policies:

User-only policy— When the user-only policy is used, SharePoint checks only the permissions for the user. SharePoint uses his policy is enforced is when the user is accessing resources directly without using an app. (This policy was always used in SharePoint 2010.) 

User+app policy—When the user+app policy is used, SharePoint checks the permissions of both the user and the app principal. Authorization checks succeed only if both the current user and the app have permissions to perform the action in question.An example of when this policy is used is when an app for SharePoint wants to get access to the user's resources on SharePoint. The code in the remote components of the app for SharePoint should be designed to make user+app calls to SharePoint. 

App-only policy—When the app-only policy is used, SharePoint checks only the permissions of the app principal. Authorization check succeeds only if the current app has sufficient permissions to perform the action in question, regardless of the permissions of the current user (if any).An expense approval app is an example of when this policy is used. The app allows users who wouldn't otherwise be able to approve expenses to approve expenses below a certain amount. See the scenario below for details.

Note

Certain APIs require a user context and can't be executed with an app-only policy. These include many APIs for interacting with Project Server 2013 and for performing search queries.

See an example scenario of an app that uses the app-only policyLet's says a sales manager at Contoso, Adam, buys an expense submission app that uses the app-only policy. When Adam chooses to buy the app, Adam is prompted to allow the app to elevate user permissions; that is, to allow the app to make app-only calls to SharePoint. Adam grants the app the requested permission. He then purchases enough licenses for all of the Contoso sales people to use the app, and he installs it in the sales team's central SharePoint site.Soon, the salespeople are submitting expense reports using the new expense submission app. Salespeople usually cannot approve their own expense reports, but they can do this when using the app because Adam granted it the ability to do this for expense submissions below $50 because he set the app to automatically approve reports below $50. The app is

Page 23: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

automatically assigns him a task to approve reports of $50 or more. This could be implemented by giving the app for SharePoint Write permission to a SharePoint list of approved expenses. But, among users, only human resources managers have Write permission to the list. The code in the app is designed to make an app-only call to SharePoint, if the expense is less than $50, to add the expense to the list. Since the user's permissions aren't checked, any user's submissions below $50 are automatically added to the approved expenses list, even if the user doesn't have Write permission to the list.Learn how apps get permission to use the app-only policyTo be able to make app-only calls to SharePoint, your app must request the ability to use the app-only policy in the app manifest. You do this by adding theAllowAppOnlyPolicy attribute to the AppPermissionRequests element and setting it to true as shown in the following markup:XML<AppPermissionRequests AllowAppOnlyPolicy="true"> ...</AppPermissionRequests>A user installing the app will be prompted to approve this request. If the app asks for tenant-scoped permissions, then only a tenant administrator can grant use of the app-only policy, so only a tenant administrator can install the app. If the app does not ask for any permissions scoped higher than site collection, then a site collection administrator can install the app. For more information about permission scopes, see App permissions in SharePoint 2013.Learn how apps make app-only callsThe difference between an app-only call to SharePoint and a user+app call is the tyoe of access token that is included in the call. The following code shows how to make obtain user+app and app-only access tokens in managed code. The detailed coding is done for you in the TokenHelper.cs (or .vb) file that the Office Developer Tools for Visual Studio automatically add to the project in Visual Studio.C#string contextTokenString = TokenHelper.GetContextTokenFromRequest(Request);if (contextTokenString != null){ //Get context token. SharePointContextToken contextToken = TokenHelper.ReadAndValidateContextToken(contextTokenString, Request.Url.Authority); Uri sharepointUrl = new Uri(Request.QueryString["SPHostUrl"]);

//Get user+app access token. string accessToken = TokenHelper.GetAccessToken(contextToken, sharepointUrl.Authority).AccessToken;

ClientContext clientContext = TokenHelper.GetClientContextWithAccessToken(sharepointUrl.ToString(), accessToken);

Page 24: Remote Event Handlers in O365 & Azure Part 5: Setup the ... Web viewThe app permission policy to specify that app-only ... This can be done by obtaining an access token using the TokenHelper

//Do something. ... //Get app-only access token. string appOnlyAccessToken = TokenHelper.GetAppOnlyAccessToken(contextToken.TargetPrincipalName, sharepointUrl.Authority, contextToken.Realm).AccessToken; //Do something. ...}

Note

Apps that do not make OAuth authenticated calls (for example, apps that are only JavaScript running in the app web) cannot use the app-only policy. They can request the permission, but they will not be able to take advantage of it because doing so requires passing an app-only OAuth token. Only apps with web applications running outside of SharePoint can create and pass app-only tokens.

In general, a current user is required to be present for a call to be made. In the case of app-only policy, SharePoint creates a SHAREPOINT\APP, similar to the existing SHAREPOINT\SYSTEM user. All app-only requests are made by SHAREPOINT\APP. There is no way to authenticate as SHAREPOINT\APP through user-based authentication.Get guidelines for using the app-only policySince app-only calls effectively elevate user privileges, you should be conservative in creating apps that ask for permission to make them. Calls should use the app-only policy only if:

The app needs to elevate its permissions above the user for a specific call; for example, to approve an expense report under conditions evaluated by the app.

The app is not acting on behalf of any user; for example, an app that performs nightly maintenance tasks on a SharePoint document library.

Additional resources Authorization and authentication of apps for SharePoint 2013 App permissions in SharePoint 2013 Context Token OAuth flow for apps in SharePoint 2013 Apps for SharePoint Get started creating provider-hosted apps for SharePoint