AAD: app secrets, API-only access, and consent

At Readify yesterday, I saw two different co-workers encounter the same issue within a few hours of each other. Time for a blog post!


Problem 1:

I’m trying to use Power BI AAD App Registration to access Power BI REST API using ClientId and Key. The idea is to automate Power BI publishing activities through VSTS without a need of using my OrgId credentials. Pretty much I follow this guide but in PowerShell. The registration through https://dev.powerbi.com/apps sets the app registration up and configures API scopes. I’m able to get a JWT but when I call any of Power BI endpoints I’m getting 401 Unauthorised response. I’ve checked JWT and it’s valid but much different from the one I’m getting using my OrgId.

Problem 2:

Anyone familiar with App Registrations in Azure? Specifically I’m trying to figure out how to call the Graph API (using AppID and secret key generated on the portal), to query for any user’s group memberships. We already have an app registration that works. I’m trying to replicate what it’s doing. The end result is that while I can obtain a token for my new registration, trying to access group membership gives an unauthorized error. I have tried checking every permission under delegated permissions but it doesn’t seem to do the trick.

They were both trying to:

  1. Create an app registration in AAD
  2. Grab the client ID and secret
  3. Immediately use these secrets to make API calls as the application (not on behalf of a user)

Base Principles

App Registrations

AAD has the concept of App Registrations. These are essentially a manifest file that describes what an application is, what its endpoints are, and what permissions it needs to operate.

It’s easiest to think of app registrations from the perspective of a multi-tenant SaaS app. There’s an organisation who publishes an application, then multiple organisations who use that app. App registrations are the publisher side of this story. They’re like the marketplace listing for the app.

App registrations are made/hosted against a tenant which represents the publisher of the app. For example, “MegaAwesome App” by Readify would have its app registration in the readify.onmicrosoft.com directory. This is a single, global registration for this app across all of AAD, regardless of how many organisations use the app.

App registrations are primarily managed via https://portal.azure.com or https://aad.portal.azure.com. There’s also a somewhat simplified interface at https://apps.dev.microsoft.com, and some workload-specific ones like https://dev.powerbi.com/apps. They’re all just different UIs on top of the same registration store.

Enterprise Apps

These are like ‘instances’ of the application, or ‘subscriptions’. In the multi-tenant SaaS app scenario, each consumer gets an Enterprise App defined.

The enterprise app entry describes whether the specific app is even approved for use or not, what permissions have actually been granted, and which users or groups have been assigned access.

  • Publisher: readify.onmicrosoft.com
    • App Registration for ‘MegaAwesome App’
      • Defined by development team
      • Describes name, logo, endpoints, required permissions
  • Subscriber: contoso.onmicrosoft.com
    • Enterprise App for ‘MegaAwesome App by Readify’
      • Acknowledges that Contoso uses the app
      • Controlled by Contoso’s IT admins
      • Grants permission for the app to access specific Contoso resources
      • Grants permission for specific Contoso users/groups to access the app
      • Defines access requirements for how Contoso users access the app (i.e. Conditional Access rules around MFA, device registration, and MDM compliance)
      • Might override the app name or logo, to rebrand how it displays in navigation experiences like https://myapps.microsoft.com.

If we take the multi-tenant SaaS scenario away, and just focus on an internal app in our own org, all we do is put both entries in the same tenant:

  • Org: readify.onmicrosoft.com
    • App Registration for ‘MegaAwesome App’
      • Defined by development team
    • Enterprise App for ‘MegaAwesome App by Readify’
      • Controlled by Readify’s IT admins (not dev team)

The App Registration and the Enterprise App then represent the internal split between the dev team and the IT/security team who own the directory.


This is (mostly) how an enterprise app instance gets created.

The first time an app is used by a subscriber tenant, the enterprise app entry is created. Some form of consent is required before the app actually gets any permissions to that subscriber tenant though.

Depending on the permissions requested in the app registration or login flow, consent might come from the end user, or might require a tenant admin.

In an interactive / web-based login flow, the user will see the consent prompt after the sign-in screen, but before they’re redirected back to the app.

Our Problem

In the scenario that both of my co-workers were hitting, they had:

  1. Created an app registration
  2. Grabbed the app’s client ID and secret
  3. Tried to make an API call using those values
  4. Failed with a 401 Unauthorised response

