Skip to content

Managing incremental consent and conditional access

Jean-Marc Prieur edited this page Jul 27, 2020 · 40 revisions

Incremental consent and conditional access: they require user interaction

Incremental consent and static permissions

Incremental consent

The Microsoft identity platform allows users to incrementally consent to your application access more resources / web APIs on their behalf (that is to consent to more scopes) as they are needed. This is named incremental consent. This means that, in a Web app a controller action could require some scopes, and then another controller action could require more scopes, and this will trigger an interaction with the user of the web application so that they consent for these new scopes.

Case of user flow in B2C

If you're building an Azure AD B2C application and use several user flows, you'll also need to handle incremental consent as interaction will be required with the user.

Static permissions

You can also decide to not handle incremental consent. In that case you define the permissions at app registration, and have the tenant administrator consent to them all (admin consent). Then, as you request tokens, you'll can use the {resource}/.default syntax to get an access token for all pre-approved scopes for this given resource. You can also request specific pre-approved scopes if you wish.

If, at some point, your app requests more scopes than what the admin has consented, you'll receive an MsalUiRequiredException, and you'll know that you need to have more scopes pre-approved by the tenant admin.

If you are a Microsoft employee building an first party application, static permissions are the way to go.

Conditional access

It can also happen that, when requesting a token to call a (downstream) web API, your web app or web API receives a claims challenge exception instructing the app that the user needs to provide more claims (for instance the user needs to perform multi factor authentication). This happens for some specific web APIs for which the tenant administrator had added conditional access policies. From your point of view, as an application developer, this looks the same as handing incremental consent: the user needs will get through a consent screen, which will trigger more user flows, such as performing multi-factor authentication.

You can choose to not handle incremental consent, however, you should not choose not to handle conditional access, as your web app / API could be broken in the future if install in tenants where the tenant admins decide to enable conditional access.

How to handle them: this depends on your type of app / technology

The way for your app to handle conditional access and incremental consent is different depending on if you are building:

  • a Web app (where interaction is possible with the user),
  • or a web API (where interaction is not possible, and therefore where the information needs to be propagated back to the client).

For web apps, it's also different depending if you implement an ASP.NET Core MVC controller, a Blazor page, or a Razor page.

Handling incremental consent or conditional access in web apps

In MVC controllers

In MVC controllers, you'll need to use the [AuthorizeForScopes] attribute on each controller action.

[Authorize]
public class HomeController : Controller
{
 private readonly ITokenAcquisition _tokenAcquisition;

 public HomeController(ITokenAcquisition tokenAcquisition)
 {
  _tokenAcquisition = tokenAcquisition;
 }

 [AuthorizeForScopes(ScopeKeySection = "CalledApi:CalledApiScopes")]
 public async Task<IActionResult> Index()
 {
  var accessToken = tokenAcquisition.GetAccessTokenForUserAsync(new string[] {"user.read"});
  // Call API
  return View();
 }
}

Alternatively, you can specify the scopes in the appsetttings.json file:

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    // more here
  },
  "CalledApi": {
    /*
     'CalledApiScopes' contains space separated scopes of the Web API you want to call. This can be:
      - a scope for a V2 application (for instance api:b3682cc7-8b30-4bd2-aaba-080c6bf0fd31/access_as_user)
      - a scope corresponding to a V1 application (for instance <App ID URI>/.default, where  <App ID URI> is the
        App ID URI of a legacy v1 Web application
      Applications are registered in the https:portal.azure.com portal.
    */
    "CalledApiScopes": "user.read",
    "CalledApiUrl": "https://graph.microsoft.com/v1.0"
  },
 [AuthorizeForScopes(ScopeKeySection = "CalledApi:CalledApiScopes")]
 public async Task<IActionResult> Index()
 {
  var accessToken = tokenAcquisition.GetAccessTokenForUserAsync(new string[] {"user.read"});
  // Call API
  return View();
 }

In Razor pages

In MVC controllers, you'll need to use the [AuthorizeForScopes] attribute on the class representing the Razor page.

In Blazor

In Blazor, you'll need to inject a service, and catch the exceptions so that the user is re-signed-in and consents / performs conditional access

Handling incremental consent or conditional access in web APIs

In a Web API, your controller action will need to explicity call ITokenAcquisition.WwwAuthenticate

Getting started with Microsoft Identity Web

Token cache serialization

Web apps

Web APIs

Daemon scenario

Advanced topics

FAQ

News

Contribute

Other resources

Clone this wiki locally