Just what *is* the /.default scope in the Microsoft identity platform & Azure AD?
Tags: azure, azuread, identity, security
Published: 2020-09-30 15:56:10

{% youtube BBQWSksJ7nY?t=44m26s %}

_We talked about this in our last community hours. Check out the video above!_

If you’ve ever worked with the Microsoft identity platform (aka Azure AD, aka Azure AD B2C), there is a good chance that you have had to work with scopes, including the `/.default` scope. In this blog post, we’re going to cover some of the basics and explain what the `/.default` scope is, when to use it and why.

## Quick background

When we need to connect to APIs or services secured with OAuth2 (called _resources_ in openid and oauth parlance), such as the [Microsoft Graph API](http://aka.ms/ge), Azure APIs, third-party APIs or our own APIs, we need to request an access token for that resource. For Microsoft services, the vast majority are secured with Azure AD, meaning you'll need to get tokens from Azure AD in order to use those services from your applications.

> Sometimes OAuth2 is referred to as 'Bearer Authentication' - this is due to how we use the token with a resource: it's put into the `Authorization` HTTP header with a value of `Bearer <access_token value>`

When users sign-in to your app, Azure AD sends you back an `id_token`, which proves their identity to _your application_ – but when your application also needs to connect to a resource, we need an access token specifically for that resource. In short, the `id_token`is for your application to use, while the `access_token` is for you to send to other resources (APIs) your app is using.

## Scopes & permissions

Scopes can be thought of as permissions within a resource – for example, Microsoft Graph exposes Office 365 scopes like `Mail.Read` (read the user’s mail) or `Files.Read` (read the user’s OneDrive files). In this case, the _resource_ is `https://graph.microsoft.com` while the permission is `Mail.Read`. Putting these together gives us our full _scope_: `https://graph.microsoft.com/Mail.Read`.

Once we know our scope, we need to ask the user if it's ok to use that scope. This is called _consent_. If the user consents to `https://graph.microsoft.com/Mail.Read`, our application will get an access token it can use to read a user’s mailbox.

You can think of it like permissions on your phone – when you install a new app, most smartphones will say "This app would like to use your location. Is that OK?"

![03-phone-perm](https://dev-to-uploads.s3.amazonaws.com/i/gdme3e3xdulzl5q9197n.png)

What makes scopes so useful in building user trust is that our users can allow other apps to access their data without having to give those other apps full access to everything. In my phone example, if I grant app ABC access to my location, that’s all the app receives – it can’t also read my contacts, for example, unless the app asks and the user allows that to happen.

## Let's order some business cards!

Imagine we’ve built an app that handles ordering business cards.   

It would be really helpful to pre-populate the user’s info in the card, so we request the `User.Read` permission from **Microsoft Graph**. This includes profile information like their display name, email address, etc.   

> If you're keeping score at home, that means we'll need this scope: `https://graph.microsoft.com/User.Read`

But we also want to give them an option to save their design, or upload a custom design. We implement a normal file picker so a user can upload from their PC, but wouldn’t it be cool to offer upload and download from **OneDrive** or a **SharePoint site**? To do that, we will need the `Files.ReadWrite` and `Sites.ReadWrite.All` permissions. 

> Now our scope list is:
- `https://graph.microsoft.com/User.Read`
- `https://graph.microsoft.com/Files.ReadWrite`
- `https://graph.microsoft.com/Sites.ReadWrite.All`

Remember, however - not all users will want to do this. Some users won't have a OneDrive or Sharepoint site, other users may have all of their files locally.

> Sample of users actually using these permissions:
- `https://graph.microsoft.com/User.Read`: this is for signing into the app - 100% of users will use this
- `https://graph.microsoft.com/Files.ReadWrite`: this is for accessing OneDrive - say, 40% of users will do this
- `https://graph.microsoft.com/Sites.ReadWrite.All`: this is for accessing a SharePoint site - we'll estimate 10% of users want to do this

In Azure AD v1 (which you may also hear being referred to as ‘the v1 endpoint’), we had to add all the permissions we needed upfront - configured on the App Registration in Azure AD. This meant users would also need to allow those permissions upfront, just to sign-in to our app. This is called *‘static consent’*. Let's see what that looks like:

![dev-view](https://dev-to-uploads.s3.amazonaws.com/i/grmoycrr259nyx7qyes8.jpg)
<figcaption>Developer/admin view</figcaption>

Meanwhile, this is what your users will see when signing into the app:

![02-consent-screen](https://dev-to-uploads.s3.amazonaws.com/i/e51613aiw5k2f5790nlb.jpg)
<figcaption>What your users will see</figcaption>

Whoa! That's a lot of permissions. I just wanted to order some business cards, but now I'm being asked to let this app I've never used write to my files? Access sharepoint sites? No way, I'm outta here - I'll go order business cards somewhere else.

![blocks](https://dev-to-uploads.s3.amazonaws.com/i/tyrewb074k5hju00xiqw.gif)
<figcaption>Not today</figcaption>

If the user *does* allow those permissions, it means your application is going to have permission to read a user’s files, even if you never need to read their files! Not particularly optimal for our app or our users.

## Dynamic consent

The Azure AD v2 (aka Microsoft identity platform, aka ‘the v2 endpoint’) scope & permission system fixes this, by allowing *dynamic consent* – instead of requiring the developers to declare all permissions upfront, v2 allows developers to ask at any time. In our business card example, this means a user is only asked to consent to their profile data being read on sign-in, while users who elect to 'upload a custom design from OneDrive' (by clicking a button in your app, etc) will be prompted for the `Files.Read` permission when they perform the action. Better for our users, better for us as the developer 😊

![v2-consent](https://dev-to-uploads.s3.amazonaws.com/i/mburgmmuh88i9e0yr796.jpg)
<figcaption>Much better</figcaption> 

## /.default  

Now that we’ve written two pages of what got us here, let’s get to the point of this post – the `/.default` scope. The short description is the `/.default` scope is a shortcut back to the Azure AD v1 behavior (e.g., static consent). When we request a `/.default` scope (for example, `https: //graph.microsoft.com/.default`), our users will be asked to consent to all of the configured permissions present on our Azure AD App Registration for that specific resource (e.g., https: //graph.microsoft.com). 

In our business card example, this means that a user would be prompted to consent to all permissions we’ve configured upfront.

For migrating old apps that currently use Azure AD v1 (including apps that use ADAL, the Active Directory Authentication Library), the `/.default` scope offers an easier migration path, as the developer gets the same behavior from the v2 endpoint keeping the experience consistent.

## When **must** I use the /.default scope? 

There are two extra scenarios where the `/.default` scope is required:  

- [**`client_credentials`**](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow), where our app is making service-to-service calls or using application-only permissions (also known as application app roles in Azure AD parlance), or

- when using the [**`on-behalf-of`** (OBO) flow](https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-on-behalf-of-flow), where our API is making calls on behalf of the user to a different API; something like this: client app --> our API --> Graph API.

In both scenarios above, there is no user interface and no user interaction. In the `client_credentials` case, an application is using its own identity (not that of a user), so there is no concept of dynamic consent, as the application must statically configure the permissions that it needs - who would it ask for extra permission at runtime if there is no user present?

`on-behalf-of` (OBO) is similar; since the backend API is making a request to another API, there is no user interface for asking for additional permissions, so permissions must be set statically between APIs. This means that your scopes in token requests for service-to-service and on-behalf-of flows must use a scope of `your-app-id-uri/.default` – e.g., https: //graph.microsoft.com/.default, or https: //your-app.your-co.com/.default.  

You can read up more on the official doc about /.default, scopes & consent here: [Microsoft identity platform scopes, permissions, and consent]( https://docs.microsoft.com/azure/active-directory/develop/v2-permissions-and-consent).

Check us out live Tuesdays & Thursdays at 10a ET, 7a PT at https://aka.ms/425show!