Because they weren’t redirecting a user off to the login endpoint, there was no user-interactive login flow, and thus no opportunity for the enterprise app entry to be created or for consent to be provided.

Basic Solution

You can jump straight to the consent prompt via this super-easy to remember, magical URL:


You fill in the values for your tenant, app client ID, and requested resource ID, then just visit this URL in a browser once. The redirect URI and nonce don’t matter as it’s only yourself being redirect there after the consent has been granted.

For example:


Better Solution

Requiring a user to visit a one-time magical URL to setup an app is prone to failure. Somebody will inevitably want to deploy the app/script to another environment, or change a permission, and then wonder why everything is broken even though the app registrations are exactly the same.

In scripts that rely on app-based authentication, I like to include a self-test for each resource. This self-test does a basic read-only API call to assert that the required permissions are there, then provides a useful error if they aren’t, including a pre-built consent URL. Anybody running the script or reviewing logs can browse straight to the link without needing to understand the full details of what we’ve just been through earlier in this post.

Preferred Solutions

Where possible, act on behalf of a user rather than using the generic app secret to make API calls. This makes for an easier consent flow in most cases, and gives a better audit log of who’s done what rather than just which app did something.

Further, try to avoid actually storing the app client ID and secret anywhere. They become another magical set of credentials that aren’t attributed to any particular user, and that don’t get rotated with any real frequency. To bootstrap them into your app, rather than storing them in config, look at solutions like Managed Service Identity. This lets AAD manage the service principal and inject it into your app’s configuration context at runtime.

Other Resources


Hassle-Free Screencast Recording with Windows 10

Short screencasts are a key technique in my overall communication toolbox.

I like to use them to communicate complex messages, where the background is often even more important than the actual outcome.

They allow us to share complex ideas in a way that people can consume asynchronously. As an example, right now we’re rolling out our Readify FY18 plans as a series of 10-minute chapters.

They also prevent people from skim-reading and missing context. I design the length of the video to be the time investment required of somebody. (Here’s an idea. Want an opinion? You need to invest at least X minutes of your time to hear it out first. Otherwise, you’re wasting both of our time.) Typically 5 – 10 minutes are good sized chunks. If somebody comments “I haven’t watched the video, but“, then I’m quite comfortable to suggest that I’ll give them the 5 – 10 minutes to go and actually watch the video, and then I’ll be willing to discuss it when they’re done.

Of course, screencasts are just one communication technique. Earlier in the FY18 planning process, when there were ideas flying everywhere, we shared the content as mostly raw meeting notes and bullet point dumps. We shared with the expectation that people would skim-read at best, and that that was ok: they would call out the areas they wanted to talk about in any detail.

Previous Tools

PowerPoint’s own recording tools aren’t great. They’re designed for narrated slides, rather than a recorded presentation, and there are some subtle but awkward differences there. The prime one is that they store the audio track as a separate recording on each slide, resulting in a silent gap at each slide transition. I usually talk over the slide transitions to bridge the content, which ends up sounding terrible. It also trashes your PPTX file by putting auto-advance time stamps all through it (because that’s how they move to the next audio block).

I used to use a tool called SnagIt. It was nice and simple, with a reasonable price point (~$50), however it hasn’t progressed to the world of 4K screens. On a Surface Pro 4, this means you’re stuck with only ¼ of your screen fitting in the maximum viewport, or you have to stuff around with changing screen resolution every time you want to record.

Native Windows 10 Tools

With Windows 10, you can now produce a decent output just using built-in tools in the OS. Some of the features aren’t so obvious though, hence this post to share how I stitch them all together

In most cases, we’ll only be recording a single app – like PowerPoint, or a web browser. These instructions assume that’s the case. If you want to toggle back and forth between multiple apps, then you’ll need to fall back to a third party app like SnagIt or Camtasia.

💭 Give these steps a go as you read through this post. You’ll just record the browser here, but you’ll get to see how it all hangs together.

Quiet Hours

The last thing you need is an awkward IM during your recording. Even if it’s completely innocuous, it’ll make you stumble mid-sentence. Turn on Quiet Hours to silence those notifications.

Quiet Hours.png

