Skip to content
Alexander Batishchev edited this page Mar 9, 2021 · 27 revisions

Getting started with Microsoft Identity Web

Token cache serialization

Web apps

Web APIs

Daemon scenario

Advanced topics




Other resources

Clone this wiki locally

Microsoft Identity Web 1.2.0 releases

Microsoft Identity Web 1.2.0 brings new features:

You can now specify scopes and app-permissions for GraphServiceClient

When you want to call Microsoft.Graph from your web app or web API, you need to:

  • specify AddMicrosoftGraph in the startup.cs
  • inject GraphServiceClient in the controller, or Razor page or Blazor page.

When you call AddMicrosoftGraph, you specify (by configuration or programmatically) the scopes to request initially. Until Microsoft.Identity.Web 1.2.0, you could not request more scopes when using a GraphServiceClient query, and you could not specify that the query needed app permissions (instead of delegated permissions)

With version 1.2.0, you can now:

  • specify the delegated scopes to use by using .WithScopes(string[]) after the Request(). For instance:

    var users = await _graphServiceClient.Users
    NumberOfUsers = messages.Count;
  • specify that you want to use app permissions (that is by using .WithAppOnly() after the Request(). For instance:

    var apps = await _graphServiceClient.Applications
    NumberOfApps = apps.Count;

    This later case requires the admin to have consented to these app-only permissions

A big thank you to @darrelmiller for providing most of the code for this feature.

Comfort methods for IDownstreamWebAPI

Microsoft.Identity.Web adds new generic extension methods applicable to the IDownstreamWebAPI interface to make it easier to call downstream APIs taking (or not) input parameters, and returning (or not) some output, and with a specified HTTP verb.

HTTP Verb Extension Method
GET with input only GetForUserAsync
GET with output only GetForUserAsync
POST with input and output PostForUserAsync<TOutput, TInput>
PUT with input only PutForUserAsync
PUT with input and output PutForUserAsync<TOutput, TInput>

See TodoListController.cs for an example of how these comfort methods are used to streamline the code in your controllers.

Thank you to @NikolaosWakem, for sharing an initial version of the code for this feature.

Integration with Azure App Services authentication of web Apps running with Microsoft.Identity.Web

When you deploy your app to Azure App Services, until now if you activated the Authentication/Authorization in App Services (EasyAuth), and also had authentication/authorization handled by Microsoft.Identity.Web, this did not work.

From version 1.2.0, the same code for your web app written with Microsoft.Identity.Web will work seamlessly with our without EasyAuth. Your web app can sign-in users and possibly call web APIs or Microsoft Graph. Indeed, Microsoft.Identity.Web now detects that the app is hosted in App Services, and uses that authentication. You can still sign-in users, and you can call web APIs provided you enabled them in App Services. For details on how to do that, see this tutorial: Configure App Service to return a usable access token.

Normally your app should not need to know if it's hosted in App Services with Authentication or not, but if you want to propose a different UI, it can call AppServicesAuthenticationInformation.IsAppServicesAadAuthenticationEnabled to detect it.

Note that when Microsoft.Identity.Web detects EasyAuth, it automatically overrides the default authentication scheme to be AppServicesAuthenticationDefaults.AppServicesAuthenticationDefaults, and uses this scheme instead of the OpenIdConnect scheme. If you configure the OpenIdConnect scheme, you might want to guard this configuration code with tests using AppServicesAuthenticationInformation.IsAppServicesAadAuthenticationEnabled

Possibility to challenge the user to request more scopes and claims

Microsoft.Identity.Web handles claims challenge exceptions automatically (See Handling incremental consent and conditional access for details)

However, in some advanced scenarios, you might need the application to request specific claims (they would still need to be known by Azure AD), you can now specify these claims in the Claims member of the TokenAcquisitionOptions. This request claims from the Microsoft identity platform /Token endpoint.

If you want to proactively request more claims or more scopes from the /Authorize endpoint you can use the ChallengeUser method of the MicrosoftIdentityConsentAndConditionalAccessHandler.

Support for Web API protected by ACLs and called by daemon apps

Daemon applications can validate a token based on application roles, or using the ACL-based authorization pattern to control tokens without a roles claim. To enable the ACL-based authorization, Microsoft Identity Web will no longer throw an exception when neither roles or scopes are not in the Claims provided you instruct it to do so. For this the MicrosoftIdentityOptions have a new boolean property named AllowWebApiToBeAuthorizedByACL which by passes the test for scopes or roles in the token. If you set this property to true in the appsettings.json or programmatically, this is your responsibility to ensure the ACL mechanism.

Ajax calls can now participate in incremental consent and conditional access

Until now, when calling a .NET Core controller action with the AuthorizeForScopes attribute client side from an AJAX call a CORS issue occurred:

Access to XMLHttpRequest at '' (redirected from 'https://localhost:44352/test/testPartialView) from origin 'https://yourhost' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

This occurred when the user's authorization was expired, or incremental consent or conditional access was needed. The controller action was throwing a MsalUiRequiredException which created a request of type "xhr / Redirect" and returned a 302 which resulted in the CORS issue due to the redirect.

Microsoft.Identity.Web 1.2.0 brings support of this scenario by extracting the return url from the ajax custom header tp return to the user agent after the challenge is satisfied.

This is illustrated in the AjaxCallActionsWithDynamicConsent dev app in this repo. See in particular the JavaScript code in index.cshtml

A big thank you @creativebrother for contributing this feature.

Support for back channel proxys for the issuer validator metadata

Support for named HttpClients for issuer validation

Until 1.2.0, back channel proxys were not applied to access the metadata at (or in general the authority), leading to an error like the following: Exception: IDX20804: Unable to retrieve document from: ''.

Microsoft.Identity.Web 1.2.0 a new AadIssuerValidatorOptions which has one property HttpClientName which will allow you to configure the HttpClient used to validate the issuer (and therefore get the authority metadata). Below is the code you'd use in the Startup.cs file, to benefit from this new feature:

        .AddMicrosoftIdentityWebApi(Configuration, "AzureAd") 

// Configure your proxy
services.Configure<AadIssuerValidatorOptions>(options => options.HttpClientName = "proxyedClient")
        .AddHttpClient("proxyedClient", c =>
            // configure your Http Client here.

Consequences on the (undocumented) public API

Part of this effort, Microsoft.Identity.Web 1.2.0 now introduces a singleton service named MicrosoftIdentityIssuerValidatorFactory which is injected by dependency injection. It also deprecates the previous static method AadIssuerValidator.GetIssuerValidator(string aadAuthority with a clear message leading to this blog post.

Disclaimer: If you were using Microsoft.Identity.Web in the way it's presented in the public documentation you won't be impacted. If you were using it in bits and pieces and using the issuer validator explicitly, you'll now have to build a MicrosoftIdentityIssuerValidatorFactory. Because this is not a mainstream scenario, I've made the hard decision of not bumping-up the major number of the library (pushing a major version causes other adoptions issues, and I've supposed that this would not impact many of you), but this is clearly a behavioral breaking change if you were using this (undocumented) feature. Please contact me if this is causing you any issue (@jmprieur). I want to know.