Kirk Evans is a Microsoft Architect for the Azure Center of Excellence.
Introduction to SharePoint and Azure IaaS
Building SharePoint Apps with Windows Azure Platform as a Service
SharePoint Solutions and Architectures on Windows Azure Infrastructure Services
Understanding Authentication and Permissions with Apps for SharePoint and Office
This post will show you how to inspect the SharePoint 2013 context token to better understand how OAuth is used in SharePoint 2013 apps.
In order to use a context token with SharePoint 2013 apps, you will need to create a provider-hosted app that uses a client ID and a client secret. This requires that the target SharePoint farm has a trust configured to Azure Access Control Services, or ACS. Office365 automatically configures this trust for you, so if you create your app using Office365 then this works just fine. If you create your app using your own SharePoint farm, then you will need to configure low-trust apps for on-premises deployments in order to establish a trust with Azure ACS for your SharePoint farm.
When you use a client ID and a client secret to build your app, you are using Azure ACS as the authentication server. The OAuth flow looks like this:
This is what I jokingly refer to as “the scary slide”. It’s not really that scary once you understand it.
The really important thing to understand is what’s passed to your app, the context token. The context token contains a few key pieces of information necessary for the rest of the plumbing to function.
Now that we’ve walked through the steps of the OAuth dance, let’s take a look at what’s in that context token that is critical to the whole process. When you use Visual Studio to create a provider-hosted app, the boiler plate code looks like this:
protected void Page_Load(object sender, EventArgs e)
// The following code gets the client context and Title property by using TokenHelper.
// To access other properties, you may need to request permissions on the host web.
var contextToken = TokenHelper.GetContextTokenFromRequest(Page.Request);
Response.Write(contextToken + "<br/>");
var hostWeb = Page.Request["SPHostUrl"];
using (var clientContext = TokenHelper.GetClientContextWithContextToken(hostWeb, contextToken, Request.Url.Authority))
clientContext.Load(clientContext.Web, web => web.Title);
Reading that code, you can see that the context token is passed to your app, but it is a base64 encoded string that is unintelligible. I added a Response.Write statement to write the context token to the page, but you can also see it in Fiddler. In the following screen shot, I highlighted the SPAppToken HTTP form variable where the context token is passed.
Once you have that context token, you have the base64 encoded value of the context token, which is a JWT token. The JWT token format is pretty straightforward, and the TokenHelper.cs class in Visual Studio simply parses that JWT token for you. However, for the curious who want to see what it looks like, you can use a tool like http://openidtest.uninett.no/jwt to inspect the JWT token. Copy the context token string into the “Encoded JWT” text box and the client secret into the “Secret” text box, and then press decode.
What is returned is the following JSON object, which is a JWT token that contains a set of claims.
The following shows the properties for the context token.
During Ignite training, I tell the attendees that the most important thing you can understand when building apps for SharePoint is OAuth. You need to understand the OAuth dance, the reason for the context token, and it is invaluable to understand what the TokenHelper.cs is doing for you when it does things like GetClientContextFromContextToken. This post goes into some of the details on why this is such an important piece to understand when troubleshooting apps. You can also see why it is mandatory for apps to SSL due to the nature of information being sent in HTTP.
You can find more information about the context token, calculating nbf and exp claim values, and links to additional articles at http://msdn.microsoft.com/en-us/library/office/apps/fp179932.aspx.
configure low-trust apps for on-premises deployments
JWT token format
Tips and FAQs: OAuth and remote apps for SharePoint 2013
Nice Post. I did a blog post recently explaining how we can use just HTTP requests to get the accesstoken, which explains some of the internal flow of TokenHelper.
Here is the post : jomit.blogspot.com/.../authentication-and-authorization-with.html
I used the VS model that mounts to interact with the app, but when the user gets some minutes without interacting with the buttons, the context is null and the error page. The user is then required to start the app again. Know what can be?
What could cause an "System.IdentityModel.Tokens.SecurityTokenException: Invalid JWT token. Could not resolve issuer token."?
The issuer token (iss right?) is supplied by SharePoint (as is everything else in that header apart from the client secret) so what could possibly cause this exception why trying to use context token in TokenHelper?
This all worked fine in development but when I published, my web site no longer receives the context token. What setting did I miss?
I had to use Fiddler to figure out what was going wrong. I had to adjust the settings in my client ID setup in the seller dashboard to match what was expected as far as the domain and URL.
The question is why? Why is Microsoft making it so hard to communicate with SharePoint server. JSOM?CSOM has FormDigest. why can't you just make the same set of calls? To make it worse they never explained in their documentation or sample what is going on behind the scene like you so clearly explained. Thanks for sharing.
Nice post! BTW, I'm having the same issue as Dave.. When I'm running the webapp locally everything is right, but when I upload it to Azure, SPAppToken is null and it can't authenticate...
Any thoughts on this?
@fretwio and @Dave -
Assuming you are using AppRegNew.aspx, the domain and callback URL are required when registering the app. If you use them locally, then you would have registered http://localhost. When publishing to another site (such as Azure Web App) you have to register a new entry with the new domain and callback URL. These are not editable when using AppRegNew.aspx.
If you are using the store registration, same thing... you need to update the domain and callback URL.
I am a little baffled about that. Every decent developer must be switching back and forth between testing locally and deploying remotely constantly. Is the intention that they should edit their Web.config to change the client ID each time such a switch is made, or is there a less dumb way to go about it?