Project Online OData using Context Tokens

This is a work in pro­gress and has yet to be suc­cess­ful so if you can provide details for the last step, please leave a com­ment.

What I'm try­ing to accom­plish is using a con­text token to make OData calls to Project Online.  All doc­u­men­ta­tion and exam­ples use a stored user­name and pass­word, which is then used to cre­ate a Share­PointOn­line­Cre­den­tials.  This is not a viable option. You can stop read­ing if that is your solu­tion to access­ing Project Online via OData.

If how­ever, you know how to store a con­text token and make headless calls to Project Online OData please leave a com­ment below as to what is being done wrong here.

The fol­low­ing steps are sim­pli­fied as there are plenty of resources on the web that describe how to do them in detail. The dif­fi­culty doesn't come until later.

  1. Cre­ate a Provider-hosted Share­Point Add-in
  2. In the AppManifest.xml provide the fol­low­ing per­mis­sions:
  3. Reg­is­ter your Add-in with /AppRegNew.aspx, and record your Client Id & Client Secret
  4. If you haven't already, cre­ate an App­Cat­a­log.
  5. Upload your .app file to 'Apps for Share­Point' in your App­Cat­a­log.
  6. Pub­lish the Add-in Web that was cre­ated when you cre­ated your Add-in.
  7. Go to your /sites/pwa Project Online Share­Point site.
  8. Go to Set­tings (gear top right), Site con­tents.
  9. Select New (drop down), App. (Or click 'add an app' if your in the clas­sic por­tal).
  10. Under 'Your Apps' select 'From Your Orga­ni­za­tion'.
  11. Click your App, then click 'Trust It'.
  12. Once installed, click your App and make sure your Add-in Web loads fine.
  13. Now to the dif­fi­cult part…

The point of this Add-in is to make calls to Project Online using an access token retrieved using the con­text token of the user that used the Add-In to visit the site.  It is assumed this user has the nec­es­sary per­mis­sions to access the PWA resources.  We ver­ify this by using the same access token to make CSOM calls, which are suc­cess­ful.

Fol­low­ing are the key snip­pets of code.

  1. Get a Share­PointAc­sCon­text and save off nec­es­sary Url's.

    2. Get an access token from the con­text token (we could use the access token in the con­text if mak­ing the PWA calls right away, but the idea is to store the con­text token so we can call into the PWA later from a headless app.)

    3. Use the access token to call into the PWA, first with CSOM to ver­ify our access token is valid.

    4. OData doesn't appear to sup­port Bearer token header autho­riza­tion so after some research, thanks to Brian P. it appears you need to use a For­mDi­gest­Value. Let's get it.

    5. Finally hav­ing every­thing we need we should be able to make OData calls.

    This is where every­thing fails with (403) For­bid­den errors.

    I've tried both POST and GET requests to OData with the X-RequestDigest header but they both returns 403's.

    This is where I am stuck.  I can not find any way to access OData using tokens. If you have any sug­ges­tions please leave me a com­ment.

What fol­lows is the entire test con­troller from my AddIn­Web.

Which results in:

PowerBI Embedded Full Walk Through

This walk through cre­ates a sim­ple PowerBI MVC app that can embed reports.  It uses the App-Owns data model pop­u­lar for use by ISV's.

Make sure the account you're using is a Power BI Pro account.  You'll need a Pro account to do embed­ding.

Register an Azure AD app

First, we need to get the app we're going to build reg­is­tered with Active Direc­tory.  Login to PowerBI and go here:

Make sure to select Native app. Even though we're embed­ding to a web page we still need to select Native app. 'Server-side Web app' is for some­thing else.

Write down your Client ID.  This is the same as what Azure calls the Appli­ca­tion ID.

Apply Azure AD permissions

Your app will access the REST APIs via a mas­ter account.  In order to do this the mas­ter account must be given per­mis­sion.  This is done by log­ging in to the Azure por­tal using the mas­ter account and going to Active Direc­tory / App reg­is­tra­tions.  Make sure to select 'All apps' so you can see your embed­ded app.


We need to enable "Access the direc­tory as the signed-in user".

And finally, Grant those Per­mis­sions.  The mas­ter account you're logged in as now has those rights.

Power BI rights should auto­mat­i­cally be con­fig­ured when the app was reg­is­tered.  If not, click Power BI Ser­vice, select the nec­es­sary Per­mis­sions, Save, and Grant Per­mis­sion for those as well.

Create Web Project

Visual C# / ASP.NET Web Appli­ca­tion (.NET Frame­work)

Create PowerBI App Workspace

This is where your PowerBI .pbix files will be uploaded to.

Get your Group ID GUID

Click on your new App Work­space to open it.

And copy the GUID from the Url.  This is your Group Id (App Work­spaces used to be called groups).

Publish a PBIX to your new App Workspace