You’ll still need to exit non-Store apps, like Outlook and Skype of Business. Until they’re upgraded to the world of UWP, they just blissfully ignore this setting.

Game Bar

Windows 10 includes a built-in Game DVR as part of the Xbox integration. We’re going to trick that into being more broadly useful for us.

First, launch the app you want to record, such as PowerPoint.

Then hit ⌨ Win+G to launch the Xbox Game bar. (G is for Game.)

The first time you do this, poor old Windows is rightly going to be a little confused about you launching the Xbox controls over the top of PowerPoint:

Game bar prompt

Just tick that box to say “Yes, this is a game”, and you’ll get the full set of controls:

Game bar full

And now you know how I unwind of an evening. PowerPoint! Woo!

Start Recording

You’ll need to explicitly tick the “Record mic” box each time, as it’s normally optimised just to record the game audio, and not the user.

Then, just hit the big, red, record button. 🔴

The Game bar won’t be part of the recording, so don’t worry if it sticks around on the screen.

Sometimes, the “Record mic” box unchecks itself again after you start recording. Double check that it’s still checked (filled in) before you power into your recording.

Clear Audio

We’re not aiming for TV broadcast quality here, but we do want to get decent audio that’s not going to annoy listeners. With a few simple tips, you can usually achieve that without buying a special mic or stapling egg cartons to the wall.

Aim for a larger room, preferably with softer furnishings. In an office, this is probably a larger boardroom with the blinds down. At home, it’s probably your bedroom (seriously, the blankets and pillows are perfect!). A small meeting room isn’t a deal breaker, but it’ll definitely sound like you’re talking in a bucket.

Start off by clearing your throat, then saying something at a normal volume. “Hi, I’m talking to myself”. Pause for a few seconds, then start your actual content. This technique will cause the automatic volume levelling on your mic to kick in and sort itself out. We’ll trim this off later.

Sit central to the laptop that you’re recording on. Most modern laptops have stereo microphones in them, so if you talk at it side-on then your audience will only hear you side-on.

Keep the energy up. The normal pacing techniques that you’d use for a live presentation don’t apply here; they just leave people to get distracted. If it feels like you’re racing through your content and talking too fast, then it’s probably about right.

Stop Recording

Leave at last a few seconds of silence at the end. There’s no rush to stop the recording, because we’ll trim the end anyway.

If the Game bar is still on screen, you can just click the Stop button.

If it disappeared, press Win+G again to bring it back first.

Recording Location

You’ll find the recording under Videos, then Captures.

My Computer Videos

While it was recording, Windows was just focussed on capturing everything really quickly. It didn’t want to use up CPU cycles that might cause a hiccup to the game that we were playing. As a result, the file will be huge, because it hasn’t been optimised at all. We’ll fix that next.

Trim + Optimize

Right click the video, then Open With > Photos. Yes, really, the Photos app, not the Film & TV app. That’s because the Photos app includes a video trimming tool:

Photos Trim.png

Even the smallest amount of trimming will let you then save a new copy of the video:

Photos Save a Copy

This time, Windows will work harder to generate a much smaller file. For recordings of slides and apps, you’ll generally see the file size reduce by 95% or more, which makes it immensely easier to distribute.

The smaller file will appear in the Captures folder, next to the original.

Three Takes Tops

Screencasts should be easy and natural for you to produce, so don’t make them a big event.

I like to restrict myself to three takes max:

  1. The first one is just a test. I know I’ll throw it away. It’s useful to test the audio, mumble my way through the slides, and think about what I’m going to say.
  2. The second take might be real. I try for it to be real. If I say ‘um’ or ‘ah’, it’s ok – it’s natural speaking style – and I keep going. I definitely try not to say ‘oh crap, I totally stuffed it’ because that just completely trashes the recording and forces you to restart. If this take is good enough, then we’re done and dusted. More often than not though, I stuff this one up majorly by getting slides in the wrong order, or getting my message wrong.
  3. The third take must be real. Any more effort than this is too much effort.

This means than a 10 minutes presentation should take ~30 mins to record. I usually book out an hour, so that I then have time left to upload the recording to Office 365 Video and post it out to Yammer.

