-
Notifications
You must be signed in to change notification settings - Fork 219
1.2.0
Microsoft Identity Web 1.2.0 brings new features:
- You can now specify scopes and app-permissions for the injected GraphServiceClient
- You can use new strongly typed comfort methods for IDownstreamWebAPI
- Web apps integrated with Azure App Services authentication are now supported with no code change
- you web API called by daemon apps can now be protected by ACLs instead of app roles
- apps called by ajax calls can now participate in incremental consent and conditional access
- Back channel proxys for the issuer validator metadata are now supported
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 theRequest()
. For instance:var users = await _graphServiceClient.Users .Request() .WithScopes("User.Read.All") .GetAsync(); NumberOfUsers = messages.Count;
-
specify that you want to use app permissions (that is https://graph.microsoft.com/.default) by using
.WithAppOnly()
after theRequest()
. For instance:var apps = await _graphServiceClient.Applications .Request() .WithAppOnly() .GetAsync(); 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.
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.
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
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
.
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.
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 'https://login.microsoftonline.com/..........' (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.
Until 1.2.0, back channel proxys were not applied to access the metadata at login.microsoft.com (or in general the authority), leading to an error like the following: Exception: IDX20804: Unable to retrieve document from: 'https://login.microsoftonline.com/common/discovery/instance?authorization_endpoint=https://login.microsoftonline.com/common/oauth2/v2.0/authorize&api-version=1.1'.
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:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(Configuration, "AzureAd")
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();
// Configure your proxy
services.Configure<AadIssuerValidatorOptions>(options => options.HttpClientName = "proxyedClient")
.AddHttpClient("proxyedClient", c =>
{
// configure your Http Client here.
});
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.
- Home
- Why use Microsoft Identity Web?
- Web apps
- Web APIs
- Using certificates
- Minimal support for .NET FW Classic
- Logging
- Azure AD B2C limitations
- Samples
- Web apps
- Web app samples
- Web app template
- Call an API from a web app
- Managing incremental consent and conditional access
- Web app troubleshooting
- Deploy to App Services Linux containers or with proxies
- SameSite cookies
- Hybrid SPA
- Web APIs
- Web API samples
- Web API template
- Call an API from a web API
- Token Decryption
- Web API troubleshooting
- web API protected by ACLs instead of app roles
- gRPC apps
- Azure Functions
- Long running processes in web APIs
- Authorization policies
- Generic API
- Customization
- Logging
- Calling graph with specific scopes/tenant
- Multiple Authentication Schemes
- Utility classes
- Setting FIC+MSI
- Mixing web app and web API
- Deploying to Azure App Services
- Azure AD B2C issuer claim support
- Performance
- specify Microsoft Graph scopes and app-permissions
- Integrate with Azure App Services authentication
- Ajax calls and incremental consent and conditional access
- Back channel proxys
- Client capabilities