I've always got a sim­ple of sim­ple PBIX lying around for test­ing.  Mine's called Colors.pbix. Feel free to down­load and rename (don't extract, just rename) to Colors.pbix.

Open your PBIX, make sure your logged in under the mas­ter account, then Pub­lish your file to your new App Work­space.


Setup Web.config

Use the Client ID you saved off dur­ing App Reg­is­tra­tion above to set "pbi.clientId"

Use the Group ID we got from cre­at­ing our new App Work­space above to set "pbi.groupId"

Then use the mas­ter account's cre­den­tials for "pbi.user" and "pbi.pass" (obvi­ously encrypt your pass­word or use some­thing like Key­Vault).

Start Coding

I won't be orga­niz­ing my code as one should in a real project but for Demo pur­poses it will do and make things easy peezy.

Setup your Project

Add a class to the Con­troller folder called EmbedManager.cs

Using NuGet install the fol­low­ing pack­ages:

 *        Microsoft.IdentityModel.Clients.ActiveDirectory
 *        Microsoft.PowerBI.Api

Add some using state­ments & pull in your App Set­tings.

Get an Access Token

The first thing you need is an access token so you can make calls into the PowerBI REST API.

Since all Embed­ded func­tion­al­ity works through App Work­spaces, all your REST API  calls using the Power­BIClient wrap­per need to use the InGroup ver­sion.

Let's make our first call into the API to get a list of reports from the App Work­space we cre­ated.

(see below if you have any issues com­pil­ing at this point)

Add a call to GetRe­ports() from the Con­troller:


If you haven't given your app the proper AD per­mis­sions you'll see this:

See "Apply Azure AD per­mis­sions" above to give the cor­rect per­mis­sions.

If all goes well, look at your Out­put win­dow and you should see:

That's it!  The hard parts done.  Now all you have to do is embed the report!

Let's do it…

Cre­ate a tiny class to hold just what you need for embed­ding.

We'll also want to get an Embed Token.  Tech­ni­cally you can use your Access Token to embed the report, but don't!  That's a secu­rity risk because any­one with that token could view other reports that token has access to.  Instead, we want a report speci­fic token that will expire.

Update our Home­Con­troller

Add use our Embed­Con­fig in the View to show the report.

OK, so that's not the rec­om­mended way to do the Javascript part of the embed­ding.  But that's what's going on under the hood and doesn't require any other JavaScript libraries.  Check out this great arti­cle for tons more details.

To do it right, use the PowerBI Javascript library and do it like this.

That's it!  Happy embed­ding.

Possible Issues

Issue: Could not load file or assem­bly 'Newtonsoft.Json, Version=
Solu­tion: Man­age NuGet pack­ages for Solu­tion, Install 7.0.1

Sample Project

Here's a great sam­ple project that includes all the code nec­es­sary to cre­ate App-Owns and User-Owns projects.

Move Azure VM from Premium to Standard Storage

Took me awhile to work out the specifics but this works.  You can have the exact VM run­ning on a Pre­mium stor­age account up and run­ning again on a Stan­dard stor­age account in only a few min­utes. Note: this is for ARM, not clas­sic.

  • Stop the VM so it says "Stopped (deal­lo­cated)", not just "Stopped". Shut­ting it down from RDP isn't enough. Do this via the por­tal, right-click, STOP.
  • Copy its VHD from the Pre­mium stor­age account to a Stan­dard stor­age account:

Next, cre­ate a new VM using the copied VHD. This came from here, then I mod­i­fied to use an exist­ing VNet rather than cre­at­ing one.

Hidden LED Keyboard Light

Annoyed by not being able to see my F-keys when it's dark I devised this lit­tle light­ing sys­tem that works great.  Ide­ally I'd like an illu­mi­nated key­board but sadly those only come on lap­tops these days.  At least the one I require isn't lit.  Until now…

What you need:

Tilt your mon­i­tor over…

2016-03-12 11.18.18

Attach the LED strip under­neath.

2016-03-12 11.27.28

Light it up!

2016-05-14 08.04.11


2016-05-14 08.05.55


2016-05-14 08.06.03

Now go enjoy those 5am cod­ing ses­sions and actu­ally be able to see F8!

How to Fix a Slippery iPhone

20151007-2029-P1010206-bSo you just got a new iPhone 6 and the first thing you notice is how ter­ri­bly slip­pery it is.  First solu­tion that obvi­ously comes to mind is get­ting a case.  That helps, but then you sac­ri­fice size.  Why have this beau­ti­fully thin phone if you've got a gigan­tic case wrapped around it.

With a few easy steps and around 25 bucks there's an easy fix.  Keep in mind, this solu­tion doesn't cre­ate any pro­tec­tion for your phone, it keeps it nice and lean but adds some much needed grip.
Con­tinue read­ing How to Fix a Slip­pery iPhone