No doubt, your first few attempts will take a bit longer while you’re learning both the tools and the style. That’s ok; just avoid getting stuck in infinite takes. Once you hit about five takes in a single sitting, it’s time to pack it up and take a break. Your voice will need a rest, and you’ll likely be muddled up about what points you have or haven’t said in any given take.

Disable Game Bar

While the game mode is enabled, even when you’re not recording, PowerPoint is running in a bit of an odd state that it’s not used to. Your whole PC will probably feel a bit sluggish.

To disable it again:

  1. Return to PowerPoint (or whatever app you were recording)
  2. Hit ⌨ Win+G to launch the Game bar again
  3. Click Settings
  4. Untick “Remember this as a game”

Then, your PC will be as good as it was to begin with.

Companion planting for the optimal garden, in Windows 10

We’re in the transition seasons in both hemispheres right now: autumn in the south, and spring in the north. This is a good time to establish a new crop of plants before the conditions get too harsh in the peak seasons.

In our house, we wanted to replace the under-loved front courtyard with a basic vegetable garden that will produce some winter greens. We’re only talking about a small urban space here, but it’s amazing how much you can produce from that, and just how much it improves the look of the space.

First, we built a simple raised bed: 1.8m x 1.4m, and around 20cm deep. Minimal tools were required, as the hardware store cut the wood to size for us, so we just had to screw some brackets into each corner and dig them in with a basic hand trowel. We covered the existing dirt with some soaked cardboard as a weed and nutrient barrier before loading in the new potting mix (80%) and manure (20%).

2017-02-05 17.33.29.jpg

The next challenge was to work out what plants we wanted. We had an idea – leafy winter greens – however garden bed planning always runs into a challenge when you consider companions and enemies. Companion planting is especially important in shared beds, where plants can compete with each other, send each other out of balance, or strive for success together.

This process has always been quite manual and annoying. As soon as you start reading about one plant, you’ll quickly find that it’s not compatible with something else you had planned, and it’s back to rearranging everything again. My mother has slowly compiled the Excel-sheet-to-end-all-Excel-sheets, saving on browser-tab-fatigue, however it’s still a laborious process to apply to a brand new garden. (And that’s if you even know everything you want to plant in the first place!)

Of course, the solution was to pause here and build a simple Windows 10 app:

2017-02-27 Screenshot v1.2

Get it on Windows 10

As you drag-and-drop plants onto the bed planner, the app constantly recalculates what will and won’t be compatible.

The list of potential plants is automatically sorted to hint “Great Companions” and “Good Companions” first, and push those sneaky enemies to the bottom of the queue.

This also means that you can use it somewhat like Spotify Radio: just pick one plant you really want (say, basil), and drag it on to the bed planner. The list of potential plants will instantly suggest capsicum or tomatoes as the ideal plants to add next. Just keep adding from the top of the list and you’ll have a perfect garden in no time.

It also renders basic sizing and spacing information, so you can get an idea of what will actually fit in your space.

With the app built, our optimum winter garden is now well on its way to success. Hopefully yours can be too!

2017-02-25 18.12.02

⚠ Action Required: Revisit your Skype account security

The Really Really Short Version

If you don’t have time to read the full post below, these are the minimum steps you should follow to secure your Skype account:

  1. Visit https://account.microsoft.com
  2. If already signed in, sign out
  3. Sign in with your Skype account (old Skype username, not email or phone number)
  4. Follow the bouncing ball to completion

For the most complete fix, and a little background, read on.

Continue reading “⚠ Action Required: Revisit your Skype account security”

How Azure Directory (AAD) and VS Team Services (VSTS) relate to Azure Subscriptions

I recently received a question along the lines of “I’m a co-admin on an Azure subscription, so I should have access to everything, but I can’t modify the directory. Why not?”

Here was my answer:

Azure Subscriptions are a billing and security container.

Azure Subscriptions contain resources like blob containers, VMs, etc.

Azure Directory is an identity container.

Azure Directories can:

  • Define a user account (org id)
  • Reference a user account from another directory (foreign principal org id)
  • Reference a Microsoft Account

An Azure Directory is not a resource. It lives outside the subscription, on its own.

Every Azure Subscription is linked to an Azure Directory as the place that it reads its identities from.

“Co-owner” is a security role applied at the Azure Subscription level, granting control of the resources within that subscription.

