Context Tokens, Refresh Tokens and Access Tokens. Building SharePoint Apps with Ruby on Rails part 2

Welcome back to the second part in our series on building SharePoint 2013 Apps with Ruby on Rails. Hopefully you have read and followed along with Part 1. Now we are ready to write some Ruby code and get our Rails app talking to SharePoint. Let’s take an overview of the things that are happening behind the scenes with SharePoint and our App. I borrowed this image from Ted Pattison’s presentation at SPC

SharePoint App OAuth Process

[click to enlarge]

Steps 1 – 4 happen behind the scenes. When SharePoint renders your App tile or link on the quick launch bar these steps happen so that when you click on the app link the user is redirected to appredirect.aspx passing the required query string parameters for that app.

Step 5 – When the user clicks on a link to your app from within SharePoint, the link goes to _layouts/15/appredirect.aspx and the user is then redirected to your app, with the Context Token which is signed with your app secret.

Step 6 – Your app receives the request and from the post body of the request you can retrieve the Context Token. Using the app secret you can decode the Context Token and get the Refresh Token value from it. The Refresh Token is posted to Azure ACS along with a few other bits of information.

Step 7 – Upon receiving a valid Refresh Token from the App, ACS returns an Access Token.

Step 8 – With the Access Token your App can make REST calls to SharePoint

Step 9 – 10 are as described in the image.

So within our App, we only need to worry about Step 5 – 10. If you are building a .NET based Provider Hosted or Auto-Provisioned App the good news is the TokenHelper.cs class which is generated as part of your solution will do Step 5 – 7 for you. If you are working away from the Microsoft stack, on Ruby on Rails or PHP for example, you will need to write the code to do this yourself. And that is the aim of this blog post! By the end of this post you will be able to get a valid Access Token back from ACS and get the SPWeb’s title where the app was installed.

From Part 1 in this series we have:

1, Registered our SharePoint App with appregnew.aspx

2, Create and deployed the app package with Visual Studio 2012

3, Create a Ruby on Rails web app

4, Configured our Ruby on Rails web app to work with a temporary ssl certificate so it can respond to https requests.

If you click on our App tile from within Office 365 all we get at the moment is the default ‘Welcome to Rails’ page. Let’s create a new controller and view. In a terminal window and from within our SharePointDemo folder, type:

rails generate controller home index

in TextMate open the file config/routes.rb and add the line

root :to => ‘home#index’

Finally delete the file public/index.html

Save the files you changed, and restart up your Rails app with

bundle exec ruby script/secure_rails s

Now if you navigate to your SharePoint Developer Site Collection and click on the SharePointDemo app link you will be navigated over to our Rails App and the Index View from the Home Controller will be rendered.

Default view

Still our App isn’t really doing anything, so let’s start to do some coding! Our list of jobs are:

1, Get the ContextToken from the post values that came from SharePoint

2, Decode the ContextToken using our App Secret to get the Refresh Token

3, Post the RefreshToken to ACS

4, Get back an Access Token

Once we have our Access Token we can start using the REST api.

In TextMate, open up app/controllers/homecontroller.rb

At the top of the file add the following ‘require’ statements

require ‘jwt’
require ‘json’
require ‘rest-client’
require ‘nokogiri’

You can think of this as being the same as adding ‘using’ statements at the top of our C# classes. This simply allows us to use these libraries within this Ruby class.

We will do things with baby steps. Within your Index controller method add the line:

@spAppToken = params[:SPAppToken]

And let’s try and display this in our Index view. Open the file /app/views/home/index.html.erb and add:

<p>SPAppToken  : <%= apAppToken %></p>

Save the files, re-run the bundle command from the Terminal window and test going to your SharePoint Dev site and clicking the App tile.

<NOTE>

When you click on the App tile you are posted over to the redirect URL which in our case happens to be https://localhost:3001. As we are using a test/temp certificate, the first time you hit this url you will get a certificate warning you need to accept. This causes a problem as displaying the certificate warning means the browser loses the values SharePoint posted ie the SPAppToken.

If you are presented with the certificate warning, accept it – then hit the back button until you get back to SharePoint again, and click on the App tile again. As you have previously accepted the certificate warning it will be surpressed, and the SPAppToken will be correctly posted to https://localhost for Ruby to work with.

</NOTE>

If you have dealt with the note above OK, you should see the SPAppToken displayed in your browser.

SPAppToken

Great – Quite a nice set of seemingly randon characters eh? Now we need to decode this using our App secret. Add this line of code to your controller method

@decoded = JWT.decode(@spAppToken, ‘Your App Secret’, false)

And add to your Index view

<p>Decoded : <%= @decoded %></p>

Save your files, re-bundle and run the app, and re-launch your app from SharePoint.

Decoded SPAppToken

The decoded value is a mixture of a Ruby hash and blob of JSON so we’ll need to get that part out and parse it:

@appctx = @decoded[‘appctx’]

@acsServer = JSON.parse(@appctx)[‘SecurityTokenServiceUri’]

With the ACS Url we get from the decoded information, we want to make a post request – passing over the following information:

part1 = ‘00000003-0000-0ff1-ce00-000000000000’
part2 = “lightningtools674.sharepoint.com
part3 = @decoded[‘appctxsender’].split(‘@’)[1]

postdata = {‘grant_type’ => ‘refresh_token’,
‘client_id’ => @decoded[‘aud’],
‘client_secret’ => ‘F3xjhfPSBTI4Ic5v/QXTzZhGDQZrDyyvv1ilEOZ1c0A=’,
‘refresh_token’ => @decoded[‘refreshtoken’],
‘resource’ => part1 + ‘/’ + part2 + ‘@’ + part3}

First we get the individual parts that make up the resource value we need to pass to ACS. Part 1 is a unique identifier for SharePoint/Office 365. Part 2 is the Office 365 tenant, and Part 3 is the App Id.

The hash that we build up to post to ACS then contains a number of parameters. The names of the values should make mostly makes sense – with client id being the app id.

Now we can actually make our post to the ACS server:

@result = RestClient.post @acsServer, postdata

And parse the access token out of the @result

@access_token = JSON.parse(@result)[‘access_token’]

Let’s modify our view, so that we can check we get back an access token from ACS. Add the line:

<p>Access Token : <%= @access_token %></p>

Save all your files in Textmate, and restart up WEBBrick. Open up your Office 365 Dev site collection and click on the app link. If everything is working correctly you will see the information we previously saw, plus the access token at the bottom.

Access Token

You will notice some other interesting values returned to you here as well. We’ll talk in a later blog post about how and why to store the CacheKey in a cookie to reference the access token and refresh token stored in a database.

Woot! Now we can actually go about using the SharePoint 2013 REST services to get some information about our host site. We want to pass our access token as part of the request body. This will ensure our access token is encrypted over SSL. Here’s the format that we send it over:

@auth = {‘Authorization’ => ‘Bearer ‘ + @access_token}

And here’s the REST call we are going to make to get the title of the Host Web where the app was installed

response = RestClient.get ‘https://{your office 365 tenant}/sites/dev/_api/web/title‘, @auth

We can parse out the site title with:

@title = Nokogiri.XML(response).xpath(‘//d:Title’).first.text

Then display @title in our view

<p>Title : <%= @title %>

Save all the files, restart Rails and visit your app again – and with some good coding skills and a bit of luck you will see the title of your host web!  😎

Site Title

Hurrah – our Ruby on Rails SharePoint App does something useful. This is where we’ll end this blog post. In our next post we will look at how we can do some more advanced things such as uploading documents and posting to the Host Webs newsfeed!

<nickswan/>