Generally, we should be granting less co-admin rights in the old portal, and focussing on RBAC-based grants in the new portal instead. (They’re more finely grained, to a specific resource, resource group, or set of actions.)

Because an Azure Directory is not a resource, and does not live in the subscription, the co-owner concept does not apply to it.

“User administrator” and “Global administrator” are security roles applied at the Azure Directory level. They relate only to the directory, and not any linked subscriptions.

VSTS Accounts are another stand-alone entity.

A VSTS Account can be linked to an Azure Subscription, so that charges can flow to the Azure subscription. If it is not linked, then there’s no way to use any paid services (as VSTS doesn’t have its own commerce system).

A VSTS Account can be linked to an Azure Directory. This is essentially like “domain joining” a PC; it opts you into a number of management advantages. If it is not linked, then you can only use Microsoft Accounts for sign-in, and it essentially maintains its own lightweight identity store in lieu of the directory.

All Azure Subscriptions are part of an Azure Account. This is where the billing information is maintained.

All Azure Accounts have a Service Administrator and an Account Owner. These are security roles applied at the Account level. They do not grant any rights into the subscriptions, directories, or VSTS accounts (as they are all different, independent entities).

When you login to https://portal.azure.com, you login with an identity that’s in the context of a directory. You can see your current directory context top-right. You will see the different resources which are within subscriptions that are linked to your current directory. You may have no subscriptions at all, in which case you just see the directory but an otherwise empty portal.

When you login to https://manage.windowsazure.com, you must always be in the context of a subscription. (Old portal, old rules.) You will see all of the directories that you have access to as a user, regardless of which subscription context you’re in. Even if you have access to a directory, but you are just lacking a subscription, they will boot you out of the portal with an error about having no subscriptions. To work around this, we grant everybody at Readify co-admin access to an “Authentication Helper” subscription. It’s empty, but it lets you login with your OrgId and then swap to the other directory that you were actually looking for. I really dislike the old portal.

Clear as mud? 🙂

Software still at the heart of IoT

Earlier today, I was quoted in Drew Turney‘s Tech giants get ready for Internet of Things operating systems article for The Age.

The article explores the relevance of ‘dedicated’ IoT systems, like GE’s Predix.

I’d like to expand on this quote:

“The opportunity of IoT lies in integrating physical intelligence right through to business processes, and back out again”

Much of the current discussion around IoT is focussed on cheap sensors, platform interoperability, and data analytics. These are all important building blocks, but they don’t really talk to the power of IoT for me.

We’ve spent two decades mashing up databases. Disconnected datasets now annoy even our least technical friends.

We spent the last decade mashing up web services. It’s mind boggling that I can add a high-quality, interactive map with global coverage straight into an app, and then spend longer trying to generate all the different icon sizes required to publish it.

We’ll spend this decade mashing up the physical world. We’re nearing the point that it’s as easy to connect to your toothbrush as it is to connect to a web service.

Software remains at the heart of all this: it’s just that we can now reach further than ever before. Rather than waiting for input data, we can just go and get it. Rather than sending an alert, we can just go and start/stop/repair/move/etc. whatever we need to.

Separately, it was encouraging to see security raised several times. A device that’s too small and dumb to run the math required for encryption is probably not something to be exposed to the public internet.

And of course, it’s always nice to see Readify’s name alongside the likes of Intel, GE, and CSIRO. 🙂

Make one thing better, starting with your bed.

U.S. Navy Admiral Bill McRaven:

It was a simple task — mundane at best. But every morning we were required to make our bed to perfection. It seemed a little ridiculous at the time, particularly in light of the fact that were aspiring to be real warriors, tough battle hardened SEALs — but the wisdom of this simple act has been proven to me many times over. If you make your bed every morning you will have accomplished the first task of the day. It will give you a small sense of pride and it will encourage you to do another task and another and another. By the end of the day, that one task completed will have turned into many tasks completed. Making your bed will also reinforce the fact that little things in life matter. If you can’t do the little things right, you will never do the big things right. And, if by chance you have a miserable day, you will come home to a bed that is made — that you made — and a made bed gives you encouragement that tomorrow will be better. If you want to change the world, start off by making your bed.

Source: http://www.businessinsider.com.au/bill-mcraven-commencement-speech-at-ut-2014-5

Trialling Vame.me

Readify is a very culturally diverse organisation: a quick scan of my inbox right now shows names like Korczynski, Mutandwa, Shah, Saikovski and The. “Tatham” isn’t exactly simple either. We’re also distributed across many different client sites spread around the country, which means a lot of our conversation is via email.

I recently came across an Aussie startup called Vame.me, via a Shoestring article. I’m a sucker for well implemented simple ideas, so I gave it a go.

This is what my email signature now looks like, with an extra “Listen” link:

Tatham Oddie (Listen) | Readify Chief Information Officer | m +61 123 456 789 | tatham.oddie@readify.net | w readify.net

I like it, not because I’m precious about my own name (I’m really not), but because I like knowing how to pronounce other peoples’. There’s been a bit of adoption across Readify already, and I look forward to seeing it grow.

It’s hard to really tell how useful it is, as it’s not the type of thing people really call out a lot. I have been tracking click-throughs though, and it’s getting a few.

PS. If you’re wondering, here’s how you pronounce “The”: http://vame.me/ericthe

Nerd Corner: Convert a Mercurial (Hg) repo to Git, with full fidelity, on any OS

Fortunately or unfortunately, Git won over Mercurial. I placed a few bets on Mercurial at the time, so I have a bit of a tail of repositories left to convert.

Converting on Windows with full fidelity isn’t really possible. None of the scripts work well, and the case insensitive file system can cause issues. Luckily, Windows Azure makes it super easy to borrow a small Linux instance quickly.

I’ve documented what I do in this post. Anybody with a web browser can follow these steps, on any platform. There looks like a lot of steps, but that’s just because I’m spelling out every last detail for clarity.

Create a Linux VM in Windows Azure

  1. Sign in to https://manage.windowsazure.com
  2. Create a new VM from the gallery:
    Create VM from Gallery
  3. Choose an Ubuntu release. As of this post, I chose Ubuntu Server 13.10.
  4. Name the VM anything you want
  5. Untick “Upload compatible SSH key for authentication”, unless you know what you’re doing there
  6. Tick “Provide a password”
  7. Leave all the rest of the defaults, and just keep clicking Next
  8. Wait a moment for the VM to get provisioned

Connect to the VM

For this, we’ll just be connecting to a command line via SSH: no GUIs will be harmed.

Because SSH is so prevalent, there are tool chains available for every platform. I’m actually writing this post on my Surface RT (not Pro), using an app called SSH-RT from the Windows Store.

  1. Connect to the DNS name for your new VM (mine was git-convert.cloudapp.net)
  2. Use the username and password you established during the wizard
  3. You should now be at a command line like azureuser@git-convert:~$

Install Git and Hg on the VM

Ubuntu doesn’t ship with Git or Mercurial installed by default, but it does have an awesome package manager called apt-get.

  1. Run sudo apt-get install git
  2. Run sudo apt-get install mercurial

The sudo prefix is a command to elevate your permissions, kind of like a UAC prompt on Windows.

Clone hg-fast-export on to the VM

We’ll be using a tool called hg-fast-export to convert the Mercurial repository to Git, without having to replay each individual changeset like some tools do. This tool is in a Git repo, so we’ll just clone that repository down in order to get it onto the VM.

  1. Run git clone https://github.com/frej/fast-export.git

Clone your Mercurial repository on to the VM

For the sake of simplicity, we’re just going to use HTTPS instead of SSH.

  1. Run hg clone https://your/hg/repo/address

Export your Mercurial repository to a new Git one

  1. Create a new folder for your Git repository: mkdir your-repo-git
  2. Change to that folder: cd your-repo-git
  3. Initialize an empty Git repository there: git init
  4. Do the fast export: ../fast-export/hg-fast-export.sh -r ../your-repo/

Upload your Git repository to your Git hosting

  1. Add the remote: git remote add origin https://your/git/repo/address
  2. Push up all branches and tags: git push -u origin --all

Convert Hg-specifc config to Git

Take the opportunity now to convert your .hgignore file to an equivalent .gitignore one. You can go and do this back on your own machine.

Delete the VM

Back in the Azure Management Console, delete the VM. When you do this, choose to “delete the attached disks”. (It will ask you.)

All done!

You’re all done. Wasn’t that just a perfect, easy use of the cloud?