From 2cf1c9a15b33b084103b04b4d120a8f3f1f084c2 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Mon, 3 Aug 2020 21:41:55 +0200 Subject: [PATCH 01/28] Initial commit (does not build) --- .../Microsoft.Identity.Web.csproj | 11 + .../Microsoft.Identity.Web.xml | 503 ++++++------------ .../DistributedTokenCacheAdapterExtension.cs | 8 +- .../InMemoryTokenCacheProviderExtension.cs | 6 +- .../SessionTokenCacheProviderExtension.cs | 4 +- .../MicrosoftWebApiAuthenticationBuilder.cs | 41 ++ .../WebApiAuthenticationBuilderExtensions.cs | 4 +- .../WebApiServiceCollectionExtensions.cs | 5 +- .../MicrosoftWebAppAuthenticationBuilder.cs | 208 ++++++++ .../WebAppAuthenticationBuilderExtensions.cs | 24 +- ...lsWebApiAuthenticationBuilderExtensions.cs | 89 +--- .../WebAppServiceCollectionExtensions.cs | 5 +- tests/B2CWebAppCallsWebApi/Client/Startup.cs | 8 +- .../Client/Startup.cs | 4 +- 14 files changed, 481 insertions(+), 439 deletions(-) create mode 100644 src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs create mode 100644 src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj index 4ff35db9f..75041eaaa 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj @@ -31,6 +31,13 @@ true snupkg + + + + + + + @@ -95,4 +102,8 @@ + + + + diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index dd6b8ec77..66afd7d80 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -716,6 +716,57 @@ OpenID Connect event. A that represents a completed remove from cache operation. + + + Authentication builder specific for Microsoft identity platform. + + + + + Constructor. + + The services being configured. + Defaut scheme used for OpenIdConnect. + Action called to configure + the Microsoft identity options. + + + + The services being configured. + + + + + Add MSAL support to the web app or web API. + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + + The configuration instance. + The name of the configuration section with the necessary + settings to initialize authentication options. + The authentication builder for chaining. + This method cannot be used with Azure AD B2C, as with B2C an initial scope needs + to be provided. + + + + + Add MSAL support to the web app or web API. + + The configuration instance. + Initial scopes to request at sign-in. + The name of the configuration section with the necessary + settings to initialize authentication options. + The authentication builder for chaining. + + + + The Web app calls a web api. + + Initial scopes. + Action to configure the + MSAL.NET confidential client application options. + the builder itself for chaining. + Extensions for IServerSideBlazorBuilder for startup initialization of web APIs. @@ -873,326 +924,6 @@ Exception thrown by MSAL when a user challenge is encountered. Scopes to request. - - - Class used to handle gracefully the obsolete token decryption certificate parameter in - deprecated AddProtectedWebApi methods. - - - - - Extensions for IServiceCollection for startup initialization of Web APIs. - - - Extensions for for startup initialization of web APIs. - - - - - Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - AuthenticationBuilder to which to add this configuration. - The Configuration object. - The configuration section with the necessary settings to initialize authentication options. - The JwtBearer scheme name to be used. By default it uses "Bearer". - Token decryption certificate (null by default). - - Set to true if you want to debug, or just understand the JwtBearer events. - - The authentication builder to chain. - - - - Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - AuthenticationBuilder to which to add this configuration. - The action to configure . - The action to configure the - configuration options. - Token decryption certificate. - The JwtBearer scheme name to be used. By default it uses "Bearer". - - Set to true if you want to debug, or just understand the JwtBearer events. - - The authentication builder to chain. - - - - Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - The to which to add this configuration. - The configuration instance. - The configuration section with the necessary settings to initialize authentication options. - The JWT bearer scheme name to be used. By default it uses "Bearer". - - Set to true if you want to debug, or just understand the JWT bearer events. - - The authentication builder to chain. - - - - Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0). - - The to which to add this configuration. - The action to configure . - The action to configure the . - The JWT bearer scheme name to be used. By default it uses "Bearer". - - Set to true if you want to debug, or just understand the JWT bearer events. - The authentication builder to chain. - - - - Extensions for IServiceCollection for startup initialization of Web APIs. - - - Extension for IServiceCollection for startup initialization of Web APIs. - - - - - Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - Service collection to which to add authentication. - The Configuration object. - The configuration section with the necessary settings to initialize authentication options. - The JwtBearer scheme name to be used. By default it uses "Bearer". - Token decryption certificate (null by default). - - Set to true if you want to debug, or just understand the JwtBearer events. - - The service collection to chain. - - - - Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - Service collection to which to add authentication. - The action to configure . - The action to configure . - Token decryption certificate (null by default). - The JwtBearer scheme name to be used. By default it uses "Bearer". - - Set to true if you want to debug, or just understand the JwtBearer events. - - The service collection to chain. - - - - Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) - This supposes that the configuration files have a section named configSectionName (typically "AzureAD"). - - Service collection to which to add authentication. - Configuration. - Section name in the config file (by default "AzureAD"). - Scheme for the JwtBearer token. - The service collection to chain. - - - - Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) - This supposes that the configuration files have a section named configSectionName (typically "AzureAD"). - - Service collection to which to add authentication. - The action to configure . - The action to configure . - Scheme for the JwtBearer token. - The service collection to chain. - - - - Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - Service collection to which to add authentication. - The Configuration object. - The configuration section with the necessary settings to initialize authentication options. - The JwtBearer scheme name to be used. By default it uses "Bearer". - - Set to true if you want to debug, or just understand the JwtBearer events. - The authentication builder to chain extension methods. - - - - Extensions for IServiceCollection for startup initialization of Web APIs. - - - Extensions for the for startup initialization. - - - - - Add authentication with Microsoft identity platform. - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - AuthenticationBuilder to which to add this configuration. - The IConfiguration object. - The configuration section with the necessary settings to initialize authentication options. - The OpenIdConnect scheme name to be used. By default it uses "OpenIdConnect". - The Cookies scheme name to be used. By default it uses "Cookies". - - Set to true if you want to debug, or just understand the OpenIdConnect events. - - The authentication builder for chaining. - - - - Add authentication with Microsoft identity platform. - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - AuthenticationBuilder to which to add this configuration. - The IConfiguration object. - The configuration section with the necessary settings to initialize authentication options. - The OpenIdConnect scheme name to be used. By default it uses "OpenIdConnect". - The Cookies scheme name to be used. By default it uses "Cookies". - - Set to true if you want to debug, or just understand the OpenIdConnect events. - - The authentication builder for chaining. - - - - Add authentication with Microsoft identity platform. - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - The to which to add this configuration. - The configuration instance. - The configuration section with the necessary settings to initialize authentication options. - The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". - The cookie-based scheme name to be used. By default it uses "Cookies". - - Set to true if you want to debug, or just understand the OpenID Connect events. - - The authentication builder for chaining. - - - - Add authentication with Microsoft identity platform. - - The to which to add this configuration. - The action to configure . - The action to configure . - The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". - The cookie-based scheme name to be used. By default it uses "Cookies". - - Set to true if you want to debug, or just understand the OpenID Connect events. - - The authentication builder for chaining. - - - - Extensions for IServiceCollection for startup initialization. - - - Extension for IServiceCollection for startup initialization. - - - - - Add authentication with Microsoft identity platform. - This method expects the configuration file will have a section, (by default named "AzureAd"), with the necessary settings to - initialize the authentication options. - - Service collection to which to add authentication. - The IConfiguration object. - The name of the configuration section with the necessary - settings to initialize authentication options. - Optional name for the open id connect authentication scheme - (by default OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support - several OpenIdConnect identity providers. - Optional name for the cookie authentication scheme - (by default OpenIdConnectDefaults.AuthenticationScheme). - - Set to true if you want to debug, or just understand the OpenIdConnect events. - - The service collection for chaining. - - - - Add authentication with Microsoft identity platform. - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - Service collection to which to add authentication. - the action to configure the . - the action to configure the . - Optional name for the open id connect authentication scheme - (by default OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support - several OpenIdConnect identity providers. - Optional name for the cookie authentication scheme - (by default OpenIdConnectDefaults.AuthenticationScheme). - - Set to true if you want to debug, or just understand the OpenIdConnect events. - - The service collection for chaining. - - - - Enable Web Apps to call APIs (acquiring tokens with MSAL.NET). - - Service collection to which to add authentication. - Configuration. - The name of the configuration section with the necessary - settings to initialize authentication options. - Optional name for the open id connect authentication scheme - (by default OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support - several OpenIdConnect identity providers. - The service collection for chaining. - This method cannot be used with Azure AD B2C as, with B2C an initial scope needs - to be provided. - - - - - Enable Web Apps to call APIs (acquiring tokens with MSAL.NET). - - Service collection to which to add authentication. - Configuration. - Initial scopes to request at sign-in. - The name of the configuration section with the necessary - settings to initialize authentication options. - Optional name for the open id connect authentication scheme - (by default OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support - several OpenIdConnect identity providers. - The service collection for chaining. - - - - Enable Web Apps to call APIs (acquiring tokens with MSAL.NET). - - Service collection to which to add authentication. - Initial scopes to request at sign-in. - The action to set the . - The action to set the . - Optional name for the open id connect authentication scheme - (by default OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support - several OpenIdConnect identity providers. - The service collection for chaining. - - - - Add authentication with Microsoft identity platform. - This method expects the configuration file will have a section, (by default named "AzureAd"), with the necessary settings to - initialize the authentication options. - - Service collection to which to add authentication. - The IConfiguration object. - The name of the configuration section with the necessary - settings to initialize authentication options. - Optional name for the open id connect authentication scheme - (by default OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support - several OpenIdConnect identity providers. - Optional name for the cookie authentication scheme - (by default OpenIdConnectDefaults.AuthenticationScheme). - - Set to true if you want to debug, or just understand the OpenIdConnect events. - - The authentication builder to chain extension methods. - Generic class that validates token issuer from the provided Azure AD authority. @@ -1213,7 +944,7 @@ - Validate the issuer for multi-tenant applications of various audience (Work and School account, or Work and School accounts + + Validate the issuer for multi-tenant applications of various audiences (Work and School accounts, or Work and School accounts + Personal accounts). Issuer to validate (will be tenanted). @@ -1226,12 +957,12 @@ The issuer if it's valid, or otherwise SecurityTokenInvalidIssuerException is thrown. if is null. if is null. - if the issuer. + if the issuer is invalid. Gets the tenant ID from a token. A JWT token. - A string containing tenant ID, if found or . + A string containing the tenant ID, if found or . Only and are acceptable types. @@ -1541,7 +1272,7 @@ . Claims principal for the user on behalf of whom to get a token. Scopes for the downstream API to call. - (optional) Specific tenant for which to acquire a token to access the scopes + (optional) Authority based on a specific tenant for which to acquire a token to access the scopes on behalf of the user described in the claimsPrincipal. Azure AD B2C user flow to target. @@ -1553,7 +1284,7 @@ User IAccount for which to acquire a token. See . Scopes for the downstream API to call. - Specific tenant for which to acquire a token to access the scopes + Authority based on a specific tenant for which to acquire a token to access the scopes on behalf of the user. Azure AD B2C user flow. @@ -1577,10 +1308,10 @@ The services collection to add to. A to chain. - + Adds both the app and per-user .NET Core distributed based token caches. The Authentication builder to add to. - A to chain. + A to chain. Adds the .NET Core distributed cache based app token cache to the service collection. @@ -1676,7 +1407,7 @@ The services collection to add to. the services (for chaining). - + Adds both the app and per-user in-memory token caches. The authentication builder to add to. the builder (for chaining). @@ -1885,7 +1616,7 @@ The services collection to add to. The service collection. - + Adds both application and per-user session token caches. @@ -1957,6 +1688,37 @@ The services collection to add to. The service collection. + + + Extensions for for startup initialization of web APIs. + + + + + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + + The to which to add this configuration. + The configuration instance. + The configuration section with the necessary settings to initialize authentication options. + The JWT bearer scheme name to be used. By default it uses "Bearer". + + Set to true if you want to debug, or just understand the JWT bearer events. + + The authentication builder to chain. + + + + Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0). + + The to which to add this configuration. + The action to configure . + The action to configure the . + The JWT bearer scheme name to be used. By default it uses "Bearer". + + Set to true if you want to debug, or just understand the JWT bearer events. + The authentication builder to chain. + Extensions for for startup initialization of web APIs. @@ -1983,12 +1745,64 @@ The scheme for the JWT bearer token. The authentication builder to chain. + + + Extension for IServiceCollection for startup initialization of Web APIs. + + + + + Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + + Service collection to which to add authentication. + The Configuration object. + The configuration section with the necessary settings to initialize authentication options. + The JwtBearer scheme name to be used. By default it uses "Bearer". + + Set to true if you want to debug, or just understand the JwtBearer events. + The authentication builder to chain extension methods. + + + + Extensions for the for startup initialization. + + + + + Add authentication with Microsoft identity platform. + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + + The to which to add this configuration. + The configuration instance. + The configuration section with the necessary settings to initialize authentication options. + The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". + The cookie-based scheme name to be used. By default it uses "Cookies". + + Set to true if you want to debug, or just understand the OpenID Connect events. + + The authentication builder for chaining. + + + + Add authentication with Microsoft identity platform. + + The to which to add this configuration. + The action to configure . + The action to configure . + The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". + The cookie-based scheme name to be used. By default it uses "Cookies". + + Set to true if you want to debug, or just understand the OpenID Connect events. + + The authentication builder for chaining. + Extensions for for startup initialization. - + Add MSAL support to the web app or web API. This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. @@ -2005,7 +1819,7 @@ to be provided. - + Add MSAL support to the web app or web API. @@ -2019,7 +1833,7 @@ several OpenID Connect identity providers. The authentication builder for chaining. - + Add MSAL support to the web app or web API. @@ -2032,5 +1846,30 @@ several OpenID Connect identity providers. The authentication builder for chaining. + + + Extension for IServiceCollection for startup initialization. + + + + + Add authentication with Microsoft identity platform. + This method expects the configuration file will have a section, (by default named "AzureAd"), with the necessary settings to + initialize the authentication options. + + Service collection to which to add authentication. + The IConfiguration object. + The name of the configuration section with the necessary + settings to initialize authentication options. + Optional name for the open id connect authentication scheme + (by default OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support + several OpenIdConnect identity providers. + Optional name for the cookie authentication scheme + (by default OpenIdConnectDefaults.AuthenticationScheme). + + Set to true if you want to debug, or just understand the OpenIdConnect events. + + The authentication builder to chain extension methods. + diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs index c72c8091c..f1a5d3312 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs @@ -15,7 +15,7 @@ public static class DistributedTokenCacheAdapterExtension /// Adds both the app and per-user in-memory token caches. /// The services collection to add to. /// A to chain. - public static IServiceCollection AddDistributedTokenCaches( + internal static IServiceCollection AddDistributedTokenCaches( this IServiceCollection services) { AddDistributedAppTokenCache(services); @@ -25,9 +25,9 @@ public static IServiceCollection AddDistributedTokenCaches( /// Adds both the app and per-user .NET Core distributed based token caches. /// The Authentication builder to add to. - /// A to chain. - public static AuthenticationBuilder AddDistributedTokenCaches( - this AuthenticationBuilder builder) + /// A to chain. + public static MicrosoftWebAppAuthenticationBuilder AddDistributedTokenCaches( + this MicrosoftWebAppAuthenticationBuilder builder) { if (builder == null) { diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs index 52b9b23f9..0d1e85758 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs @@ -15,7 +15,7 @@ public static class InMemoryTokenCacheProviderExtension /// Adds both the app and per-user in-memory token caches. /// The services collection to add to. /// the services (for chaining). - public static IServiceCollection AddInMemoryTokenCaches( + internal static IServiceCollection AddInMemoryTokenCaches( this IServiceCollection services) { if (services == null) @@ -32,8 +32,8 @@ public static IServiceCollection AddInMemoryTokenCaches( /// Adds both the app and per-user in-memory token caches. /// The authentication builder to add to. /// the builder (for chaining). - public static AuthenticationBuilder AddInMemoryTokenCaches( - this AuthenticationBuilder builder) + public static MicrosoftWebAppAuthenticationBuilder AddInMemoryTokenCaches( + this MicrosoftWebAppAuthenticationBuilder builder) { if (builder == null) { diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs index 685ecf43a..76e6dce7c 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs @@ -38,7 +38,7 @@ public static class SessionTokenCacheProviderExtension /// /// The services collection to add to. /// The service collection. - public static IServiceCollection AddSessionTokenCaches(this IServiceCollection services) + internal static IServiceCollection AddSessionTokenCaches(this IServiceCollection services) { if (services == null) { @@ -103,7 +103,7 @@ public static IServiceCollection AddSessionTokenCaches(this IServiceCollection s /// /// The authentication builder to add the session token caches to. /// The builder to chain more commands. - public static AuthenticationBuilder AddSessionTokenCaches(this AuthenticationBuilder builder) + public static MicrosoftWebAppAuthenticationBuilder AddSessionTokenCaches(this MicrosoftWebAppAuthenticationBuilder builder) { if (builder == null) { diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs new file mode 100644 index 000000000..013a0d4eb --- /dev/null +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs @@ -0,0 +1,41 @@ +using System; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Identity.Web +{ + public class MicrosoftWebApiAuthenticationBuilder + { + /// + /// Constructor. + /// + /// The services being configured. + /// Defaut scheme used for OpenIdConnect. + /// Action called to configure + /// the Microsoft identity options. + internal MicrosoftWebApiAuthenticationBuilder( + IServiceCollection services, + string jwtBearerAuthenticationScheme, + Action configureMicrosoftIdentityOptions) + { + Services = services; + _jwtBearerAuthenticationScheme = jwtBearerAuthenticationScheme; + _configureMicrosoftIdentityOptions = configureMicrosoftIdentityOptions; + + if (_configureMicrosoftIdentityOptions == null) + { + throw new ArgumentNullException(nameof(configureMicrosoftIdentityOptions)); + } + } + + /// + /// The services being configured. + /// + public virtual IServiceCollection Services { get; private set; } + + private Action _configureMicrosoftIdentityOptions { get; set; } + + private string _jwtBearerAuthenticationScheme { get; set; } + + MicrosoftWebApiAuthenticationBuilder CallWebApi(); + } +} diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs index 37f9d2e90..b8091c370 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs @@ -31,7 +31,7 @@ public static partial class WebApiAuthenticationBuilderExtensions /// Set to true if you want to debug, or just understand the JWT bearer events. /// /// The authentication builder to chain. - public static AuthenticationBuilder AddMicrosoftWebApi( + public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApi( this AuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -55,7 +55,7 @@ public static AuthenticationBuilder AddMicrosoftWebApi( /// /// Set to true if you want to debug, or just understand the JWT bearer events. /// The authentication builder to chain. - public static AuthenticationBuilder AddMicrosoftWebApi( + public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApi( this AuthenticationBuilder builder, Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions, diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs index 44e56bcc3..4084f6b33 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs @@ -24,7 +24,7 @@ public static partial class WebApiServiceCollectionExtensions /// /// Set to true if you want to debug, or just understand the JwtBearer events. /// The authentication builder to chain extension methods. - public static AuthenticationBuilder AddMicrosoftWebApiAuthentication( + public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApiAuthentication( this IServiceCollection services, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -32,12 +32,11 @@ public static AuthenticationBuilder AddMicrosoftWebApiAuthentication( bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) { AuthenticationBuilder builder = services.AddAuthentication(jwtBearerScheme); - builder.AddMicrosoftWebApi( + return builder.AddMicrosoftWebApi( configuration, configSectionName, jwtBearerScheme, subscribeToJwtBearerMiddlewareDiagnosticsEvents); - return builder; } } } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs new file mode 100644 index 000000000..a46b951e0 --- /dev/null +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs @@ -0,0 +1,208 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Identity.Client; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; + +namespace Microsoft.Identity.Web +{ + /// + /// Authentication builder specific for Microsoft identity platform. + /// + public class MicrosoftWebAppAuthenticationBuilder + { + /// + /// Constructor. + /// + /// The services being configured. + /// Defaut scheme used for OpenIdConnect. + /// Action called to configure + /// the Microsoft identity options. + internal MicrosoftWebAppAuthenticationBuilder( + IServiceCollection services, + string openIdConnectScheme, + Action configureMicrosoftIdentityOptions) + { + Services = services; + _openIdConnectScheme = openIdConnectScheme; + _configureMicrosoftIdentityOptions = configureMicrosoftIdentityOptions; + + if (_configureMicrosoftIdentityOptions == null) + { + throw new ArgumentNullException(nameof(configureMicrosoftIdentityOptions)); + } + } + + /// + /// The services being configured. + /// + public virtual IServiceCollection Services { get; private set; } + + private Action _configureMicrosoftIdentityOptions { get; set; } + + private string _openIdConnectScheme { get; set; } + + internal IConfigurationSection? ConfigurationSection { get; set; } + + /// + /// Add MSAL support to the web app or web API. + /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + /// + /// The configuration instance. + /// The name of the configuration section with the necessary + /// settings to initialize authentication options. + /// The authentication builder for chaining. + /// This method cannot be used with Azure AD B2C, as with B2C an initial scope needs + /// to be provided. + /// + public MicrosoftWebAppAuthenticationBuilder CallsWebApi() + { + return CallsWebApi(null); + } + + /// + /// Add MSAL support to the web app or web API. + /// + /// The configuration instance. + /// Initial scopes to request at sign-in. + /// The name of the configuration section with the necessary + /// settings to initialize authentication options. + /// The authentication builder for chaining. + [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] + public MicrosoftWebAppAuthenticationBuilder CallsWebApi( + IEnumerable initialScopes) + { + return CallsWebApi( + initialScopes, + options => ConfigurationSection.Bind(options)); + } + + /// + /// Add MSAL support to the web app or web API. + /// + /// The configuration section instance from which to extract the values + /// + /// Initial scopes to request at sign-in. + /// The name of the configuration section with the necessary + /// settings to initialize authentication options. + /// The authentication builder for chaining. + [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] + public MicrosoftWebAppAuthenticationBuilder CallsWebApi( + IConfigurationSection configurationSection, + IEnumerable initialScopes) + { + return CallsWebApi( + initialScopes, + options => configurationSection.Bind(options)); + } + + /// + /// The Web app calls a web api. + /// + /// Initial scopes. + /// Action to configure the + /// MSAL.NET confidential client application options. + /// the builder itself for chaining. + public MicrosoftWebAppAuthenticationBuilder CallsWebApi( + IEnumerable? initialScopes, + Action configureConfidentialClientApplicationOptions) + { + if (configureConfidentialClientApplicationOptions == null) + { + throw new ArgumentNullException(nameof(configureConfidentialClientApplicationOptions)); + } + + CallsWebApiImplementation( + Services, + initialScopes, + _configureMicrosoftIdentityOptions, + _openIdConnectScheme, + configureConfidentialClientApplicationOptions); + return this; + } + + internal static void CallsWebApiImplementation( + IServiceCollection services, + IEnumerable? initialScopes, + Action configureMicrosoftIdentityOptions, + string openIdConnectScheme, + Action configureConfidentialClientApplicationOptions) + { + // Ensure that configuration options for MSAL.NET, HttpContext accessor and the Token acquisition service + // (encapsulating MSAL.NET) are available through dependency injection + services.Configure(configureMicrosoftIdentityOptions); + services.Configure(configureConfidentialClientApplicationOptions); + + services.AddHttpContextAccessor(); + + services.AddTokenAcquisition(); + + services.AddOptions(openIdConnectScheme) + .Configure((options, serviceProvider) => + { + options.ResponseType = OpenIdConnectResponseType.CodeIdToken; + + // This scope is needed to get a refresh token when users sign-in with their Microsoft personal accounts + // It's required by MSAL.NET and automatically provided when users sign-in with work or school accounts + options.Scope.Add(OidcConstants.ScopeOfflineAccess); + if (initialScopes != null) + { + foreach (string scope in initialScopes) + { + if (!options.Scope.Contains(scope)) + { + options.Scope.Add(scope); + } + } + } + + // Handling the auth redemption by MSAL.NET so that a token is available in the token cache + // where it will be usable from Controllers later (through the TokenAcquisition service) + var codeReceivedHandler = options.Events.OnAuthorizationCodeReceived; + options.Events.OnAuthorizationCodeReceived = async context => + { + var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService(); + await tokenAcquisition.AddAccountToCacheFromAuthorizationCodeAsync(context, options.Scope).ConfigureAwait(false); + await codeReceivedHandler(context).ConfigureAwait(false); + }; + + // Handling the token validated to get the client_info for cases where tenantId is not present (example: B2C) + var onTokenValidatedHandler = options.Events.OnTokenValidated; + options.Events.OnTokenValidated = async context => + { + string? clientInfo = context.ProtocolMessage?.GetParameter(ClaimConstants.ClientInfo); + + if (!string.IsNullOrEmpty(clientInfo)) + { + ClientInfo? clientInfoFromServer = ClientInfo.CreateFromJson(clientInfo); + + if (clientInfoFromServer != null) + { + context.Principal.Identities.FirstOrDefault()?.AddClaim(new Claim(ClaimConstants.UniqueTenantIdentifier, clientInfoFromServer.UniqueTenantIdentifier)); + context.Principal.Identities.FirstOrDefault()?.AddClaim(new Claim(ClaimConstants.UniqueObjectIdentifier, clientInfoFromServer.UniqueObjectIdentifier)); + } + } + + await onTokenValidatedHandler(context).ConfigureAwait(false); + }; + + // Handling the sign-out: removing the account from MSAL.NET cache + var signOutHandler = options.Events.OnRedirectToIdentityProviderForSignOut; + options.Events.OnRedirectToIdentityProviderForSignOut = async context => + { + // Remove the account from MSAL.NET token cache + var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService(); + await tokenAcquisition.RemoveAccountAsync(context).ConfigureAwait(false); + await signOutHandler(context).ConfigureAwait(false); + }; + }); + } + } +} diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs index 19c79aeb1..38539b5f5 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs @@ -33,19 +33,23 @@ public static partial class WebAppAuthenticationBuilderExtensions /// Set to true if you want to debug, or just understand the OpenID Connect events. /// /// The authentication builder for chaining. - public static AuthenticationBuilder AddMicrosoftWebApp( + public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( this AuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, string openIdConnectScheme = OpenIdConnectDefaults.AuthenticationScheme, string cookieScheme = CookieAuthenticationDefaults.AuthenticationScheme, - bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false) => - builder.AddMicrosoftWebApp( - options => configuration.Bind(configSectionName, options), - null, - openIdConnectScheme, - cookieScheme, - subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); + bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false) + { + var microsoftWebAppAuthenticationBuilder = builder.AddMicrosoftWebApp( + options => configuration.Bind(configSectionName, options), + null, + openIdConnectScheme, + cookieScheme, + subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); + microsoftWebAppAuthenticationBuilder.ConfigurationSection = configuration.GetSection(configSectionName); + return microsoftWebAppAuthenticationBuilder; + } /// /// Add authentication with Microsoft identity platform. @@ -59,7 +63,7 @@ public static AuthenticationBuilder AddMicrosoftWebApp( /// Set to true if you want to debug, or just understand the OpenID Connect events. /// /// The authentication builder for chaining. - public static AuthenticationBuilder AddMicrosoftWebApp( + public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( this AuthenticationBuilder builder, Action configureMicrosoftIdentityOptions, Action? configureCookieAuthenticationOptions = null, @@ -187,7 +191,7 @@ public static AuthenticationBuilder AddMicrosoftWebApp( } }); - return builder; + return new MicrosoftWebAppAuthenticationBuilder(builder.Services, openIdConnectScheme, configureMicrosoftIdentityOptions); } internal static void PopulateOpenIdOptionsFromMicrosoftIdentityOptions(OpenIdConnectOptions options, MicrosoftIdentityOptions microsoftIdentityOptions) diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs index db794f4ff..949d5d20f 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs @@ -35,8 +35,9 @@ public static class WebAppCallsWebApiAuthenticationBuilderExtensions /// This method cannot be used with Azure AD B2C, as with B2C an initial scope needs /// to be provided. /// - public static AuthenticationBuilder AddMicrosoftWebAppCallsWebApi( - this AuthenticationBuilder builder, + [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] + public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( + this MicrosoftWebAppAuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, string openIdConnectScheme = OpenIdConnectDefaults.AuthenticationScheme) @@ -60,8 +61,9 @@ public static AuthenticationBuilder AddMicrosoftWebAppCallsWebApi( /// (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support /// several OpenID Connect identity providers. /// The authentication builder for chaining. - public static AuthenticationBuilder AddMicrosoftWebAppCallsWebApi( - this AuthenticationBuilder builder, + [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] + public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( + this MicrosoftWebAppAuthenticationBuilder builder, IConfiguration configuration, IEnumerable initialScopes, string configSectionName = Constants.AzureAd, @@ -85,8 +87,9 @@ public static AuthenticationBuilder AddMicrosoftWebAppCallsWebApi( /// (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support /// several OpenID Connect identity providers. /// The authentication builder for chaining. - public static AuthenticationBuilder AddMicrosoftWebAppCallsWebApi( - this AuthenticationBuilder builder, + [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] + public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( + this MicrosoftWebAppAuthenticationBuilder builder, IEnumerable? initialScopes, Action configureMicrosoftIdentityOptions, Action configureConfidentialClientApplicationOptions, @@ -107,74 +110,12 @@ public static AuthenticationBuilder AddMicrosoftWebAppCallsWebApi( throw new ArgumentNullException(nameof(configureConfidentialClientApplicationOptions)); } - // Ensure that configuration options for MSAL.NET, HttpContext accessor and the Token acquisition service - // (encapsulating MSAL.NET) are available through dependency injection - builder.Services.Configure(configureMicrosoftIdentityOptions); - builder.Services.Configure(configureConfidentialClientApplicationOptions); - - builder.Services.AddHttpContextAccessor(); - - builder.Services.AddTokenAcquisition(); - - builder.Services.AddOptions(openIdConnectScheme) - .Configure((options, serviceProvider) => - { - options.ResponseType = OpenIdConnectResponseType.CodeIdToken; - - // This scope is needed to get a refresh token when users sign-in with their Microsoft personal accounts - // It's required by MSAL.NET and automatically provided when users sign-in with work or school accounts - options.Scope.Add(OidcConstants.ScopeOfflineAccess); - if (initialScopes != null) - { - foreach (string scope in initialScopes) - { - if (!options.Scope.Contains(scope)) - { - options.Scope.Add(scope); - } - } - } - - // Handling the auth redemption by MSAL.NET so that a token is available in the token cache - // where it will be usable from Controllers later (through the TokenAcquisition service) - var codeReceivedHandler = options.Events.OnAuthorizationCodeReceived; - options.Events.OnAuthorizationCodeReceived = async context => - { - var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService(); - await tokenAcquisition.AddAccountToCacheFromAuthorizationCodeAsync(context, options.Scope).ConfigureAwait(false); - await codeReceivedHandler(context).ConfigureAwait(false); - }; - - // Handling the token validated to get the client_info for cases where tenantId is not present (example: B2C) - var onTokenValidatedHandler = options.Events.OnTokenValidated; - options.Events.OnTokenValidated = async context => - { - string? clientInfo = context.ProtocolMessage?.GetParameter(ClaimConstants.ClientInfo); - - if (!string.IsNullOrEmpty(clientInfo)) - { - ClientInfo? clientInfoFromServer = ClientInfo.CreateFromJson(clientInfo); - - if (clientInfoFromServer != null) - { - context.Principal.Identities.FirstOrDefault()?.AddClaim(new Claim(ClaimConstants.UniqueTenantIdentifier, clientInfoFromServer.UniqueTenantIdentifier)); - context.Principal.Identities.FirstOrDefault()?.AddClaim(new Claim(ClaimConstants.UniqueObjectIdentifier, clientInfoFromServer.UniqueObjectIdentifier)); - } - } - - await onTokenValidatedHandler(context).ConfigureAwait(false); - }; - - // Handling the sign-out: removing the account from MSAL.NET cache - var signOutHandler = options.Events.OnRedirectToIdentityProviderForSignOut; - options.Events.OnRedirectToIdentityProviderForSignOut = async context => - { - // Remove the account from MSAL.NET token cache - var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService(); - await tokenAcquisition.RemoveAccountAsync(context).ConfigureAwait(false); - await signOutHandler(context).ConfigureAwait(false); - }; - }); + MicrosoftWebAppAuthenticationBuilder.CallsWebApiImplementation( + builder.Services, + initialScopes, + configureMicrosoftIdentityOptions, + openIdConnectScheme, + configureConfidentialClientApplicationOptions); return builder; } } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs index 7bb647db6..ec3377191 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs @@ -32,7 +32,7 @@ public static partial class WebAppServiceCollectionExtensions /// Set to true if you want to debug, or just understand the OpenIdConnect events. /// /// The authentication builder to chain extension methods. - public static AuthenticationBuilder AddMicrosoftWebAppAuthentication( + public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppAuthentication( this IServiceCollection services, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -41,13 +41,12 @@ public static AuthenticationBuilder AddMicrosoftWebAppAuthentication( bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false) { AuthenticationBuilder builder = services.AddAuthentication(openIdConnectScheme); - builder.AddMicrosoftWebApp( + return builder.AddMicrosoftWebApp( options => configuration.Bind(configSectionName, options), null, openIdConnectScheme, cookieScheme, subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); - return builder; } } } diff --git a/tests/B2CWebAppCallsWebApi/Client/Startup.cs b/tests/B2CWebAppCallsWebApi/Client/Startup.cs index a271f4ff0..5df7aa1a5 100644 --- a/tests/B2CWebAppCallsWebApi/Client/Startup.cs +++ b/tests/B2CWebAppCallsWebApi/Client/Startup.cs @@ -44,10 +44,10 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftWebApp(Configuration, "AzureAdB2C") - .AddMicrosoftWebAppCallsWebApi(Configuration, - initialScopes: new string[] { Configuration["TodoList:TodoListScope"] }, - configSectionName: "AzureAdB2C"); - services.AddInMemoryTokenCaches(); + .CallsWebApi(Configuration, + initialScopes: new string[] { Configuration["TodoList:TodoListScope"] }, + configSectionName: "AzureAdB2C") + .AddInMemoryTokenCaches(); // Add APIs services.AddTodoListService(Configuration); diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs index b0829e20c..7ae957983 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs @@ -45,8 +45,8 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftWebApp(Configuration, "AzureAd") - .AddMicrosoftWebAppCallsWebApi(Configuration); - services.AddInMemoryTokenCaches(); + .CallsWebApi(Configuration) + .AddInMemoryTokenCaches(); // Add APIs services.AddTodoListService(Configuration); From b6dcf59afc10273b5ece74c12c62baa5328b081e Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Tue, 4 Aug 2020 02:15:22 +0200 Subject: [PATCH 02/28] Updating Web API. Todo: - see if we could have some commonalities between the Web app and Web API builder (configuration?) - Enfoce configuration for CallsWebAPI can only be called if configuration for the AddMicrosoftWebApp/Api --- .../Microsoft.Identity.Web.xml | 139 ++++++++++-------- .../InMemoryTokenCacheProviderExtension.cs | 15 ++ .../MicrosoftWebApiAuthenticationBuilder.cs | 93 +++++++++++- .../WebApiAuthenticationBuilderExtensions.cs | 25 +++- ...lsWebApiAuthenticationBuilderExtensions.cs | 24 +-- .../MicrosoftWebAppAuthenticationBuilder.cs | 57 ++----- .../WebAppAuthenticationBuilderExtensions.cs | 10 ++ tests/B2CWebAppCallsWebApi/Client/Startup.cs | 4 +- tests/BlazorServerCallsGraph/Startup.cs | 11 +- tests/WebAppCallsMicrosoftGraph/Startup.cs | 4 +- .../Client/Startup.cs | 2 +- .../TodoListService/Startup.cs | 4 +- 12 files changed, 240 insertions(+), 148 deletions(-) diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 66afd7d80..3d9d76011 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -716,57 +716,6 @@ OpenID Connect event. A that represents a completed remove from cache operation. - - - Authentication builder specific for Microsoft identity platform. - - - - - Constructor. - - The services being configured. - Defaut scheme used for OpenIdConnect. - Action called to configure - the Microsoft identity options. - - - - The services being configured. - - - - - Add MSAL support to the web app or web API. - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - The configuration instance. - The name of the configuration section with the necessary - settings to initialize authentication options. - The authentication builder for chaining. - This method cannot be used with Azure AD B2C, as with B2C an initial scope needs - to be provided. - - - - - Add MSAL support to the web app or web API. - - The configuration instance. - Initial scopes to request at sign-in. - The name of the configuration section with the necessary - settings to initialize authentication options. - The authentication builder for chaining. - - - - The Web app calls a web api. - - Initial scopes. - Action to configure the - MSAL.NET confidential client application options. - the builder itself for chaining. - Extensions for IServerSideBlazorBuilder for startup initialization of web APIs. @@ -1308,10 +1257,10 @@ The services collection to add to. A to chain. - + Adds both the app and per-user .NET Core distributed based token caches. The Authentication builder to add to. - A to chain. + A to chain. Adds the .NET Core distributed cache based app token cache to the service collection. @@ -1407,7 +1356,12 @@ The services collection to add to. the services (for chaining). - + + Adds both the app and per-user in-memory token caches. + The authentication builder to add to. + the builder (for chaining). + + Adds both the app and per-user in-memory token caches. The authentication builder to add to. the builder (for chaining). @@ -1616,7 +1570,7 @@ The services collection to add to. The service collection. - + Adds both application and per-user session token caches. @@ -1688,6 +1642,40 @@ The services collection to add to. The service collection. + + + Authentication builder for a web API. + + + + + Constructor. + + The services being configured. + Defaut scheme used for OpenIdConnect. + ACtion called to configure the JwtBearer options. + Action called to configure + the Microsoft identity options. + + + + The services being configured. + + + + + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + + The authentication builder to chain. + + + + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + + The action to configure . + The authentication builder to chain. + Extensions for for startup initialization of web APIs. @@ -1763,6 +1751,41 @@ Set to true if you want to debug, or just understand the JwtBearer events. The authentication builder to chain extension methods. + + + Authentication builder specific for Microsoft identity platform. + + + + + Constructor. + + The services being configured. + Defaut scheme used for OpenIdConnect. + Action called to configure + the Microsoft identity options. + + + + The services being configured. + + + + + Add MSAL support to the web app or web API. + + Optional initial scopes to request. + The authentication builder for chaining. + + + + The Web app calls a web api. + + Initial scopes. + Action to configure the + MSAL.NET confidential client application options. + the builder itself for chaining. + Extensions for the for startup initialization. @@ -1802,7 +1825,7 @@ Extensions for for startup initialization. - + Add MSAL support to the web app or web API. This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. @@ -1819,7 +1842,7 @@ to be provided. - + Add MSAL support to the web app or web API. @@ -1833,7 +1856,7 @@ several OpenID Connect identity providers. The authentication builder for chaining. - + Add MSAL support to the web app or web API. diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs index 0d1e85758..bb996c51d 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs @@ -43,5 +43,20 @@ public static MicrosoftWebAppAuthenticationBuilder AddInMemoryTokenCaches( builder.Services.AddInMemoryTokenCaches(); return builder; } + + /// Adds both the app and per-user in-memory token caches. + /// The authentication builder to add to. + /// the builder (for chaining). + public static MicrosoftWebApiAuthenticationBuilder AddInMemoryTokenCaches( + this MicrosoftWebApiAuthenticationBuilder builder) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + builder.Services.AddInMemoryTokenCaches(); + return builder; + } } } diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs index 013a0d4eb..a0daf3a9e 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs @@ -1,8 +1,18 @@ -using System; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IdentityModel.Tokens.Jwt; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Identity.Client; namespace Microsoft.Identity.Web { + /// + /// Authentication builder for a web API. + /// public class MicrosoftWebApiAuthenticationBuilder { /// @@ -10,21 +20,31 @@ public class MicrosoftWebApiAuthenticationBuilder /// /// The services being configured. /// Defaut scheme used for OpenIdConnect. + /// ACtion called to configure the JwtBearer options. /// Action called to configure /// the Microsoft identity options. internal MicrosoftWebApiAuthenticationBuilder( IServiceCollection services, string jwtBearerAuthenticationScheme, + Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions) { Services = services; - _jwtBearerAuthenticationScheme = jwtBearerAuthenticationScheme; - _configureMicrosoftIdentityOptions = configureMicrosoftIdentityOptions; + JwtBearerAuthenticationScheme = jwtBearerAuthenticationScheme; + ConfigureJwtBearerOptions = configureJwtBearerOptions; + ConfigureMicrosoftIdentityOptions = configureMicrosoftIdentityOptions; + + if (ConfigureMicrosoftIdentityOptions == null) + { + throw new ArgumentNullException(nameof(configureMicrosoftIdentityOptions)); + } - if (_configureMicrosoftIdentityOptions == null) + if (ConfigureJwtBearerOptions == null) { throw new ArgumentNullException(nameof(configureMicrosoftIdentityOptions)); } + + Services.Configure(configureMicrosoftIdentityOptions); } /// @@ -32,10 +52,69 @@ internal MicrosoftWebApiAuthenticationBuilder( /// public virtual IServiceCollection Services { get; private set; } - private Action _configureMicrosoftIdentityOptions { get; set; } + private Action ConfigureMicrosoftIdentityOptions { get; set; } + + private string JwtBearerAuthenticationScheme { get; set; } + + private Action ConfigureJwtBearerOptions { get; set; } + + internal IConfigurationSection? ConfigurationSection { get; set; } + + /// + /// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + /// + /// The authentication builder to chain. + public MicrosoftWebApiAuthenticationBuilder CallsWebApi() + { + return CallsWebApi(options => ConfigurationSection.Bind(options)); + } + + /// + /// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + /// + /// The action to configure . + /// The authentication builder to chain. + public MicrosoftWebApiAuthenticationBuilder CallsWebApi( + Action configureConfidentialClientApplicationOptions) + { + if (configureConfidentialClientApplicationOptions == null) + { + throw new ArgumentNullException(nameof(configureConfidentialClientApplicationOptions)); + } + + CallsWebApiImplementation( + Services, + JwtBearerAuthenticationScheme, + configureConfidentialClientApplicationOptions); - private string _jwtBearerAuthenticationScheme { get; set; } + return this; + } - MicrosoftWebApiAuthenticationBuilder CallWebApi(); + internal static void CallsWebApiImplementation( + IServiceCollection services, + string jwtBearerAuthenticationScheme, + Action configureConfidentialClientApplicationOptions) + { + services.Configure(configureConfidentialClientApplicationOptions); + + services.AddTokenAcquisition(); + services.AddHttpContextAccessor(); + + services.AddOptions(jwtBearerAuthenticationScheme) + .Configure((options, serviceProvider) => + { + options.Events ??= new JwtBearerEvents(); + + var onTokenValidatedHandler = options.Events.OnTokenValidated; + + options.Events.OnTokenValidated = async context => + { + await onTokenValidatedHandler(context).ConfigureAwait(false); + context.HttpContext.StoreTokenUsedToCallWebAPI(context.SecurityToken as JwtSecurityToken); + context.Success(); + }; + }); + } } } diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs index b8091c370..3ecec0466 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs @@ -38,11 +38,24 @@ public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApi( string jwtBearerScheme = JwtBearerDefaults.AuthenticationScheme, bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) { - return builder.AddMicrosoftWebApi( - options => configuration.Bind(configSectionName, options), - options => configuration.Bind(configSectionName, options), + if (configuration == null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + if (configSectionName == null) + { + throw new ArgumentNullException(nameof(configSectionName)); + } + + IConfigurationSection configurationSection = configuration.GetSection(configSectionName); + var microsoftWebApiAuthenticationBuilder = builder.AddMicrosoftWebApi( + options => configurationSection.Bind(options), + options => configurationSection.Bind(options), jwtBearerScheme, subscribeToJwtBearerMiddlewareDiagnosticsEvents); + microsoftWebApiAuthenticationBuilder.ConfigurationSection = configurationSection; + return microsoftWebApiAuthenticationBuilder; } /// @@ -158,7 +171,11 @@ public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApi( } }); - return builder; + return new MicrosoftWebApiAuthenticationBuilder( + builder.Services, + jwtBearerScheme, + configureJwtBearerOptions, + configureMicrosoftIdentityOptions); } } } diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiCallsWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiCallsWebApiAuthenticationBuilderExtensions.cs index 5e67e4d72..6e2a1c94f 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiCallsWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiCallsWebApiAuthenticationBuilderExtensions.cs @@ -26,6 +26,7 @@ public static partial class WebApiCallsWebApiAuthenticationBuilderExtensions /// The section name in the config file (by default "AzureAd"). /// The scheme for the JWT bearer token. /// The authentication builder to chain. + [Obsolete("Rather use MicrosoftWebApiAuthenticationBuilder.CallsWebApi")] public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( this AuthenticationBuilder builder, IConfiguration configuration, @@ -46,6 +47,7 @@ public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( /// The action to configure . /// The scheme for the JWT bearer token. /// The authentication builder to chain. + [Obsolete("Rather use MicrosoftWebApiAuthenticationBuilder.CallsWebApi")] public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( this AuthenticationBuilder builder, Action configureConfidentialClientApplicationOptions, @@ -67,26 +69,12 @@ public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( throw new ArgumentNullException(nameof(configureMicrosoftIdentityOptions)); } - builder.Services.Configure(configureConfidentialClientApplicationOptions); builder.Services.Configure(configureMicrosoftIdentityOptions); - builder.Services.AddTokenAcquisition(); - builder.Services.AddHttpContextAccessor(); - - builder.Services.AddOptions(jwtBearerScheme) - .Configure((options, serviceProvider) => - { - options.Events ??= new JwtBearerEvents(); - - var onTokenValidatedHandler = options.Events.OnTokenValidated; - - options.Events.OnTokenValidated = async context => - { - await onTokenValidatedHandler(context).ConfigureAwait(false); - context.HttpContext.StoreTokenUsedToCallWebAPI(context.SecurityToken as JwtSecurityToken); - context.Success(); - }; - }); + MicrosoftWebApiAuthenticationBuilder.CallsWebApiImplementation( + builder.Services, + jwtBearerScheme, + configureConfidentialClientApplicationOptions); return builder; } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs index a46b951e0..4fc3fe9d8 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs @@ -31,10 +31,10 @@ internal MicrosoftWebAppAuthenticationBuilder( Action configureMicrosoftIdentityOptions) { Services = services; - _openIdConnectScheme = openIdConnectScheme; - _configureMicrosoftIdentityOptions = configureMicrosoftIdentityOptions; + OpenIdConnectScheme = openIdConnectScheme; + ConfigureMicrosoftIdentityOptions = configureMicrosoftIdentityOptions; - if (_configureMicrosoftIdentityOptions == null) + if (ConfigureMicrosoftIdentityOptions == null) { throw new ArgumentNullException(nameof(configureMicrosoftIdentityOptions)); } @@ -45,64 +45,25 @@ internal MicrosoftWebAppAuthenticationBuilder( /// public virtual IServiceCollection Services { get; private set; } - private Action _configureMicrosoftIdentityOptions { get; set; } + private Action ConfigureMicrosoftIdentityOptions { get; set; } - private string _openIdConnectScheme { get; set; } + private string OpenIdConnectScheme { get; set; } internal IConfigurationSection? ConfigurationSection { get; set; } /// /// Add MSAL support to the web app or web API. - /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. /// - /// The configuration instance. - /// The name of the configuration section with the necessary - /// settings to initialize authentication options. + /// Optional initial scopes to request. /// The authentication builder for chaining. - /// This method cannot be used with Azure AD B2C, as with B2C an initial scope needs - /// to be provided. - /// - public MicrosoftWebAppAuthenticationBuilder CallsWebApi() - { - return CallsWebApi(null); - } - - /// - /// Add MSAL support to the web app or web API. - /// - /// The configuration instance. - /// Initial scopes to request at sign-in. - /// The name of the configuration section with the necessary - /// settings to initialize authentication options. - /// The authentication builder for chaining. - [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] public MicrosoftWebAppAuthenticationBuilder CallsWebApi( - IEnumerable initialScopes) + IEnumerable? initialScopes = null) { return CallsWebApi( initialScopes, options => ConfigurationSection.Bind(options)); } - /// - /// Add MSAL support to the web app or web API. - /// - /// The configuration section instance from which to extract the values - /// - /// Initial scopes to request at sign-in. - /// The name of the configuration section with the necessary - /// settings to initialize authentication options. - /// The authentication builder for chaining. - [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] - public MicrosoftWebAppAuthenticationBuilder CallsWebApi( - IConfigurationSection configurationSection, - IEnumerable initialScopes) - { - return CallsWebApi( - initialScopes, - options => configurationSection.Bind(options)); - } - /// /// The Web app calls a web api. /// @@ -122,8 +83,8 @@ public MicrosoftWebAppAuthenticationBuilder CallsWebApi( CallsWebApiImplementation( Services, initialScopes, - _configureMicrosoftIdentityOptions, - _openIdConnectScheme, + ConfigureMicrosoftIdentityOptions, + OpenIdConnectScheme, configureConfidentialClientApplicationOptions); return this; } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs index 38539b5f5..3bd29f0dc 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs @@ -41,6 +41,16 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( string cookieScheme = CookieAuthenticationDefaults.AuthenticationScheme, bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false) { + if (configuration == null) + { + throw new ArgumentException(nameof(configuration)); + } + + if (string.IsNullOrEmpty(configSectionName)) + { + throw new ArgumentException(nameof(configSectionName)); + } + var microsoftWebAppAuthenticationBuilder = builder.AddMicrosoftWebApp( options => configuration.Bind(configSectionName, options), null, diff --git a/tests/B2CWebAppCallsWebApi/Client/Startup.cs b/tests/B2CWebAppCallsWebApi/Client/Startup.cs index 5df7aa1a5..60a2fcc22 100644 --- a/tests/B2CWebAppCallsWebApi/Client/Startup.cs +++ b/tests/B2CWebAppCallsWebApi/Client/Startup.cs @@ -44,9 +44,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftWebApp(Configuration, "AzureAdB2C") - .CallsWebApi(Configuration, - initialScopes: new string[] { Configuration["TodoList:TodoListScope"] }, - configSectionName: "AzureAdB2C") + .CallsWebApi(initialScopes: new string[] { Configuration["TodoList:TodoListScope"] }) .AddInMemoryTokenCaches(); // Add APIs diff --git a/tests/BlazorServerCallsGraph/Startup.cs b/tests/BlazorServerCallsGraph/Startup.cs index 17b1654d5..c218aa6fc 100644 --- a/tests/BlazorServerCallsGraph/Startup.cs +++ b/tests/BlazorServerCallsGraph/Startup.cs @@ -10,6 +10,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using blazor.Data; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; namespace blazor { @@ -27,11 +28,11 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { string[] scopes = Configuration.GetValue("CalledApi:CalledApiScopes")?.Split(' '); - services.AddMicrosoftWebAppAuthentication(Configuration, "AzureAd") - .AddMicrosoftWebAppCallsWebApi(Configuration, - scopes, - "AzureAd") - .AddInMemoryTokenCaches(); + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftWebApp(Configuration, "AzureAd") + .CallsWebApi(scopes) + .AddInMemoryTokenCaches(); + services.AddDownstreamWebApiService(Configuration); services.AddMicrosoftGraph(scopes, Configuration.GetValue("CalledApi:CalledApiUrl")); diff --git a/tests/WebAppCallsMicrosoftGraph/Startup.cs b/tests/WebAppCallsMicrosoftGraph/Startup.cs index d9932b33d..c5648e31a 100644 --- a/tests/WebAppCallsMicrosoftGraph/Startup.cs +++ b/tests/WebAppCallsMicrosoftGraph/Startup.cs @@ -29,8 +29,8 @@ public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftWebApp(Configuration) - .AddMicrosoftWebAppCallsWebApi(Configuration); - services.AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); services.AddMicrosoftGraph(Configuration, new string[] { "user.read" }); diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs index 7ae957983..4871a228d 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs @@ -45,7 +45,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftWebApp(Configuration, "AzureAd") - .CallsWebApi(Configuration) + .CallsWebApi() .AddInMemoryTokenCaches(); // Add APIs diff --git a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs index 229326d43..c9aa16f54 100644 --- a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs @@ -34,8 +34,8 @@ public void ConfigureServices(IServiceCollection services) // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftWebApi(Configuration, "AzureAd") - .AddMicrosoftWebApiCallsWebApi(Configuration); - services.AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); services.AddControllers(); } From fdc7004a8dad45f6e9f7f87ac9e9d806a4780ae7 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Tue, 4 Aug 2020 14:08:56 +0200 Subject: [PATCH 03/28] Improving the API --- .../Microsoft.Identity.Web.xml | 132 +++++++- .../MicrosoftBaseAuthenticationBuilder.cs | 40 +++ .../WebApiExtensions/ClassDiagram1.cd | 18 ++ .../MicrosoftWebAppAuthenticationBuilder.cs | 47 +-- ...pAuthenticationBuilderWithConfiguration.cs | 51 +++ ...ftAppCallingWebApiAuthenticationBuilder.cs | 52 +++ .../WebAppAuthenticationBuilderExtensions.cs | 297 +++++++++++++----- ...lsWebApiAuthenticationBuilderExtensions.cs | 4 +- .../WebAppServiceCollectionExtensions.cs | 6 +- tests/WebAppCallsMicrosoftGraph/Startup.cs | 26 +- 10 files changed, 533 insertions(+), 140 deletions(-) create mode 100644 src/Microsoft.Identity.Web/MicrosoftBaseAuthenticationBuilder.cs create mode 100644 src/Microsoft.Identity.Web/WebApiExtensions/ClassDiagram1.cd create mode 100644 src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilderWithConfiguration.cs create mode 100644 src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 3d9d76011..f65047808 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -716,6 +716,31 @@ OpenID Connect event. A that represents a completed remove from cache operation. + + + Base class for Web app and Web API Microsoft authentication + builders. + + + + + Constructor. + + The services being configured. + Optional configuration section. + + + + The services being configured. + + + + + Configuration section from which to bind options. + + It can be null if the configuration happens with delegates + rather than configuration. + Extensions for IServerSideBlazorBuilder for startup initialization of web APIs. @@ -1756,7 +1781,7 @@ Authentication builder specific for Microsoft identity platform. - + Constructor. @@ -1764,27 +1789,64 @@ Defaut scheme used for OpenIdConnect. Action called to configure the Microsoft identity options. + Optional configuration section. - + - The services being configured. + The Web app calls a web api. This overrides enables you to specify the + ConfidentialClientApplicationOptions (from MSAL.NET) programmatically. + Action to configure the + MSAL.NET confidential client application options. + Initial scopes. + the builder itself for chaining. - + - Add MSAL support to the web app or web API. + Builder for a Microsoft web app authentication where configuration is + available for CallsWebApi. + + + + + Constructor. + + The services being configured. + Defaut scheme used for OpenIdConnect. + Action called to configure + the Microsoft identity options. + Optional configuration section. + + + + Add support for the Web app to acquire tokens to call an API. Optional initial scopes to request. The authentication builder for chaining. - + - The Web app calls a web api. + Authentication builder returned by the CallsWebApi methods + enabling to decide token cache implementations. - Initial scopes. - Action to configure the - MSAL.NET confidential client application options. - the builder itself for chaining. + + + + Add in memory token caches. + + the service collection. + + + + Add distributed token caches. + + the service collection. + + + + Add session token caches. + + the service collection. @@ -1793,8 +1855,9 @@ - Add authentication with Microsoft identity platform. - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + Add authentication to a Web app with Microsoft identity platform. + This method expects the configuration file will have a section, named "AzureAd" as default, + with the necessary settings to initialize authentication options. The to which to add this configuration. The configuration instance. @@ -1804,6 +1867,20 @@ Set to true if you want to debug, or just understand the OpenID Connect events. + The builder for chaining. + + + + Add authentication with Microsoft identity platform. + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + + The to which to add this configuration. + The configuration section from which to get the options. + The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". + The cookie-based scheme name to be used. By default it uses "Cookies". + + Set to true if you want to debug, or just understand the OpenID Connect events. + The authentication builder for chaining. @@ -1820,6 +1897,35 @@ The authentication builder for chaining. + + + Add authentication with Microsoft identity platform. + + The to which to add this configuration. + The action to configure . + The action to configure . + The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". + The cookie-based scheme name to be used. By default it uses "Cookies". + + Set to true if you want to debug, or just understand the OpenID Connect events. + + Configuration section. + The authentication builder for chaining. + + + + Add authentication with Microsoft identity platform. + + The to which to add this configuration. + The action to configure . + The action to configure . + The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". + The cookie-based scheme name to be used. By default it uses "Cookies". + + Set to true if you want to debug, or just understand the OpenID Connect events. + + The authentication builder for chaining. + Extensions for for startup initialization. diff --git a/src/Microsoft.Identity.Web/MicrosoftBaseAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/MicrosoftBaseAuthenticationBuilder.cs new file mode 100644 index 000000000..48ad5e6be --- /dev/null +++ b/src/Microsoft.Identity.Web/MicrosoftBaseAuthenticationBuilder.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Identity.Web +{ + /// + /// Base class for Web app and Web API Microsoft authentication + /// builders. + /// + public abstract class MicrosoftBaseAuthenticationBuilder + { + /// + /// Constructor. + /// + /// The services being configured. + /// Optional configuration section. + protected MicrosoftBaseAuthenticationBuilder( + IServiceCollection services, + IConfigurationSection? configurationSection = null) + { + Services = services; + ConfigurationSection = configurationSection; + } + + /// + /// The services being configured. + /// + public IServiceCollection Services { get; private set; } + + /// + /// Configuration section from which to bind options. + /// + /// It can be null if the configuration happens with delegates + /// rather than configuration. + protected IConfigurationSection? ConfigurationSection { get; set; } + } +} diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/ClassDiagram1.cd b/src/Microsoft.Identity.Web/WebApiExtensions/ClassDiagram1.cd new file mode 100644 index 000000000..fa21bfa1a --- /dev/null +++ b/src/Microsoft.Identity.Web/WebApiExtensions/ClassDiagram1.cd @@ -0,0 +1,18 @@ + + + + + + gAAAAQAAAAAAIAAAAAAAAABAAAAAgAAAAAAgAAACAAA= + WebApiExtensions\MicrosoftWebApiAuthenticationBuilder.cs + + + + + + AAAAAAAAAQAAIAAAAAAAAAAAAAAAgAAAAAAgAAAAAAA= + WebAppExtensions\MicrosoftWebAppAuthenticationBuilder.cs + + + + \ No newline at end of file diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs index 4fc3fe9d8..73d58565f 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs @@ -16,7 +16,7 @@ namespace Microsoft.Identity.Web /// /// Authentication builder specific for Microsoft identity platform. /// - public class MicrosoftWebAppAuthenticationBuilder + public class MicrosoftWebAppAuthenticationBuilder : MicrosoftBaseAuthenticationBuilder { /// /// Constructor. @@ -25,12 +25,14 @@ public class MicrosoftWebAppAuthenticationBuilder /// Defaut scheme used for OpenIdConnect. /// Action called to configure /// the Microsoft identity options. + /// Optional configuration section. internal MicrosoftWebAppAuthenticationBuilder( IServiceCollection services, string openIdConnectScheme, - Action configureMicrosoftIdentityOptions) + Action configureMicrosoftIdentityOptions, + IConfigurationSection? configurationSection) + : base(services, configurationSection) { - Services = services; OpenIdConnectScheme = openIdConnectScheme; ConfigureMicrosoftIdentityOptions = configureMicrosoftIdentityOptions; @@ -40,56 +42,39 @@ internal MicrosoftWebAppAuthenticationBuilder( } } - /// - /// The services being configured. - /// - public virtual IServiceCollection Services { get; private set; } - private Action ConfigureMicrosoftIdentityOptions { get; set; } private string OpenIdConnectScheme { get; set; } - internal IConfigurationSection? ConfigurationSection { get; set; } - - /// - /// Add MSAL support to the web app or web API. - /// - /// Optional initial scopes to request. - /// The authentication builder for chaining. - public MicrosoftWebAppAuthenticationBuilder CallsWebApi( - IEnumerable? initialScopes = null) - { - return CallsWebApi( - initialScopes, - options => ConfigurationSection.Bind(options)); - } - /// - /// The Web app calls a web api. + /// The Web app calls a web api. This overrides enables you to specify the + /// ConfidentialClientApplicationOptions (from MSAL.NET) programmatically. /// - /// Initial scopes. /// Action to configure the /// MSAL.NET confidential client application options. + /// Initial scopes. /// the builder itself for chaining. - public MicrosoftWebAppAuthenticationBuilder CallsWebApi( - IEnumerable? initialScopes, - Action configureConfidentialClientApplicationOptions) + public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi( + Action configureConfidentialClientApplicationOptions, + IEnumerable? initialScopes = null) { if (configureConfidentialClientApplicationOptions == null) { throw new ArgumentNullException(nameof(configureConfidentialClientApplicationOptions)); } - CallsWebApiImplementation( + WebAppCallsWebApiImplementation( Services, initialScopes, ConfigureMicrosoftIdentityOptions, OpenIdConnectScheme, configureConfidentialClientApplicationOptions); - return this; + return new MicrososoftAppCallingWebApiAuthenticationBuilder( + Services, + ConfigurationSection); } - internal static void CallsWebApiImplementation( + internal static void WebAppCallsWebApiImplementation( IServiceCollection services, IEnumerable? initialScopes, Action configureMicrosoftIdentityOptions, diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilderWithConfiguration.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilderWithConfiguration.cs new file mode 100644 index 000000000..fcbddb3c1 --- /dev/null +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilderWithConfiguration.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Identity.Web +{ + /// + /// Builder for a Microsoft web app authentication where configuration is + /// available for CallsWebApi. + /// + public class MicrosoftWebAppAuthenticationBuilderWithConfiguration : MicrosoftWebAppAuthenticationBuilder + { + /// + /// Constructor. + /// + /// The services being configured. + /// Defaut scheme used for OpenIdConnect. + /// Action called to configure + /// the Microsoft identity options. + /// Optional configuration section. + internal MicrosoftWebAppAuthenticationBuilderWithConfiguration( + IServiceCollection services, + string openIdConnectScheme, + Action configureMicrosoftIdentityOptions, + IConfigurationSection configurationSection) + : base(services, openIdConnectScheme, configureMicrosoftIdentityOptions, configurationSection) + { + if (configurationSection == null) + { + throw new ArgumentNullException(nameof(configurationSection)); + } + } + + /// + /// Add support for the Web app to acquire tokens to call an API. + /// + /// Optional initial scopes to request. + /// The authentication builder for chaining. + public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi( + IEnumerable? initialScopes = null) + { + return CallsWebApi( + options => ConfigurationSection.Bind(options), + initialScopes); + } + } +} diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs new file mode 100644 index 000000000..d31d7c8ab --- /dev/null +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Identity.Web.TokenCacheProviders.Distributed; +using Microsoft.Identity.Web.TokenCacheProviders.InMemory; +using Microsoft.Identity.Web.TokenCacheProviders.Session; + +namespace Microsoft.Identity.Web +{ + /// + /// Authentication builder returned by the CallsWebApi methods + /// enabling to decide token cache implementations. + /// + public class MicrososoftAppCallingWebApiAuthenticationBuilder : MicrosoftBaseAuthenticationBuilder + { + internal MicrososoftAppCallingWebApiAuthenticationBuilder( + IServiceCollection services, + IConfigurationSection? configurationSection = null) + : base(services, configurationSection) + { + } + + /// + /// Add in memory token caches. + /// + /// the service collection. + public IServiceCollection AddInMemoryTokenCaches() + { + return Services.AddInMemoryTokenCaches(); + } + + /// + /// Add distributed token caches. + /// + /// the service collection. + public IServiceCollection AddDistributedTokenCaches() + { + return Services.AddDistributedTokenCaches(); + } + + /// + /// Add session token caches. + /// + /// the service collection. + public IServiceCollection AddSessionTokenCaches() + { + return Services.AddSessionTokenCaches(); + } + } +} diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs index 3bd29f0dc..3f2e31aa3 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs @@ -21,8 +21,9 @@ namespace Microsoft.Identity.Web public static partial class WebAppAuthenticationBuilderExtensions { /// - /// Add authentication with Microsoft identity platform. - /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + /// Add authentication to a Web app with Microsoft identity platform. + /// This method expects the configuration file will have a section, named "AzureAd" as default, + /// with the necessary settings to initialize authentication options. /// /// The to which to add this configuration. /// The configuration instance. @@ -32,8 +33,8 @@ public static partial class WebAppAuthenticationBuilderExtensions /// /// Set to true if you want to debug, or just understand the OpenID Connect events. /// - /// The authentication builder for chaining. - public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( + /// The builder for chaining. + public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftWebApp( this AuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -51,14 +52,51 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( throw new ArgumentException(nameof(configSectionName)); } - var microsoftWebAppAuthenticationBuilder = builder.AddMicrosoftWebApp( - options => configuration.Bind(configSectionName, options), - null, + IConfigurationSection configurationSection = configuration.GetSection(configSectionName); + + return builder.AddMicrosoftWebApp( + configurationSection, openIdConnectScheme, cookieScheme, subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); - microsoftWebAppAuthenticationBuilder.ConfigurationSection = configuration.GetSection(configSectionName); - return microsoftWebAppAuthenticationBuilder; + } + + /// + /// Add authentication with Microsoft identity platform. + /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + /// + /// The to which to add this configuration. + /// The configuration section from which to get the options. + /// The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". + /// The cookie-based scheme name to be used. By default it uses "Cookies". + /// + /// Set to true if you want to debug, or just understand the OpenID Connect events. + /// + /// The authentication builder for chaining. + public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftWebApp( + this AuthenticationBuilder builder, + IConfigurationSection configurationSection, + string openIdConnectScheme = OpenIdConnectDefaults.AuthenticationScheme, + string cookieScheme = CookieAuthenticationDefaults.AuthenticationScheme, + bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + if (configurationSection == null) + { + throw new ArgumentException(nameof(configurationSection)); + } + + return builder.AddMicrosoftWebAppWithConfiguration( + options => configurationSection.Bind(options), + null, + openIdConnectScheme, + cookieScheme, + subscribeToOpenIdConnectMiddlewareDiagnosticsEvents, + configurationSection); } /// @@ -86,6 +124,93 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( throw new ArgumentNullException(nameof(builder)); } + return builder.AddMicrosoftWebAppWithoutConfiguration( + configureMicrosoftIdentityOptions, + configureCookieAuthenticationOptions, + openIdConnectScheme, + cookieScheme, + subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); + } + + /// + /// Add authentication with Microsoft identity platform. + /// + /// The to which to add this configuration. + /// The action to configure . + /// The action to configure . + /// The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". + /// The cookie-based scheme name to be used. By default it uses "Cookies". + /// + /// Set to true if you want to debug, or just understand the OpenID Connect events. + /// + /// Configuration section. + /// The authentication builder for chaining. + private static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftWebAppWithConfiguration( + this AuthenticationBuilder builder, + Action configureMicrosoftIdentityOptions, + Action? configureCookieAuthenticationOptions, + string openIdConnectScheme, + string cookieScheme, + bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents, + IConfigurationSection configurationSection) + { + AddMicrosoftWebAppInternal( + builder, + configureMicrosoftIdentityOptions, + configureCookieAuthenticationOptions, + openIdConnectScheme, + cookieScheme, + subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); + + return new MicrosoftWebAppAuthenticationBuilderWithConfiguration( + builder.Services, + openIdConnectScheme, + configureMicrosoftIdentityOptions, + configurationSection); + } + + /// + /// Add authentication with Microsoft identity platform. + /// + /// The to which to add this configuration. + /// The action to configure . + /// The action to configure . + /// The OpenID Connect scheme name to be used. By default it uses "OpenIdConnect". + /// The cookie-based scheme name to be used. By default it uses "Cookies". + /// + /// Set to true if you want to debug, or just understand the OpenID Connect events. + /// + /// The authentication builder for chaining. + private static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppWithoutConfiguration( + this AuthenticationBuilder builder, + Action configureMicrosoftIdentityOptions, + Action? configureCookieAuthenticationOptions, + string openIdConnectScheme, + string cookieScheme, + bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents) + { + AddMicrosoftWebAppInternal( + builder, + configureMicrosoftIdentityOptions, + configureCookieAuthenticationOptions, + openIdConnectScheme, + cookieScheme, + subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); + + return new MicrosoftWebAppAuthenticationBuilder( + builder.Services, + openIdConnectScheme, + configureMicrosoftIdentityOptions, + null); + } + + private static void AddMicrosoftWebAppInternal(AuthenticationBuilder builder, Action configureMicrosoftIdentityOptions, Action? configureCookieAuthenticationOptions, string openIdConnectScheme, string cookieScheme, bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + if (configureMicrosoftIdentityOptions == null) { throw new ArgumentNullException(nameof(configureMicrosoftIdentityOptions)); @@ -106,102 +231,100 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( builder.AddOpenIdConnect(openIdConnectScheme, options => { }); builder.Services.AddOptions(openIdConnectScheme) .Configure>((options, serviceProvider, microsoftIdentityOptions) => - { - PopulateOpenIdOptionsFromMicrosoftIdentityOptions(options, microsoftIdentityOptions.Value); - var b2cOidcHandlers = new AzureADB2COpenIDConnectEventHandlers(openIdConnectScheme, microsoftIdentityOptions.Value); - - options.SignInScheme = cookieScheme; - - if (string.IsNullOrWhiteSpace(options.Authority)) { - options.Authority = AuthorityHelpers.BuildAuthority(microsoftIdentityOptions.Value); - } + PopulateOpenIdOptionsFromMicrosoftIdentityOptions(options, microsoftIdentityOptions.Value); + var b2cOidcHandlers = new AzureADB2COpenIDConnectEventHandlers(openIdConnectScheme, microsoftIdentityOptions.Value); - // This is a Microsoft identity platform Web app - options.Authority = AuthorityHelpers.EnsureAuthorityIsV2(options.Authority); + options.SignInScheme = cookieScheme; - options.TokenValidationParameters = options.TokenValidationParameters.Clone(); - - // B2C doesn't have preferred_username claims - if (microsoftIdentityOptions.Value.IsB2C) - { - options.TokenValidationParameters.NameClaimType = ClaimConstants.Name; - } - else - { - options.TokenValidationParameters.NameClaimType = ClaimConstants.PreferredUserName; - } - - // If the developer registered an IssuerValidator, do not overwrite it - if (options.TokenValidationParameters.IssuerValidator == null) - { - // If you want to restrict the users that can sign-in to several organizations - // Set the tenant value in the appsettings.json file to 'organizations', and add the - // issuers you want to accept to options.TokenValidationParameters.ValidIssuers collection - options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate; - } - - // Avoids having users being presented the select account dialog when they are already signed-in - // for instance when going through incremental consent - var redirectToIdpHandler = options.Events.OnRedirectToIdentityProvider; - options.Events.OnRedirectToIdentityProvider = async context => - { - var login = context.Properties.GetParameter(OpenIdConnectParameterNames.LoginHint); - if (!string.IsNullOrWhiteSpace(login)) + if (string.IsNullOrWhiteSpace(options.Authority)) { - context.ProtocolMessage.LoginHint = login; - context.ProtocolMessage.DomainHint = context.Properties.GetParameter( - OpenIdConnectParameterNames.DomainHint); - - // delete the login_hint and domainHint from the Properties when we are done otherwise - // it will take up extra space in the cookie. - context.Properties.Parameters.Remove(OpenIdConnectParameterNames.LoginHint); - context.Properties.Parameters.Remove(OpenIdConnectParameterNames.DomainHint); + options.Authority = AuthorityHelpers.BuildAuthority(microsoftIdentityOptions.Value); } - context.ProtocolMessage.SetParameter(Constants.ClientInfo, Constants.One); + // This is a Microsoft identity platform Web app + options.Authority = AuthorityHelpers.EnsureAuthorityIsV2(options.Authority); - // Additional claims - if (context.Properties.Items.ContainsKey(OidcConstants.AdditionalClaims)) - { - context.ProtocolMessage.SetParameter( - OidcConstants.AdditionalClaims, - context.Properties.Items[OidcConstants.AdditionalClaims]); - } + options.TokenValidationParameters = options.TokenValidationParameters.Clone(); + // B2C doesn't have preferred_username claims if (microsoftIdentityOptions.Value.IsB2C) { - // When a new Challenge is returned using any B2C user flow different than susi, we must change - // the ProtocolMessage.IssuerAddress to the desired user flow otherwise the redirect would use the susi user flow - await b2cOidcHandlers.OnRedirectToIdentityProvider(context).ConfigureAwait(false); + options.TokenValidationParameters.NameClaimType = ClaimConstants.Name; + } + else + { + options.TokenValidationParameters.NameClaimType = ClaimConstants.PreferredUserName; } - await redirectToIdpHandler(context).ConfigureAwait(false); - }; - - if (microsoftIdentityOptions.Value.IsB2C) - { - var remoteFailureHandler = options.Events.OnRemoteFailure; - options.Events.OnRemoteFailure = async context => + // If the developer registered an IssuerValidator, do not overwrite it + if (options.TokenValidationParameters.IssuerValidator == null) { - // Handles the error when a user cancels an action on the Azure Active Directory B2C UI. - // Handle the error code that Azure Active Directory B2C throws when trying to reset a password from the login page - // because password reset is not supported by a "sign-up or sign-in user flow". - await b2cOidcHandlers.OnRemoteFailure(context).ConfigureAwait(false); + // If you want to restrict the users that can sign-in to several organizations + // Set the tenant value in the appsettings.json file to 'organizations', and add the + // issuers you want to accept to options.TokenValidationParameters.ValidIssuers collection + options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate; + } - await remoteFailureHandler(context).ConfigureAwait(false); + // Avoids having users being presented the select account dialog when they are already signed-in + // for instance when going through incremental consent + var redirectToIdpHandler = options.Events.OnRedirectToIdentityProvider; + options.Events.OnRedirectToIdentityProvider = async context => + { + var login = context.Properties.GetParameter(OpenIdConnectParameterNames.LoginHint); + if (!string.IsNullOrWhiteSpace(login)) + { + context.ProtocolMessage.LoginHint = login; + context.ProtocolMessage.DomainHint = context.Properties.GetParameter( + OpenIdConnectParameterNames.DomainHint); + + // delete the login_hint and domainHint from the Properties when we are done otherwise + // it will take up extra space in the cookie. + context.Properties.Parameters.Remove(OpenIdConnectParameterNames.LoginHint); + context.Properties.Parameters.Remove(OpenIdConnectParameterNames.DomainHint); + } + + context.ProtocolMessage.SetParameter(Constants.ClientInfo, Constants.One); + + // Additional claims + if (context.Properties.Items.ContainsKey(OidcConstants.AdditionalClaims)) + { + context.ProtocolMessage.SetParameter( + OidcConstants.AdditionalClaims, + context.Properties.Items[OidcConstants.AdditionalClaims]); + } + + if (microsoftIdentityOptions.Value.IsB2C) + { + // When a new Challenge is returned using any B2C user flow different than susi, we must change + // the ProtocolMessage.IssuerAddress to the desired user flow otherwise the redirect would use the susi user flow + await b2cOidcHandlers.OnRedirectToIdentityProvider(context).ConfigureAwait(false); + } + + await redirectToIdpHandler(context).ConfigureAwait(false); }; - } - if (subscribeToOpenIdConnectMiddlewareDiagnosticsEvents) - { - var diagnostics = serviceProvider.GetRequiredService(); + if (microsoftIdentityOptions.Value.IsB2C) + { + var remoteFailureHandler = options.Events.OnRemoteFailure; + options.Events.OnRemoteFailure = async context => + { + // Handles the error when a user cancels an action on the Azure Active Directory B2C UI. + // Handle the error code that Azure Active Directory B2C throws when trying to reset a password from the login page + // because password reset is not supported by a "sign-up or sign-in user flow". + await b2cOidcHandlers.OnRemoteFailure(context).ConfigureAwait(false); + + await remoteFailureHandler(context).ConfigureAwait(false); + }; + } - diagnostics.Subscribe(options.Events); - } - }); + if (subscribeToOpenIdConnectMiddlewareDiagnosticsEvents) + { + var diagnostics = serviceProvider.GetRequiredService(); - return new MicrosoftWebAppAuthenticationBuilder(builder.Services, openIdConnectScheme, configureMicrosoftIdentityOptions); + diagnostics.Subscribe(options.Events); + } + }); } internal static void PopulateOpenIdOptionsFromMicrosoftIdentityOptions(OpenIdConnectOptions options, MicrosoftIdentityOptions microsoftIdentityOptions) diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs index 949d5d20f..2fadc227e 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs @@ -36,7 +36,7 @@ public static class WebAppCallsWebApiAuthenticationBuilderExtensions /// to be provided. /// [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] - public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( + private static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( this MicrosoftWebAppAuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -110,7 +110,7 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi throw new ArgumentNullException(nameof(configureConfidentialClientApplicationOptions)); } - MicrosoftWebAppAuthenticationBuilder.CallsWebApiImplementation( + MicrosoftWebAppAuthenticationBuilder.WebAppCallsWebApiImplementation( builder.Services, initialScopes, configureMicrosoftIdentityOptions, diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs index ec3377191..fa29e57a5 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs @@ -32,7 +32,7 @@ public static partial class WebAppServiceCollectionExtensions /// Set to true if you want to debug, or just understand the OpenIdConnect events. /// /// The authentication builder to chain extension methods. - public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppAuthentication( + public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftWebAppAuthentication( this IServiceCollection services, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -42,8 +42,8 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppAuthenticat { AuthenticationBuilder builder = services.AddAuthentication(openIdConnectScheme); return builder.AddMicrosoftWebApp( - options => configuration.Bind(configSectionName, options), - null, + configuration, + configSectionName, openIdConnectScheme, cookieScheme, subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); diff --git a/tests/WebAppCallsMicrosoftGraph/Startup.cs b/tests/WebAppCallsMicrosoftGraph/Startup.cs index c5648e31a..a8176fd05 100644 --- a/tests/WebAppCallsMicrosoftGraph/Startup.cs +++ b/tests/WebAppCallsMicrosoftGraph/Startup.cs @@ -28,11 +28,29 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftWebApp(Configuration) - .CallsWebApi() - .AddInMemoryTokenCaches(); + .AddMicrosoftWebApp(Configuration.GetSection("AzureAd")) + .CallsWebApi() + .AddInMemoryTokenCaches(); +/* OR + services.AddMicrosoftWebAppAuthentication(Configuration) + .CallsWebApi() + .AddInMemoryTokenCaches(); - services.AddMicrosoftGraph(Configuration, new string[] { "user.read" }); + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftWebApp(options => + { + Configuration.Bind("AzureAd", options); + // do something + }) + .CallsWebApi(options => + { + Configuration.Bind("AzureAd", options); + // do something + } + ) + .AddInMemoryTokenCaches(); +*/ + services.AddMicrosoftGraph(Configuration, new string[] { "user.read" }); services.AddRazorPages().AddMvcOptions(options => { From 4d3e5350f4fb63991672679045b372d4774620e4 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Tue, 4 Aug 2020 18:50:22 +0200 Subject: [PATCH 04/28] Improving the API. --- .../Microsoft.Identity.Web.xml | 72 +++---- .../DistributedTokenCacheAdapterExtension.cs | 16 +- .../InMemoryTokenCacheProviderExtension.cs | 31 +-- .../SessionTokenCacheProviderExtension.cs | 34 +--- .../MicrosoftWebApiAuthenticationBuilder.cs | 32 +--- ...iAuthenticationBuilderWithConfiguration.cs | 40 ++++ .../WebApiAuthenticationBuilderExtensions.cs | 179 +++++++++++------- ...ftAppCallingWebApiAuthenticationBuilder.cs | 50 ++++- 8 files changed, 239 insertions(+), 215 deletions(-) create mode 100644 src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilderWithConfiguration.cs diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index f65047808..2ab8c21fd 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1282,11 +1282,6 @@ The services collection to add to. A to chain. - - Adds both the app and per-user .NET Core distributed based token caches. - The Authentication builder to add to. - A to chain. - Adds the .NET Core distributed cache based app token cache to the service collection. The services collection to add to. @@ -1381,16 +1376,6 @@ The services collection to add to. the services (for chaining). - - Adds both the app and per-user in-memory token caches. - The authentication builder to add to. - the builder (for chaining). - - - Adds both the app and per-user in-memory token caches. - The authentication builder to add to. - the builder (for chaining). - MSAL's in-memory token cache options. @@ -1595,30 +1580,6 @@ The services collection to add to. The service collection. - - - Adds both application and per-user session token caches. - - - For this session cache to work effectively the ASP.NET Core session has to be configured properly. - The latest guidance is provided at https://docs.microsoft.com/aspnet/core/fundamentals/app-state. - - In the method public void ConfigureServices(IServiceCollection services) in Startup.cs, add the following: - - services.AddSession(option => - { - option.Cookie.IsEssential = true; - }); - - In the method public void Configure(IApplicationBuilder app, IHostingEnvironment env) in Startup.cs, add the following: - - app.UseSession(); // Before UseMvc() - - Because session token caches are added with scoped lifetime, they should not be used when TokenAcquisition is also used as a singleton (for example, when using Microsoft Graph SDK). - - The authentication builder to add the session token caches to. - The builder to chain more commands. - Adds an HTTP session-based application token cache to the service collection. @@ -1672,7 +1633,7 @@ Authentication builder for a web API. - + Constructor. @@ -1681,24 +1642,26 @@ ACtion called to configure the JwtBearer options. Action called to configure the Microsoft identity options. + Configuration section from which to + get parameters. - + - The services being configured. + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + The action to configure . + The authentication builder to chain. - + - Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + Builder for Web API authentication with configuration. - The authentication builder to chain. - + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - The action to configure . The authentication builder to chain. @@ -1720,6 +1683,19 @@ The authentication builder to chain. + + + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + + The to which to add this configuration. + The configuration second from which to fill-in the options. + The JWT bearer scheme name to be used. By default it uses "Bearer". + + Set to true if you want to debug, or just understand the JWT bearer events. + + The authentication builder to chain. + Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0). diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs index f1a5d3312..2bf76d67e 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs @@ -15,6 +15,7 @@ public static class DistributedTokenCacheAdapterExtension /// Adds both the app and per-user in-memory token caches. /// The services collection to add to. /// A to chain. + [Obsolete("Rather use .CallsWebApi().AddDistributedTokenCaches()")] internal static IServiceCollection AddDistributedTokenCaches( this IServiceCollection services) { @@ -23,21 +24,6 @@ internal static IServiceCollection AddDistributedTokenCaches( return services; } - /// Adds both the app and per-user .NET Core distributed based token caches. - /// The Authentication builder to add to. - /// A to chain. - public static MicrosoftWebAppAuthenticationBuilder AddDistributedTokenCaches( - this MicrosoftWebAppAuthenticationBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - builder.Services.AddDistributedTokenCaches(); - return builder; - } - /// Adds the .NET Core distributed cache based app token cache to the service collection. /// The services collection to add to. /// A to chain. diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs index bb996c51d..820bbca03 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs @@ -15,6 +15,7 @@ public static class InMemoryTokenCacheProviderExtension /// Adds both the app and per-user in-memory token caches. /// The services collection to add to. /// the services (for chaining). + [Obsolete("Rather use .CallsWebApi().AddInMemoryTokenCaches()")] internal static IServiceCollection AddInMemoryTokenCaches( this IServiceCollection services) { @@ -28,35 +29,5 @@ internal static IServiceCollection AddInMemoryTokenCaches( services.AddSingleton(); return services; } - - /// Adds both the app and per-user in-memory token caches. - /// The authentication builder to add to. - /// the builder (for chaining). - public static MicrosoftWebAppAuthenticationBuilder AddInMemoryTokenCaches( - this MicrosoftWebAppAuthenticationBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - builder.Services.AddInMemoryTokenCaches(); - return builder; - } - - /// Adds both the app and per-user in-memory token caches. - /// The authentication builder to add to. - /// the builder (for chaining). - public static MicrosoftWebApiAuthenticationBuilder AddInMemoryTokenCaches( - this MicrosoftWebApiAuthenticationBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - builder.Services.AddInMemoryTokenCaches(); - return builder; - } } } diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs index 76e6dce7c..6474de9dd 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs @@ -38,6 +38,7 @@ public static class SessionTokenCacheProviderExtension /// /// The services collection to add to. /// The service collection. + [Obsolete("Rather use .CallsWebApi().AddSessionTokenCaches()")] internal static IServiceCollection AddSessionTokenCaches(this IServiceCollection services) { if (services == null) @@ -81,39 +82,6 @@ internal static IServiceCollection AddSessionTokenCaches(this IServiceCollection return services; } - /// - /// Adds both application and per-user session token caches. - /// - /// - /// For this session cache to work effectively the ASP.NET Core session has to be configured properly. - /// The latest guidance is provided at https://docs.microsoft.com/aspnet/core/fundamentals/app-state. - /// - /// In the method public void ConfigureServices(IServiceCollection services) in Startup.cs, add the following: - /// - /// services.AddSession(option => - /// { - /// option.Cookie.IsEssential = true; - /// }); - /// - /// In the method public void Configure(IApplicationBuilder app, IHostingEnvironment env) in Startup.cs, add the following: - /// - /// app.UseSession(); // Before UseMvc() - /// - /// Because session token caches are added with scoped lifetime, they should not be used when TokenAcquisition is also used as a singleton (for example, when using Microsoft Graph SDK). - /// - /// The authentication builder to add the session token caches to. - /// The builder to chain more commands. - public static MicrosoftWebAppAuthenticationBuilder AddSessionTokenCaches(this MicrosoftWebAppAuthenticationBuilder builder) - { - if (builder == null) - { - throw new ArgumentNullException(nameof(builder)); - } - - builder.Services.AddSessionTokenCaches(); - return builder; - } - /// /// Adds an HTTP session-based application token cache to the service collection. /// diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs index a0daf3a9e..7b51b6625 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs @@ -13,7 +13,7 @@ namespace Microsoft.Identity.Web /// /// Authentication builder for a web API. /// - public class MicrosoftWebApiAuthenticationBuilder + public class MicrosoftWebApiAuthenticationBuilder : MicrosoftBaseAuthenticationBuilder { /// /// Constructor. @@ -23,13 +23,16 @@ public class MicrosoftWebApiAuthenticationBuilder /// ACtion called to configure the JwtBearer options. /// Action called to configure /// the Microsoft identity options. + /// Configuration section from which to + /// get parameters. internal MicrosoftWebApiAuthenticationBuilder( IServiceCollection services, string jwtBearerAuthenticationScheme, Action configureJwtBearerOptions, - Action configureMicrosoftIdentityOptions) + Action configureMicrosoftIdentityOptions, + IConfigurationSection? configurationSection) + : base(services, configurationSection) { - Services = services; JwtBearerAuthenticationScheme = jwtBearerAuthenticationScheme; ConfigureJwtBearerOptions = configureJwtBearerOptions; ConfigureMicrosoftIdentityOptions = configureMicrosoftIdentityOptions; @@ -47,35 +50,18 @@ internal MicrosoftWebApiAuthenticationBuilder( Services.Configure(configureMicrosoftIdentityOptions); } - /// - /// The services being configured. - /// - public virtual IServiceCollection Services { get; private set; } - private Action ConfigureMicrosoftIdentityOptions { get; set; } private string JwtBearerAuthenticationScheme { get; set; } private Action ConfigureJwtBearerOptions { get; set; } - internal IConfigurationSection? ConfigurationSection { get; set; } - - /// - /// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). - /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - /// - /// The authentication builder to chain. - public MicrosoftWebApiAuthenticationBuilder CallsWebApi() - { - return CallsWebApi(options => ConfigurationSection.Bind(options)); - } - /// /// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). /// /// The action to configure . /// The authentication builder to chain. - public MicrosoftWebApiAuthenticationBuilder CallsWebApi( + public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi( Action configureConfidentialClientApplicationOptions) { if (configureConfidentialClientApplicationOptions == null) @@ -88,7 +74,9 @@ public MicrosoftWebApiAuthenticationBuilder CallsWebApi( JwtBearerAuthenticationScheme, configureConfidentialClientApplicationOptions); - return this; + return new MicrososoftAppCallingWebApiAuthenticationBuilder( + Services, + ConfigurationSection); } internal static void CallsWebApiImplementation( diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilderWithConfiguration.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilderWithConfiguration.cs new file mode 100644 index 000000000..0fad716a0 --- /dev/null +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilderWithConfiguration.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +namespace Microsoft.Identity.Web +{ + /// + /// Builder for Web API authentication with configuration. + /// + public class MicrosoftWebApiAuthenticationBuilderWithConfiguration : MicrosoftWebApiAuthenticationBuilder + { + internal MicrosoftWebApiAuthenticationBuilderWithConfiguration( + IServiceCollection services, + string jwtBearerAuthenticationScheme, + Action configureJwtBearerOptions, + Action configureMicrosoftIdentityOptions, + IConfigurationSection? configurationSection) + : base(services, jwtBearerAuthenticationScheme, configureJwtBearerOptions, configureMicrosoftIdentityOptions, configurationSection) + { + if (configurationSection == null) + { + throw new ArgumentNullException(nameof(configurationSection)); + } + } + + /// + /// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + /// + /// The authentication builder to chain. + public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi() + { + return CallsWebApi(options => ConfigurationSection.Bind(options)); + } + } +} diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs index 3ecec0466..82fdf66e0 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs @@ -31,7 +31,7 @@ public static partial class WebApiAuthenticationBuilderExtensions /// Set to true if you want to debug, or just understand the JWT bearer events. /// /// The authentication builder to chain. - public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApi( + public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoftWebApi( this AuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -49,13 +49,53 @@ public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApi( } IConfigurationSection configurationSection = configuration.GetSection(configSectionName); - var microsoftWebApiAuthenticationBuilder = builder.AddMicrosoftWebApi( + + return builder.AddMicrosoftWebApi( + configurationSection, + jwtBearerScheme, + subscribeToJwtBearerMiddlewareDiagnosticsEvents); + } + + /// + /// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + /// + /// The to which to add this configuration. + /// The configuration second from which to fill-in the options. + /// The JWT bearer scheme name to be used. By default it uses "Bearer". + /// + /// Set to true if you want to debug, or just understand the JWT bearer events. + /// + /// The authentication builder to chain. + public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoftWebApi( + this AuthenticationBuilder builder, + IConfigurationSection configurationSection, + string jwtBearerScheme = JwtBearerDefaults.AuthenticationScheme, + bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) + { + if (configurationSection == null) + { + throw new ArgumentNullException(nameof(configurationSection)); + } + + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + AddMicrosoftWebApiImplementation( + builder, options => configurationSection.Bind(options), options => configurationSection.Bind(options), jwtBearerScheme, subscribeToJwtBearerMiddlewareDiagnosticsEvents); - microsoftWebApiAuthenticationBuilder.ConfigurationSection = configurationSection; - return microsoftWebApiAuthenticationBuilder; + + return new MicrosoftWebApiAuthenticationBuilderWithConfiguration( + builder.Services, + jwtBearerScheme, + options => configurationSection.Bind(options), + options => configurationSection.Bind(options), + configurationSection); } /// @@ -90,6 +130,23 @@ public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApi( throw new ArgumentNullException(nameof(configureMicrosoftIdentityOptions)); } + AddMicrosoftWebApiImplementation( + builder, + configureJwtBearerOptions, + configureMicrosoftIdentityOptions, + jwtBearerScheme, + subscribeToJwtBearerMiddlewareDiagnosticsEvents); + + return new MicrosoftWebApiAuthenticationBuilder( + builder.Services, + jwtBearerScheme, + configureJwtBearerOptions, + configureMicrosoftIdentityOptions, + null); + } + + private static void AddMicrosoftWebApiImplementation(AuthenticationBuilder builder, Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions, string jwtBearerScheme, bool subscribeToJwtBearerMiddlewareDiagnosticsEvents) + { builder.AddJwtBearer(jwtBearerScheme, configureJwtBearerOptions); builder.Services.Configure(configureMicrosoftIdentityOptions); @@ -105,77 +162,71 @@ public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApi( // Change the authentication configuration to accommodate the Microsoft identity platform endpoint (v2.0). builder.Services.AddOptions(jwtBearerScheme) .Configure>((options, serviceProvider, microsoftIdentityOptions) => - { - if (string.IsNullOrWhiteSpace(options.Authority)) { - options.Authority = AuthorityHelpers.BuildAuthority(microsoftIdentityOptions.Value); - } - - // This is a Microsoft identity platform Web API - options.Authority = AuthorityHelpers.EnsureAuthorityIsV2(options.Authority); - - options.TokenValidationParameters = options.TokenValidationParameters.Clone(); + if (string.IsNullOrWhiteSpace(options.Authority)) + { + options.Authority = AuthorityHelpers.BuildAuthority(microsoftIdentityOptions.Value); + } - if (options.TokenValidationParameters.AudienceValidator == null - && options.TokenValidationParameters.ValidAudience == null - && options.TokenValidationParameters.ValidAudiences == null) - { - RegisterValidAudience registerAudience = new RegisterValidAudience(); - registerAudience.RegisterAudienceValidation( - options.TokenValidationParameters, - microsoftIdentityOptions.Value); - } - - // If the developer registered an IssuerValidator, do not overwrite it - if (options.TokenValidationParameters.IssuerValidator == null) - { - // Instead of using the default validation (validating against a single tenant, as we do in line of business apps), - // we inject our own multi-tenant validation logic (which even accepts both v1.0 and v2.0 tokens) - options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate; - } + // This is a Microsoft identity platform Web API + options.Authority = AuthorityHelpers.EnsureAuthorityIsV2(options.Authority); - // If you provide a token decryption certificate, it will be used to decrypt the token - if (microsoftIdentityOptions.Value.TokenDecryptionCertificates != null) - { - options.TokenValidationParameters.TokenDecryptionKey = - new X509SecurityKey(DefaultCertificateLoader.LoadFirstCertificate(microsoftIdentityOptions.Value.TokenDecryptionCertificates)); - } + options.TokenValidationParameters = options.TokenValidationParameters.Clone(); - if (options.Events == null) - { - options.Events = new JwtBearerEvents(); - } + if (options.TokenValidationParameters.AudienceValidator == null + && options.TokenValidationParameters.ValidAudience == null + && options.TokenValidationParameters.ValidAudiences == null) + { + RegisterValidAudience registerAudience = new RegisterValidAudience(); + registerAudience.RegisterAudienceValidation( + options.TokenValidationParameters, + microsoftIdentityOptions.Value); + } - // When an access token for our own Web API is validated, we add it to MSAL.NET's cache so that it can - // be used from the controllers. - var tokenValidatedHandler = options.Events.OnTokenValidated; - options.Events.OnTokenValidated = async context => - { - // This check is required to ensure that the Web API only accepts tokens from tenants where it has been consented and provisioned. - if (!context.Principal.Claims.Any(x => x.Type == ClaimConstants.Scope) - && !context.Principal.Claims.Any(y => y.Type == ClaimConstants.Scp) - && !context.Principal.Claims.Any(y => y.Type == ClaimConstants.Roles) - && !context.Principal.Claims.Any(y => y.Type == ClaimConstants.Role)) + // If the developer registered an IssuerValidator, do not overwrite it + if (options.TokenValidationParameters.IssuerValidator == null) { - throw new UnauthorizedAccessException(IDWebErrorMessage.NeitherScopeOrRolesClaimFoundInToken); + // Instead of using the default validation (validating against a single tenant, as we do in line of business apps), + // we inject our own multi-tenant validation logic (which even accepts both v1.0 and v2.0 tokens) + options.TokenValidationParameters.IssuerValidator = AadIssuerValidator.GetIssuerValidator(options.Authority).Validate; } - await tokenValidatedHandler(context).ConfigureAwait(false); - }; + // If you provide a token decryption certificate, it will be used to decrypt the token + if (microsoftIdentityOptions.Value.TokenDecryptionCertificates != null) + { + options.TokenValidationParameters.TokenDecryptionKey = + new X509SecurityKey(DefaultCertificateLoader.LoadFirstCertificate(microsoftIdentityOptions.Value.TokenDecryptionCertificates)); + } - if (subscribeToJwtBearerMiddlewareDiagnosticsEvents) - { - var diagnostics = serviceProvider.GetRequiredService(); + if (options.Events == null) + { + options.Events = new JwtBearerEvents(); + } - diagnostics.Subscribe(options.Events); - } - }); + // When an access token for our own Web API is validated, we add it to MSAL.NET's cache so that it can + // be used from the controllers. + var tokenValidatedHandler = options.Events.OnTokenValidated; + options.Events.OnTokenValidated = async context => + { + // This check is required to ensure that the Web API only accepts tokens from tenants where it has been consented and provisioned. + if (!context.Principal.Claims.Any(x => x.Type == ClaimConstants.Scope) + && !context.Principal.Claims.Any(y => y.Type == ClaimConstants.Scp) + && !context.Principal.Claims.Any(y => y.Type == ClaimConstants.Roles) + && !context.Principal.Claims.Any(y => y.Type == ClaimConstants.Role)) + { + throw new UnauthorizedAccessException(IDWebErrorMessage.NeitherScopeOrRolesClaimFoundInToken); + } + + await tokenValidatedHandler(context).ConfigureAwait(false); + }; + + if (subscribeToJwtBearerMiddlewareDiagnosticsEvents) + { + var diagnostics = serviceProvider.GetRequiredService(); - return new MicrosoftWebApiAuthenticationBuilder( - builder.Services, - jwtBearerScheme, - configureJwtBearerOptions, - configureMicrosoftIdentityOptions); + diagnostics.Subscribe(options.Events); + } + }); } } } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs index d31d7c8ab..55ea04e06 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs @@ -1,8 +1,14 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; +using System.Linq; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Microsoft.Identity.Web.TokenCacheProviders; using Microsoft.Identity.Web.TokenCacheProviders.Distributed; using Microsoft.Identity.Web.TokenCacheProviders.InMemory; using Microsoft.Identity.Web.TokenCacheProviders.Session; @@ -28,7 +34,10 @@ internal MicrososoftAppCallingWebApiAuthenticationBuilder( /// the service collection. public IServiceCollection AddInMemoryTokenCaches() { - return Services.AddInMemoryTokenCaches(); + Services.AddMemoryCache(); + Services.AddHttpContextAccessor(); + Services.AddSingleton(); + return Services; } /// @@ -37,7 +46,9 @@ public IServiceCollection AddInMemoryTokenCaches() /// the service collection. public IServiceCollection AddDistributedTokenCaches() { - return Services.AddDistributedTokenCaches(); + Services.AddDistributedAppTokenCache(); + Services.AddDistributedUserTokenCache(); + return Services; } /// @@ -46,7 +57,40 @@ public IServiceCollection AddDistributedTokenCaches() /// the service collection. public IServiceCollection AddSessionTokenCaches() { - return Services.AddSessionTokenCaches(); + // Add session if you are planning to use session based token cache + var sessionStoreService = Services.FirstOrDefault(x => x.ServiceType.Name == "ISessionStore"); + + // If not added already + if (sessionStoreService == null) + { + Services.AddSession(option => + { + option.Cookie.IsEssential = true; + }); + } + else + { + // If already added, ensure the options are set to use Cookies + Services.Configure(option => + { + option.Cookie.IsEssential = true; + }); + } + + Services.AddHttpContextAccessor(); + Services.AddScoped(); + Services.TryAddScoped(provider => + { + var httpContext = provider.GetRequiredService().HttpContext; + if (httpContext == null) + { + throw new InvalidOperationException(IDWebErrorMessage.HttpContextIsNull); + } + + return httpContext.Session; + }); + + return Services; } } } From 96d643e4a7821f3b5adb923a8ed948f29fa6f3de Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Tue, 4 Aug 2020 19:46:32 +0200 Subject: [PATCH 05/28] Updating unit tests so that they build Fixing a few. --- .../WebApiExtensionsTests.cs | 4 ++-- .../WebAppExtensionsTests.cs | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs index 9829f17c2..1167f778a 100644 --- a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs @@ -68,7 +68,7 @@ public void AddMicrosoftWebApi_WithConfigName() // Config bind actions added correctly provider.GetRequiredService>().Create(JwtBearerScheme); provider.GetRequiredService>().Create(string.Empty); - config.Received(3).GetSection(ConfigSectionName); + config.Received(1).GetSection(ConfigSectionName); AddMicrosoftWebApi_TestCommon(services, provider, false); } @@ -113,7 +113,7 @@ public void AddMicrosoftWebApiAuthentication_WithConfigName() // Config bind actions added correctly provider.GetRequiredService>().Create(JwtBearerScheme); provider.GetRequiredService>().Create(string.Empty); - config.Received(3).GetSection(ConfigSectionName); + config.Received(1).GetSection(ConfigSectionName); AddMicrosoftWebApi_TestCommon(services, provider, false); } diff --git a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs index 96fbce9fc..9de617e7b 100644 --- a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs @@ -73,7 +73,7 @@ public void AddMicrosoftWebApp_WithConfigNameParameters(bool subscribeToDiagnost // Assert config bind actions added correctly provider.GetRequiredService>().Create(OidcScheme); provider.GetRequiredService>().Create(string.Empty); - configMock.Received(2).GetSection(ConfigSectionName); + configMock.Received(1).GetSection(ConfigSectionName); AddMicrosoftWebApp_TestCommon(services, provider); AddMicrosoftWebApp_TestSubscribesToDiagnostics(services, diagnosticsMock, subscribeToDiagnostics); @@ -105,7 +105,7 @@ public void AddMicrosoftWebAppAuthentication_WithConfigNameParameters(bool subsc // Assert config bind actions added correctly provider.GetRequiredService>().Create(OidcScheme); provider.GetRequiredService>().Create(string.Empty); - configMock.Received(2).GetSection(ConfigSectionName); + configMock.Received(1).GetSection(ConfigSectionName); AddMicrosoftWebApp_TestCommon(services, provider); AddMicrosoftWebApp_TestSubscribesToDiagnostics(services, diagnosticsMock, subscribeToDiagnostics); @@ -241,7 +241,8 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigNameParameters() var services = new ServiceCollection(); var builder = services.AddAuthentication() - .AddMicrosoftWebAppCallsWebApi(configMock, initialScopes, ConfigSectionName, OidcScheme); + .AddMicrosoftWebApp(configMock, ConfigSectionName, OidcScheme) + .CallsWebApi(initialScopes); services.Configure(OidcScheme, (options) => { options.Events ??= new OpenIdConnectEvents(); @@ -281,7 +282,8 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigActionParameters() var services = new ServiceCollection(); var builder = services.AddAuthentication() - .AddMicrosoftWebAppCallsWebApi(initialScopes, _configureMsOptions, _configureAppOptions, OidcScheme); + .AddMicrosoftWebApp(_configureMsOptions, null, OidcScheme) + .CallsWebApi(_configureAppOptions, initialScopes); services.Configure(OidcScheme, (options) => { options.Events ??= new OpenIdConnectEvents(); @@ -317,7 +319,8 @@ public void AddMicrosoftWebAppCallsWebApi_NoScopes() var services = new ServiceCollection(); services.AddAuthentication() - .AddMicrosoftWebAppCallsWebApi(Substitute.For()); + .AddMicrosoftWebApp(Substitute.For()) + .CallsWebApi(); var provider = services.BuildServiceProvider(); From aa71f4594c77bde9e27c5f4afcc137acbde96bb3 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Wed, 5 Aug 2020 11:31:48 +0200 Subject: [PATCH 06/28] Renamings an clean-up discussed with DevDiv - Renaming AddMicrosoftWebApp to AddMicrosoftIdentityPlatformWebApp, - Renaming AddMicrosoftWebApi to AddMicrosoftIdentityPlatformWebApi, - MicrososoftAppCallingWebApiAuthenticationBuilder.AddInXXXTokenCaches etc ... return their parent builder. --- .../Services/DownstreamWebApi.cs | 4 ++ .../Microsoft.Identity.Web.xml | 4 +- .../WebApiAuthenticationBuilderExtensions.cs | 2 +- .../WebApiServiceCollectionExtensions.cs | 2 +- ...ftAppCallingWebApiAuthenticationBuilder.cs | 12 ++-- .../WebAppAuthenticationBuilderExtensions.cs | 4 +- .../WebApiExtensionsTests.cs | 6 +- tests/WebAppCallsMicrosoftGraph/Startup.cs | 55 ++++++++++++------- .../TodoListService/Startup.cs | 2 +- 9 files changed, 54 insertions(+), 37 deletions(-) diff --git a/ProjectTemplates/templates/StarterWeb-CSharp/Services/DownstreamWebApi.cs b/ProjectTemplates/templates/StarterWeb-CSharp/Services/DownstreamWebApi.cs index 4806ca192..edaa1faa8 100644 --- a/ProjectTemplates/templates/StarterWeb-CSharp/Services/DownstreamWebApi.cs +++ b/ProjectTemplates/templates/StarterWeb-CSharp/Services/DownstreamWebApi.cs @@ -48,6 +48,7 @@ public DownstreamWebApi( /// A JSON string representing the result of calling the Web API public async Task CallWebApiAsync(string relativeEndpoint = "", string[] requiredScopes = null) { + // Do not read directly from config. string[] scopes = requiredScopes ?? _configuration["CalledApi:CalledApiScopes"]?.Split(' '); string apiUrl = (_configuration["CalledApi:CalledApiUrl"] as string)?.TrimEnd('/') + $"/{relativeEndpoint}"; @@ -57,6 +58,9 @@ public async Task CallWebApiAsync(string relativeEndpoint = "", string[] string apiResult; var response = await _httpClient.SendAsync(httpRequestMessage); + + + // Return the HttpReponse!!! if (response.StatusCode == HttpStatusCode.OK) { apiResult = await response.Content.ReadAsStringAsync(); diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index b359e9db3..8ba4e4c8c 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1246,7 +1246,7 @@ Creates an MSAL confidential client application. - + Gets an access token for a downstream API on behalf of the user described by its claimsPrincipal. @@ -1257,7 +1257,7 @@ on behalf of the user described in the claimsPrincipal. Azure AD B2C user flow to target. - + Gets an access token for a downstream API on behalf of the user which account is passed as an argument. diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs index 82fdf66e0..39015675c 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs @@ -31,7 +31,7 @@ public static partial class WebApiAuthenticationBuilderExtensions /// Set to true if you want to debug, or just understand the JWT bearer events. /// /// The authentication builder to chain. - public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoftWebApi( + public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoftIdentityPlatformWebApi( this AuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs index 4084f6b33..423e96730 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs @@ -32,7 +32,7 @@ public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApiAuthenticat bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) { AuthenticationBuilder builder = services.AddAuthentication(jwtBearerScheme); - return builder.AddMicrosoftWebApi( + return builder.AddMicrosoftIdentityPlatformWebApi( configuration, configSectionName, jwtBearerScheme, diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs index 55ea04e06..d56a479ae 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs @@ -32,30 +32,30 @@ internal MicrososoftAppCallingWebApiAuthenticationBuilder( /// Add in memory token caches. /// /// the service collection. - public IServiceCollection AddInMemoryTokenCaches() + public MicrososoftAppCallingWebApiAuthenticationBuilder AddInMemoryTokenCaches() { Services.AddMemoryCache(); Services.AddHttpContextAccessor(); Services.AddSingleton(); - return Services; + return this; } /// /// Add distributed token caches. /// /// the service collection. - public IServiceCollection AddDistributedTokenCaches() + public MicrososoftAppCallingWebApiAuthenticationBuilder AddDistributedTokenCaches() { Services.AddDistributedAppTokenCache(); Services.AddDistributedUserTokenCache(); - return Services; + return this; } /// /// Add session token caches. /// /// the service collection. - public IServiceCollection AddSessionTokenCaches() + public MicrososoftAppCallingWebApiAuthenticationBuilder AddSessionTokenCaches() { // Add session if you are planning to use session based token cache var sessionStoreService = Services.FirstOrDefault(x => x.ServiceType.Name == "ISessionStore"); @@ -90,7 +90,7 @@ public IServiceCollection AddSessionTokenCaches() return httpContext.Session; }); - return Services; + return this; } } } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs index 3f2e31aa3..67b48f464 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs @@ -54,7 +54,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft IConfigurationSection configurationSection = configuration.GetSection(configSectionName); - return builder.AddMicrosoftWebApp( + return builder.AddMicrosoftIdentityPlatformWebApp( configurationSection, openIdConnectScheme, cookieScheme, @@ -73,7 +73,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft /// Set to true if you want to debug, or just understand the OpenID Connect events. /// /// The authentication builder for chaining. - public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftWebApp( + public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityPlatformWebApp( this AuthenticationBuilder builder, IConfigurationSection configurationSection, string openIdConnectScheme = OpenIdConnectDefaults.AuthenticationScheme, diff --git a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs index 1167f778a..8c9d30433 100644 --- a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs @@ -61,7 +61,7 @@ public void AddMicrosoftWebApi_WithConfigName() .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftWebApi(config, ConfigSectionName, JwtBearerScheme, true); + .AddMicrosoftIdentityPlatformWebApi(config, ConfigSectionName, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); @@ -158,7 +158,7 @@ public void AddMicrosoftWebApi_WithConfigName_JwtBearerTokenValidatedEventCalled .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftWebApi(config, ConfigSectionName, JwtBearerScheme, true); + .AddMicrosoftIdentityPlatformWebApi(config, ConfigSectionName, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); @@ -233,7 +233,7 @@ public void AddMicrosoftWebApi_WithConfigName_SubscribesToDiagnostics(bool subsc .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftWebApi(config, ConfigSectionName, JwtBearerScheme, subscribeToDiagnostics); + .AddMicrosoftIdentityPlatformWebApi(config, ConfigSectionName, JwtBearerScheme, subscribeToDiagnostics); services.RemoveAll(); services.AddSingleton((provider) => diagnostics); diff --git a/tests/WebAppCallsMicrosoftGraph/Startup.cs b/tests/WebAppCallsMicrosoftGraph/Startup.cs index a8176fd05..7f813cdcd 100644 --- a/tests/WebAppCallsMicrosoftGraph/Startup.cs +++ b/tests/WebAppCallsMicrosoftGraph/Startup.cs @@ -28,29 +28,42 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftWebApp(Configuration.GetSection("AzureAd")) - .CallsWebApi() - .AddInMemoryTokenCaches(); -/* OR - services.AddMicrosoftWebAppAuthentication(Configuration) - .CallsWebApi() - .AddInMemoryTokenCaches(); + .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) + .CallsWebApi() + .AddInMemoryTokenCaches(); // Add a delegate overload. Should return the parent builder + + /* + * services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) + .CallsWebApi() + .AddInMemoryTokenCaches() // Change the builder + + .AddAuthentication() + .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAd")) - services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftWebApp(options => - { - Configuration.Bind("AzureAd", options); - // do something - }) - .CallsWebApi(options => - { - Configuration.Bind("AzureAd", options); - // do something - } - ) - .AddInMemoryTokenCaches(); */ - services.AddMicrosoftGraph(Configuration, new string[] { "user.read" }); + + + /* OR + services.AddMicrosoftWebAppAuthentication(Configuration) + .CallsWebApi() + .AddInMemoryTokenCaches(); + + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftWebApp(options => + { + Configuration.Bind("AzureAd", options); + // do something + }) + .CallsWebApi(options => + { + Configuration.Bind("AzureAd", options); + // do something + } + ) + .AddInMemoryTokenCaches(); + */ + services.AddMicrosoftGraph(Configuration, new string[] { "user.read" }); services.AddRazorPages().AddMvcOptions(options => { diff --git a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs index c9aa16f54..665188228 100644 --- a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs @@ -33,7 +33,7 @@ public void ConfigureServices(IServiceCollection services) // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddMicrosoftWebApi(Configuration, "AzureAd") + .AddMicrosoftIdentityPlatformWebApi(Configuration, "AzureAd") .CallsWebApi() .AddInMemoryTokenCaches(); From f84bc4b1e95e920a82bda882945f34a48c69b7d4 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Wed, 5 Aug 2020 14:02:38 +0200 Subject: [PATCH 07/28] More renaming --- src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml | 4 ++-- .../WebApiExtensions/WebApiServiceCollectionExtensions.cs | 2 +- .../WebAppExtensions/WebAppServiceCollectionExtensions.cs | 2 +- tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs | 2 +- tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs | 2 +- tests/blazorwasm2/Server/Startup.cs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 8ba4e4c8c..2777c3d3f 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1676,7 +1676,7 @@ Extensions for for startup initialization of web APIs. - + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. @@ -1852,7 +1852,7 @@ The builder for chaining. - + Add authentication with Microsoft identity platform. This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs index 423e96730..4e16a9f26 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs @@ -24,7 +24,7 @@ public static partial class WebApiServiceCollectionExtensions /// /// Set to true if you want to debug, or just understand the JwtBearer events. /// The authentication builder to chain extension methods. - public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApiAuthentication( + public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftIdentityPlatformWebApiAuthentication( this IServiceCollection services, IConfiguration configuration, string configSectionName = Constants.AzureAd, diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs index fa29e57a5..2629f0109 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs @@ -32,7 +32,7 @@ public static partial class WebAppServiceCollectionExtensions /// Set to true if you want to debug, or just understand the OpenIdConnect events. /// /// The authentication builder to chain extension methods. - public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftWebAppAuthentication( + public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityPlatformWebAppAuthentication( this IServiceCollection services, IConfiguration configuration, string configSectionName = Constants.AzureAd, diff --git a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs index 8c9d30433..4be333ec9 100644 --- a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs @@ -106,7 +106,7 @@ public void AddMicrosoftWebApiAuthentication_WithConfigName() var services = new ServiceCollection() .AddLogging(); - services.AddMicrosoftWebApiAuthentication(config, ConfigSectionName, JwtBearerScheme, true); + services.AddMicrosoftIdentityPlatformWebApiAuthentication(config, ConfigSectionName, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); diff --git a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs index 9de617e7b..d96f9aaff 100644 --- a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs @@ -93,7 +93,7 @@ public void AddMicrosoftWebAppAuthentication_WithConfigNameParameters(bool subsc services.AddDataProtection(); - services.AddMicrosoftWebAppAuthentication( + services.AddMicrosoftIdentityPlatformWebAppAuthentication( configMock, ConfigSectionName, OidcScheme, diff --git a/tests/blazorwasm2/Server/Startup.cs b/tests/blazorwasm2/Server/Startup.cs index e35312dea..dc1783229 100644 --- a/tests/blazorwasm2/Server/Startup.cs +++ b/tests/blazorwasm2/Server/Startup.cs @@ -24,7 +24,7 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api - services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAd"); + services.AddMicrosoftIdentityPlatformWebApiAuthentication(Configuration, "AzureAd"); services.AddControllersWithViews(); services.AddRazorPages(); From 2f7ad849267e8295fdc1a08a451c4cf0d3e57460 Mon Sep 17 00:00:00 2001 From: pmaytak <34331512+pmaytak@users.noreply.github.com> Date: Wed, 5 Aug 2020 16:38:17 -0700 Subject: [PATCH 08/28] Test fix. --- tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs index d96f9aaff..c2ad007df 100644 --- a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs @@ -233,6 +233,7 @@ public async Task AddMicrosoftWebApp_WithConfigActionParameters_B2cSpecificSetup public async Task AddMicrosoftWebAppCallsWebApi_WithConfigNameParameters() { var configMock = Substitute.For(); + configMock.Configure().GetSection(ConfigSectionName).Returns(_configSection); var initialScopes = new List() { "custom_scope" }; var tokenAcquisitionMock = Substitute.For(); var authCodeReceivedFuncMock = Substitute.For>(); @@ -260,7 +261,7 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigNameParameters() provider.GetRequiredService>().Create(string.Empty); provider.GetRequiredService>().Create(string.Empty); - configMock.Received(2).GetSection(ConfigSectionName); + configMock.Received(1).GetSection(ConfigSectionName); var oidcOptions = provider.GetRequiredService>().Create(OidcScheme); From e2efa7c80e56c335c986f0829b96cf9373ba5198 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Sat, 8 Aug 2020 20:58:17 +0200 Subject: [PATCH 09/28] Renaming of more overrides --- src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml | 6 +++--- .../WebApiAuthenticationBuilderExtensions.cs | 2 +- .../WebAppAuthenticationBuilderExtensions.cs | 2 +- .../WebAppServiceCollectionExtensions.cs | 2 +- tests/B2CWebAppCallsWebApi/Client/Startup.cs | 2 +- tests/B2CWebAppCallsWebApi/TodoListService/Startup.cs | 2 +- tests/BlazorServerCallsGraph/Startup.cs | 2 +- .../WebApiExtensionsTests.cs | 6 +++--- .../WebAppExtensionsTests.cs | 10 +++++----- tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs | 2 +- 10 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 2777c3d3f..b69fc169e 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1746,7 +1746,7 @@ Extension for IServiceCollection for startup initialization of Web APIs. - + Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. @@ -1836,7 +1836,7 @@ Extensions for the for startup initialization. - + Add authentication to a Web app with Microsoft identity platform. This method expects the configuration file will have a section, named "AzureAd" as default, @@ -1963,7 +1963,7 @@ Extension for IServiceCollection for startup initialization. - + Add authentication with Microsoft identity platform. This method expects the configuration file will have a section, (by default named "AzureAd"), with the necessary settings to diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs index 39015675c..4248127d6 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs @@ -108,7 +108,7 @@ public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoft /// /// Set to true if you want to debug, or just understand the JWT bearer events. /// The authentication builder to chain. - public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftWebApi( + public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftIdentityPlatformWebApi( this AuthenticationBuilder builder, Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions, diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs index 67b48f464..b99ea77dc 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs @@ -34,7 +34,7 @@ public static partial class WebAppAuthenticationBuilderExtensions /// Set to true if you want to debug, or just understand the OpenID Connect events. /// /// The builder for chaining. - public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftWebApp( + public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityPlatformWebApp( this AuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs index 2629f0109..cc5555b6a 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs @@ -41,7 +41,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false) { AuthenticationBuilder builder = services.AddAuthentication(openIdConnectScheme); - return builder.AddMicrosoftWebApp( + return builder.AddMicrosoftIdentityPlatformWebApp( configuration, configSectionName, openIdConnectScheme, diff --git a/tests/B2CWebAppCallsWebApi/Client/Startup.cs b/tests/B2CWebAppCallsWebApi/Client/Startup.cs index 60a2fcc22..c1a6a9336 100644 --- a/tests/B2CWebAppCallsWebApi/Client/Startup.cs +++ b/tests/B2CWebAppCallsWebApi/Client/Startup.cs @@ -43,7 +43,7 @@ public void ConfigureServices(IServiceCollection services) services.AddOptions(); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftWebApp(Configuration, "AzureAdB2C") + .AddMicrosoftIdentityPlatformWebApp(Configuration, "AzureAdB2C") .CallsWebApi(initialScopes: new string[] { Configuration["TodoList:TodoListScope"] }) .AddInMemoryTokenCaches(); diff --git a/tests/B2CWebAppCallsWebApi/TodoListService/Startup.cs b/tests/B2CWebAppCallsWebApi/TodoListService/Startup.cs index 651173b0b..dd859c0d6 100644 --- a/tests/B2CWebAppCallsWebApi/TodoListService/Startup.cs +++ b/tests/B2CWebAppCallsWebApi/TodoListService/Startup.cs @@ -34,7 +34,7 @@ public void ConfigureServices(IServiceCollection services) // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddMicrosoftWebApi(options => + .AddMicrosoftIdentityPlatformWebApi(options => { Configuration.Bind(sectionName, options); options.TokenValidationParameters.NameClaimType = "name"; diff --git a/tests/BlazorServerCallsGraph/Startup.cs b/tests/BlazorServerCallsGraph/Startup.cs index c218aa6fc..6e5d1dffd 100644 --- a/tests/BlazorServerCallsGraph/Startup.cs +++ b/tests/BlazorServerCallsGraph/Startup.cs @@ -29,7 +29,7 @@ public void ConfigureServices(IServiceCollection services) { string[] scopes = Configuration.GetValue("CalledApi:CalledApiScopes")?.Split(' '); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftWebApp(Configuration, "AzureAd") + .AddMicrosoftIdentityPlatformWebApp(Configuration, "AzureAd") .CallsWebApi(scopes) .AddInMemoryTokenCaches(); diff --git a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs index 4be333ec9..640f11d8d 100644 --- a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs @@ -80,7 +80,7 @@ public void AddMicrosoftWebApi_WithConfigActions() .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, true); + .AddMicrosoftIdentityPlatformWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); @@ -181,7 +181,7 @@ public void AddMicrosoftWebApi_WithConfigActions_JwtBearerTokenValidatedEventCal .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, true); + .AddMicrosoftIdentityPlatformWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); @@ -263,7 +263,7 @@ public void AddMicrosoftWebApi_WithConfigActions_SubscribesToDiagnostics(bool su .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, subscribeToDiagnostics); + .AddMicrosoftIdentityPlatformWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, subscribeToDiagnostics); services.RemoveAll(); services.AddSingleton((provider) => diagnostics); diff --git a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs index c2ad007df..5740a85cc 100644 --- a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs @@ -66,7 +66,7 @@ public void AddMicrosoftWebApp_WithConfigNameParameters(bool subscribeToDiagnost services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, subscribeToDiagnostics); + .AddMicrosoftIdentityPlatformWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, subscribeToDiagnostics); var provider = services.BuildServiceProvider(); @@ -157,7 +157,7 @@ public async Task AddMicrosoftWebApp_WithConfigNameParameters_TestRedirectToIden services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); + .AddMicrosoftIdentityPlatformWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); await AddMicrosoftWebApp_TestRedirectToIdentityProviderEvent(services, redirectFunc).ConfigureAwait(false); } @@ -197,7 +197,7 @@ public async Task AddMicrosoftWebApp_WithConfigNameParameters_TestB2cSpecificSet services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); + .AddMicrosoftIdentityPlatformWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); await AddMicrosoftWebApp_TestB2cSpecificSetup(services, remoteFailureFuncMock).ConfigureAwait(false); } @@ -242,7 +242,7 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigNameParameters() var services = new ServiceCollection(); var builder = services.AddAuthentication() - .AddMicrosoftWebApp(configMock, ConfigSectionName, OidcScheme) + .AddMicrosoftIdentityPlatformWebApp(configMock, ConfigSectionName, OidcScheme) .CallsWebApi(initialScopes); services.Configure(OidcScheme, (options) => { @@ -320,7 +320,7 @@ public void AddMicrosoftWebAppCallsWebApi_NoScopes() var services = new ServiceCollection(); services.AddAuthentication() - .AddMicrosoftWebApp(Substitute.For()) + .AddMicrosoftIdentityPlatformWebApp(Substitute.For()) .CallsWebApi(); var provider = services.BuildServiceProvider(); diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs index 4871a228d..8e19e0187 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs @@ -44,7 +44,7 @@ public void ConfigureServices(IServiceCollection services) services.AddOptions(); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftWebApp(Configuration, "AzureAd") + .AddMicrosoftIdentityPlatformWebApp(Configuration, "AzureAd") .CallsWebApi() .AddInMemoryTokenCaches(); From 2c8c092d16259be5f67ebceae307cc8fb1996146 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Sat, 8 Aug 2020 22:43:54 +0200 Subject: [PATCH 10/28] Updating the templates --- ...icrosoftIdentityWebProjectTemplates.csproj | 2 +- .../BlazorServerWeb-CSharp.csproj | 4 +-- .../BlazorServerWeb-CSharp/Startup.cs | 20 ++++++------- ...ComponentsWebAssembly-CSharp.Server.csproj | 2 +- .../Server/Startup.cs | 20 ++++++------- .../Company.WebApplication1.csproj | 4 +-- .../templates/RazorPagesWeb-CSharp/Startup.cs | 26 ++++++----------- .../Company.WebApplication1.csproj | 4 +-- .../templates/StarterWeb-CSharp/Startup.cs | 28 ++++++------------- .../Company.WebApplication1.csproj | 2 +- .../templates/WebApi-CSharp/Startup.cs | 25 ++++++----------- ProjectTemplates/test-templates.bat | 2 +- .../Microsoft.Identity.Web.xml | 2 +- tests/B2CWebAppCallsWebApi/Client/Startup.cs | 1 - tests/BlazorServerCallsGraph/Startup.cs | 1 - .../Client/Startup.cs | 1 - .../TodoListService/Startup.cs | 1 - 17 files changed, 55 insertions(+), 90 deletions(-) diff --git a/ProjectTemplates/AspNetCoreMicrosoftIdentityWebProjectTemplates.csproj b/ProjectTemplates/AspNetCoreMicrosoftIdentityWebProjectTemplates.csproj index 2b078705c..c5155f10e 100644 --- a/ProjectTemplates/AspNetCoreMicrosoftIdentityWebProjectTemplates.csproj +++ b/ProjectTemplates/AspNetCoreMicrosoftIdentityWebProjectTemplates.csproj @@ -2,7 +2,7 @@ - 0.2.1-preview + 0.3.0-preview $(ClientSemVer) diff --git a/ProjectTemplates/templates/BlazorServerWeb-CSharp/BlazorServerWeb-CSharp.csproj b/ProjectTemplates/templates/BlazorServerWeb-CSharp/BlazorServerWeb-CSharp.csproj index fcc8448b5..ef6cf163c 100644 --- a/ProjectTemplates/templates/BlazorServerWeb-CSharp/BlazorServerWeb-CSharp.csproj +++ b/ProjectTemplates/templates/BlazorServerWeb-CSharp/BlazorServerWeb-CSharp.csproj @@ -3,8 +3,8 @@ netcoreapp3.1; net5.0 - - + + diff --git a/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs b/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs index 5ee1523ab..eb97e13cc 100644 --- a/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs +++ b/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs @@ -4,9 +4,9 @@ using System.Threading.Tasks; #if (OrganizationalAuth || IndividualB2CAuth) using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.Identity.Web; using Microsoft.Identity.Web.UI; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; #endif #if (OrganizationalAuth) #if (MultiOrgAuth) @@ -75,12 +75,11 @@ public void ConfigureServices(IServiceCollection services) #if (GenerateApiOrGraph) string[] scopes = Configuration.GetValue("CalledApi:CalledApiScopes")?.Split(' '); #endif - services.AddMicrosoftWebAppAuthentication(Configuration, "AzureAd") + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .AddMicrosoftWebAppCallsWebApi(Configuration, - scopes, - "AzureAd") - .AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); #else ; #endif @@ -95,12 +94,11 @@ public void ConfigureServices(IServiceCollection services) #if (GenerateApi) string[] scopes = Configuration.GetValue("CalledApi:CalledApiScopes")?.Split(' '); #endif - services.AddMicrosoftWebAppAuthentication(Configuration, "AzureAdB2C") + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .AddMicrosoftWebAppCallsWebApi(Configuration, - scopes, - "AzureAdB2C") - .AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); #else diff --git a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/ComponentsWebAssembly-CSharp.Server.csproj b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/ComponentsWebAssembly-CSharp.Server.csproj index e79ad45a7..8a5549bac 100644 --- a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/ComponentsWebAssembly-CSharp.Server.csproj +++ b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/ComponentsWebAssembly-CSharp.Server.csproj @@ -4,7 +4,7 @@ - + diff --git a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs index 0d25e68a1..ae4030760 100644 --- a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs +++ b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs @@ -3,8 +3,8 @@ #endif using Microsoft.AspNetCore.Builder; #if (OrganizationalAuth || IndividualB2CAuth) +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Identity.Web; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; #endif #if (RequiresHttps) using Microsoft.AspNetCore.HttpsPolicy; @@ -61,13 +61,11 @@ public void ConfigureServices(IServiceCollection services) .AddIdentityServerJwt(); #endif #if (OrganizationalAuth) - // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api - services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAd") + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .AddMicrosoftWebApiCallsWebApi(Configuration, - "AzureAd") - .AddInMemoryTokenCaches(); - + .CallsWebApi() + .AddInMemoryTokenCaches(); #else ; #endif @@ -79,11 +77,11 @@ public void ConfigureServices(IServiceCollection services) Configuration.GetValue("CalledApi:CalledApiUrl")); #endif #elif (IndividualB2CAuth) - services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAdB2C") + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .AddMicrosoftWebApiCallsWebApi(Configuration, - "AzureAdB2C") - .AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); #else diff --git a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Company.WebApplication1.csproj b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Company.WebApplication1.csproj index 4f2854b90..b63175550 100644 --- a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Company.WebApplication1.csproj +++ b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Company.WebApplication1.csproj @@ -3,8 +3,8 @@ netcoreapp3.1; net5.0 - - + + diff --git a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs index 242f93d1e..c47850c2d 100644 --- a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs +++ b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs @@ -4,21 +4,11 @@ using System.Threading.Tasks; #if (OrganizationalAuth || IndividualB2CAuth) using Microsoft.AspNetCore.Authentication; -#endif -#if (OrganizationalAuth) using Microsoft.Identity.Web; using Microsoft.Identity.Web.UI; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; -#if (MultiOrgAuth) using Microsoft.AspNetCore.Authentication.OpenIdConnect; -#endif using Microsoft.AspNetCore.Authorization; #endif -#if (IndividualB2CAuth) -using Microsoft.Identity.Web; -using Microsoft.Identity.Web.UI; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; -#endif using Microsoft.AspNetCore.Builder; #if (IndividualLocalAuth) using Microsoft.AspNetCore.Identity; @@ -71,11 +61,11 @@ public void ConfigureServices(IServiceCollection services) services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); #elif (OrganizationalAuth) - services.AddMicrosoftWebAppAuthentication(Configuration, "AzureAd") + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .AddMicrosoftWebAppCallsWebApi(Configuration, - "AzureAd") - .AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); #else ; #endif @@ -87,11 +77,11 @@ public void ConfigureServices(IServiceCollection services) Configuration.GetValue("CalledApi:CalledApiUrl")); #endif #elif (IndividualB2CAuth) - services.AddMicrosoftWebAppAuthentication(Configuration, "AzureAdB2C") + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .AddMicrosoftWebAppCallsWebApi(Configuration, - "AzureAdB2C") - .AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); #else diff --git a/ProjectTemplates/templates/StarterWeb-CSharp/Company.WebApplication1.csproj b/ProjectTemplates/templates/StarterWeb-CSharp/Company.WebApplication1.csproj index c6e263d57..b9fdca64a 100644 --- a/ProjectTemplates/templates/StarterWeb-CSharp/Company.WebApplication1.csproj +++ b/ProjectTemplates/templates/StarterWeb-CSharp/Company.WebApplication1.csproj @@ -3,8 +3,8 @@ netcoreapp3.1; net5.0 - - + + diff --git a/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs b/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs index 72af4c5e5..895604d6b 100644 --- a/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs +++ b/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs @@ -4,20 +4,10 @@ using System.Threading.Tasks; #if (OrganizationalAuth || IndividualB2CAuth) using Microsoft.AspNetCore.Authentication; -#endif -#if (OrganizationalAuth) -using Microsoft.Identity.Web; -using Microsoft.Identity.Web.UI; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; -#if (MultiOrgAuth) using Microsoft.AspNetCore.Authentication.OpenIdConnect; -#endif -using Microsoft.AspNetCore.Authorization; -#endif -#if (IndividualB2CAuth) using Microsoft.Identity.Web; using Microsoft.Identity.Web.UI; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; +using Microsoft.AspNetCore.Authorization; #endif using Microsoft.AspNetCore.Builder; #if (IndividualLocalAuth) @@ -71,11 +61,11 @@ public void ConfigureServices(IServiceCollection services) services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores(); #elif (OrganizationalAuth) - services.AddMicrosoftWebAppAuthentication(Configuration, "AzureAd") + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .AddMicrosoftWebAppCallsWebApi(Configuration, - "AzureAd") - .AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); #else ; #endif @@ -87,11 +77,11 @@ public void ConfigureServices(IServiceCollection services) Configuration.GetValue("CalledApi:CalledApiUrl")); #endif #elif (IndividualB2CAuth) - services.AddMicrosoftWebAppAuthentication(Configuration, "AzureAdB2C") + services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .AddMicrosoftWebAppCallsWebApi(Configuration, - "AzureAdB2C") - .AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); #else diff --git a/ProjectTemplates/templates/WebApi-CSharp/Company.WebApplication1.csproj b/ProjectTemplates/templates/WebApi-CSharp/Company.WebApplication1.csproj index 460dc1f6a..066435e68 100644 --- a/ProjectTemplates/templates/WebApi-CSharp/Company.WebApplication1.csproj +++ b/ProjectTemplates/templates/WebApi-CSharp/Company.WebApplication1.csproj @@ -3,7 +3,7 @@ netcoreapp3.1; net5.0 - + diff --git a/ProjectTemplates/templates/WebApi-CSharp/Startup.cs b/ProjectTemplates/templates/WebApi-CSharp/Startup.cs index a67f026b9..ab3c75c7f 100644 --- a/ProjectTemplates/templates/WebApi-CSharp/Startup.cs +++ b/ProjectTemplates/templates/WebApi-CSharp/Startup.cs @@ -9,15 +9,9 @@ #endif using Microsoft.AspNetCore.Mvc; #if (OrganizationalAuth || IndividualB2CAuth) +using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication; -#endif -#if (OrganizationalAuth) -using Microsoft.Identity.Web; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; -#endif -#if (IndividualB2CAuth) using Microsoft.Identity.Web; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; #endif using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -41,12 +35,11 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { #if (OrganizationalAuth) - // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api - services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAd") + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .AddMicrosoftWebApiCallsWebApi(Configuration, - "AzureAd") - .AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); #else ; @@ -59,11 +52,11 @@ public void ConfigureServices(IServiceCollection services) Configuration.GetValue("CalledApi:CalledApiUrl")); #endif #elif (IndividualB2CAuth) - services.AddMicrosoftWebApiAuthentication(Configuration, "AzureAdB2C") + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .AddMicrosoftWebApiCallsWebApi(Configuration, - "AzureAdB2C") - .AddInMemoryTokenCaches(); + .CallsWebApi() + .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); #else diff --git a/ProjectTemplates/test-templates.bat b/ProjectTemplates/test-templates.bat index 4e7b2b955..e1eff29b8 100644 --- a/ProjectTemplates/test-templates.bat +++ b/ProjectTemplates/test-templates.bat @@ -2,7 +2,7 @@ echo "Build and Install templates" dotnet pack AspNetCoreMicrosoftIdentityWebProjectTemplates.csproj cd bin cd Debug -dotnet new -i Microsoft.Identity.Web.ProjectTemplates.0.2.1-preview.nupkg +dotnet new -i Microsoft.Identity.Web.ProjectTemplates.0.3.0-preview.nupkg echo "Test templates" mkdir tests diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index b69fc169e..59ffd7301 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1703,7 +1703,7 @@ The authentication builder to chain. - + Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0). diff --git a/tests/B2CWebAppCallsWebApi/Client/Startup.cs b/tests/B2CWebAppCallsWebApi/Client/Startup.cs index c1a6a9336..af68d1191 100644 --- a/tests/B2CWebAppCallsWebApi/Client/Startup.cs +++ b/tests/B2CWebAppCallsWebApi/Client/Startup.cs @@ -9,7 +9,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Identity.Web; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; using TodoListClient.Services; using Microsoft.Extensions.Hosting; using Microsoft.AspNetCore.Authentication.OpenIdConnect; diff --git a/tests/BlazorServerCallsGraph/Startup.cs b/tests/BlazorServerCallsGraph/Startup.cs index 6e5d1dffd..1f776650a 100644 --- a/tests/BlazorServerCallsGraph/Startup.cs +++ b/tests/BlazorServerCallsGraph/Startup.cs @@ -3,7 +3,6 @@ using Microsoft.Identity.Web; using Microsoft.Identity.Web.UI; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs index 8e19e0187..220954889 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs @@ -9,7 +9,6 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Identity.Web; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; using TodoListClient.Services; using Microsoft.Extensions.Hosting; diff --git a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs index 665188228..ad2ae1cc7 100644 --- a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs @@ -9,7 +9,6 @@ using Microsoft.Identity.Web; using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Identity.Web.TokenCacheProviders.InMemory; namespace TodoListService { From e7a3c1048a4429ceed32a12f08fca181d0627e57 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Sat, 8 Aug 2020 20:16:44 -0700 Subject: [PATCH 11/28] initial commit api w/microsoftIdentity --- .../Microsoft.Identity.Web.csproj | 4 - .../Microsoft.Identity.Web.xml | 294 +++++++++--------- ...osoftIdentityBaseAuthenticationBuilder.cs} | 6 +- ...sWebApiAuthenticationBuilderExtensions.cs} | 10 +- ...sWebApiAuthenticationBuilderExtensions.cs} | 26 +- ...oftIdentityWebApiAuthenticationBuilder.cs} | 8 +- ...yWebApiAuthenticationBuilderExtensions.cs} | 12 +- ...AuthenticationBuilderWithConfiguration.cs} | 6 +- ...ntityWebApiServiceCollectionExtensions.cs} | 8 +- ...yAppCallingWebApiAuthenticationBuilder.cs} | 12 +- ...oftIdentityWebAppAuthenticationBuilder.cs} | 16 +- ...yWebAppAuthenticationBuilderExtensions.cs} | 44 +-- ...AuthenticationBuilderWithConfiguration.cs} | 12 +- ...ntityWebAppServiceCollectionExtensions.cs} | 8 +- tests/B2CWebAppCallsWebApi/Client/Startup.cs | 2 +- .../TodoListService/Startup.cs | 2 +- tests/BlazorServerCallsGraph/Startup.cs | 2 +- .../WebApiExtensionsTests.cs | 14 +- .../WebAppExtensionsTests.cs | 12 +- tests/WebAppCallsMicrosoftGraph/Startup.cs | 2 +- .../Client/Startup.cs | 2 +- .../TodoListService/Startup.cs | 2 +- tests/blazorwasm2/Server/Startup.cs | 2 +- 23 files changed, 251 insertions(+), 255 deletions(-) rename src/Microsoft.Identity.Web/{MicrosoftBaseAuthenticationBuilder.cs => MicrosoftIdentityBaseAuthenticationBuilder.cs} (85%) rename src/Microsoft.Identity.Web/{WebApiExtensions/WebApiCallsWebApiAuthenticationBuilderExtensions.cs => MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs} (90%) rename src/Microsoft.Identity.Web/{WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs => MigrationAid/MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExtensions.cs} (85%) rename src/Microsoft.Identity.Web/WebApiExtensions/{MicrosoftWebApiAuthenticationBuilder.cs => MicrosoftIdentityWebApiAuthenticationBuilder.cs} (93%) rename src/Microsoft.Identity.Web/WebApiExtensions/{WebApiAuthenticationBuilderExtensions.cs => MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs} (95%) rename src/Microsoft.Identity.Web/WebApiExtensions/{MicrosoftWebApiAuthenticationBuilderWithConfiguration.cs => MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs} (83%) rename src/Microsoft.Identity.Web/WebApiExtensions/{WebApiServiceCollectionExtensions.cs => MicrosoftIdentityWebApiServiceCollectionExtensions.cs} (86%) rename src/Microsoft.Identity.Web/WebAppExtensions/{MicrososoftAppCallingWebApiAuthenticationBuilder.cs => MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs} (84%) rename src/Microsoft.Identity.Web/WebAppExtensions/{MicrosoftWebAppAuthenticationBuilder.cs => MicrosoftIdentityWebAppAuthenticationBuilder.cs} (92%) rename src/Microsoft.Identity.Web/WebAppExtensions/{WebAppAuthenticationBuilderExtensions.cs => MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs} (92%) rename src/Microsoft.Identity.Web/WebAppExtensions/{MicrosoftWebAppAuthenticationBuilderWithConfiguration.cs => MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs} (75%) rename src/Microsoft.Identity.Web/WebAppExtensions/{WebAppServiceCollectionExtensions.cs => MicrosoftIdentityWebAppServiceCollectionExtensions.cs} (88%) diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj index 75041eaaa..01ea65cab 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj @@ -102,8 +102,4 @@ - - - - diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index b69fc169e..0ef5f1c5e 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -723,25 +723,25 @@ OpenID Connect event. A that represents a completed remove from cache operation. - + - Base class for Web app and Web API Microsoft authentication + Base class for Web app and Web API Microsoft Identity authentication builders. - + Constructor. The services being configured. Optional configuration section. - + The services being configured. - + Configuration section from which to bind options. @@ -905,6 +905,81 @@ Exception thrown by MSAL when a user challenge is encountered. Scopes to request. + + + Extensions for for startup initialization of web APIs. + + + + + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + + The to which to add this configuration. + The configuration instance. + The section name in the config file (by default "AzureAd"). + The scheme for the JWT bearer token. + The authentication builder to chain. + + + + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). + + The to which to add this configuration. + The action to configure . + The action to configure . + The scheme for the JWT bearer token. + The authentication builder to chain. + + + + Extensions for for startup initialization. + + + + + Add MSAL support to the web app or web API. + This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. + + The to which to add this configuration. + The configuration instance. + The name of the configuration section with the necessary + settings to initialize authentication options. + Optional name for the OpenID Connect authentication scheme + (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support + several OpenID Connect identity providers. + The authentication builder for chaining. + This method cannot be used with Azure AD B2C, as with B2C an initial scope needs + to be provided. + + + + + Add MSAL support to the web app or web API. + + The to which to add this configuration. + The configuration instance. + Initial scopes to request at sign-in. + The name of the configuration section with the necessary + settings to initialize authentication options. + Optional name for the OpenID Connect authentication scheme + (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support + several OpenID Connect identity providers. + The authentication builder for chaining. + + + + Add MSAL support to the web app or web API. + + The to which to add this configuration. + Initial scopes to request at sign-in. + The action to set the . + The action to set the . + Optional name for the Open ID Connect authentication scheme + (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support + several OpenID Connect identity providers. + The authentication builder for chaining. + Generic class that validates token issuer from the provided Azure AD authority. @@ -1635,12 +1710,12 @@ The services collection to add to. The service collection. - + Authentication builder for a web API. - + Constructor. @@ -1652,31 +1727,19 @@ Configuration section from which to get parameters. - + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). The action to configure . The authentication builder to chain. - - - Builder for Web API authentication with configuration. - - - - - Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - The authentication builder to chain. - - + Extensions for for startup initialization of web APIs. - + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. @@ -1690,7 +1753,7 @@ The authentication builder to chain. - + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. @@ -1703,7 +1766,7 @@ The authentication builder to chain. - + Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0). @@ -1715,40 +1778,26 @@ Set to true if you want to debug, or just understand the JWT bearer events. The authentication builder to chain. - + - Extensions for for startup initialization of web APIs. + Builder for Web API authentication with configuration. - + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - The to which to add this configuration. - The configuration instance. - The section name in the config file (by default "AzureAd"). - The scheme for the JWT bearer token. - The authentication builder to chain. - - - - Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). - - The to which to add this configuration. - The action to configure . - The action to configure . - The scheme for the JWT bearer token. The authentication builder to chain. - + Extension for IServiceCollection for startup initialization of Web APIs. - + - Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0) This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. Service collection to which to add authentication. @@ -1759,86 +1808,63 @@ Set to true if you want to debug, or just understand the JwtBearer events. The authentication builder to chain extension methods. - + - Authentication builder specific for Microsoft identity platform. + Authentication builder returned by the CallsWebApi methods + enabling you to decide token cache implementations. - + - Constructor. + Add in memory token caches. - The services being configured. - Defaut scheme used for OpenIdConnect. - Action called to configure - the Microsoft identity options. - Optional configuration section. + the service collection. - + - The Web app calls a web api. This overrides enables you to specify the - ConfidentialClientApplicationOptions (from MSAL.NET) programmatically. + Add distributed token caches. - Action to configure the - MSAL.NET confidential client application options. - Initial scopes. - the builder itself for chaining. + the service collection. - + - Builder for a Microsoft web app authentication where configuration is - available for CallsWebApi. + Add session token caches. + + the service collection. + + + + Authentication builder specific for Microsoft Identity. - + Constructor. The services being configured. - Defaut scheme used for OpenIdConnect. + Default scheme used for OpenIdConnect. Action called to configure the Microsoft identity options. Optional configuration section. - + - Add support for the Web app to acquire tokens to call an API. - - Optional initial scopes to request. - The authentication builder for chaining. - - - - Authentication builder returned by the CallsWebApi methods - enabling to decide token cache implementations. - - - - - Add in memory token caches. - - the service collection. - - - - Add distributed token caches. - - the service collection. - - - - Add session token caches. + The Web app calls a Web API. This override enables you to specify the + ConfidentialClientApplicationOptions (from MSAL.NET) programmatically. - the service collection. + Action to configure the + MSAL.NET confidential client application options. + Initial scopes. + The builder itself for chaining. - + Extensions for the for startup initialization. - + - Add authentication to a Web app with Microsoft identity platform. + Add authentication to a web app with Microsoft Identity. This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. @@ -1850,11 +1876,11 @@ Set to true if you want to debug, or just understand the OpenID Connect events. - The builder for chaining. + The builder for chaining. - + - Add authentication with Microsoft identity platform. + Add authentication with Microsoft Identity. This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. The to which to add this configuration. @@ -1866,9 +1892,9 @@ The authentication builder for chaining. - + - Add authentication with Microsoft identity platform. + Add authentication with Microsoft Identity. The to which to add this configuration. The action to configure . @@ -1880,9 +1906,9 @@ The authentication builder for chaining. - + - Add authentication with Microsoft identity platform. + Add authentication with Microsoft Identity. The to which to add this configuration. The action to configure . @@ -1895,9 +1921,9 @@ Configuration section. The authentication builder for chaining. - + - Add authentication with Microsoft identity platform. + Add authentication with Microsoft Identity. The to which to add this configuration. The action to configure . @@ -1909,63 +1935,37 @@ The authentication builder for chaining. - + - Extensions for for startup initialization. + Builder for a Microsoft identity web app authentication where configuration is + available for CallsWebApi. - + - Add MSAL support to the web app or web API. - This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. - - The to which to add this configuration. - The configuration instance. - The name of the configuration section with the necessary - settings to initialize authentication options. - Optional name for the OpenID Connect authentication scheme - (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support - several OpenID Connect identity providers. - The authentication builder for chaining. - This method cannot be used with Azure AD B2C, as with B2C an initial scope needs - to be provided. - - - - - Add MSAL support to the web app or web API. + Constructor. - The to which to add this configuration. - The configuration instance. - Initial scopes to request at sign-in. - The name of the configuration section with the necessary - settings to initialize authentication options. - Optional name for the OpenID Connect authentication scheme - (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support - several OpenID Connect identity providers. - The authentication builder for chaining. + The services being configured. + Default scheme used for OpenIdConnect. + Action called to configure + the Microsoft identity options. + Optional configuration section. - + - Add MSAL support to the web app or web API. + Add support for the web app to acquire tokens to call an API. - The to which to add this configuration. - Initial scopes to request at sign-in. - The action to set the . - The action to set the . - Optional name for the Open ID Connect authentication scheme - (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support - several OpenID Connect identity providers. + Optional initial scopes to request. The authentication builder for chaining. - + Extension for IServiceCollection for startup initialization. - + - Add authentication with Microsoft identity platform. + Add authentication with Microsoft Identity. This method expects the configuration file will have a section, (by default named "AzureAd"), with the necessary settings to initialize the authentication options. diff --git a/src/Microsoft.Identity.Web/MicrosoftBaseAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/MicrosoftIdentityBaseAuthenticationBuilder.cs similarity index 85% rename from src/Microsoft.Identity.Web/MicrosoftBaseAuthenticationBuilder.cs rename to src/Microsoft.Identity.Web/MicrosoftIdentityBaseAuthenticationBuilder.cs index 48ad5e6be..5d4d2a640 100644 --- a/src/Microsoft.Identity.Web/MicrosoftBaseAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/MicrosoftIdentityBaseAuthenticationBuilder.cs @@ -7,17 +7,17 @@ namespace Microsoft.Identity.Web { /// - /// Base class for Web app and Web API Microsoft authentication + /// Base class for Web app and Web API Microsoft Identity authentication /// builders. /// - public abstract class MicrosoftBaseAuthenticationBuilder + public abstract class MicrosoftIdentityBaseAuthenticationBuilder { /// /// Constructor. /// /// The services being configured. /// Optional configuration section. - protected MicrosoftBaseAuthenticationBuilder( + protected MicrosoftIdentityBaseAuthenticationBuilder( IServiceCollection services, IConfigurationSection? configurationSection = null) { diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiCallsWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs similarity index 90% rename from src/Microsoft.Identity.Web/WebApiExtensions/WebApiCallsWebApiAuthenticationBuilderExtensions.cs rename to src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs index 6e2a1c94f..55e612285 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiCallsWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs @@ -2,12 +2,10 @@ // Licensed under the MIT License. using System; -using System.IdentityModel.Tokens.Jwt; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using Microsoft.Identity.Client; namespace Microsoft.Identity.Web @@ -15,7 +13,7 @@ namespace Microsoft.Identity.Web /// /// Extensions for for startup initialization of web APIs. /// - public static partial class WebApiCallsWebApiAuthenticationBuilderExtensions + public static partial class MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions { /// /// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). @@ -26,7 +24,7 @@ public static partial class WebApiCallsWebApiAuthenticationBuilderExtensions /// The section name in the config file (by default "AzureAd"). /// The scheme for the JWT bearer token. /// The authentication builder to chain. - [Obsolete("Rather use MicrosoftWebApiAuthenticationBuilder.CallsWebApi")] + [Obsolete("Rather use AddMicrosoftIdentityWebApi().CallsWebApi")] public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( this AuthenticationBuilder builder, IConfiguration configuration, @@ -47,7 +45,7 @@ public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( /// The action to configure . /// The scheme for the JWT bearer token. /// The authentication builder to chain. - [Obsolete("Rather use MicrosoftWebApiAuthenticationBuilder.CallsWebApi")] + [Obsolete("Rather use AddMicrosoftIdentityWebApi().CallsWebApi")] public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( this AuthenticationBuilder builder, Action configureConfidentialClientApplicationOptions, @@ -71,7 +69,7 @@ public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( builder.Services.Configure(configureMicrosoftIdentityOptions); - MicrosoftWebApiAuthenticationBuilder.CallsWebApiImplementation( + MicrosoftIdentityWebApiAuthenticationBuilder.CallsWebApiImplementation( builder.Services, jwtBearerScheme, configureConfidentialClientApplicationOptions); diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExtensions.cs similarity index 85% rename from src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs rename to src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExtensions.cs index 2fadc227e..a91ea953a 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppCallsWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExtensions.cs @@ -3,22 +3,18 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Security.Claims; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; using Microsoft.Identity.Client; -using Microsoft.IdentityModel.Protocols.OpenIdConnect; namespace Microsoft.Identity.Web { /// /// Extensions for for startup initialization. /// - public static class WebAppCallsWebApiAuthenticationBuilderExtensions + public static class MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExtensions { /// /// Add MSAL support to the web app or web API. @@ -35,9 +31,9 @@ public static class WebAppCallsWebApiAuthenticationBuilderExtensions /// This method cannot be used with Azure AD B2C, as with B2C an initial scope needs /// to be provided. /// - [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] - private static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( - this MicrosoftWebAppAuthenticationBuilder builder, + [Obsolete("Rather use AddMicrosoftIdentityWebApp().CallsWebApi")] + private static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( + this MicrosoftIdentityWebAppAuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, string openIdConnectScheme = OpenIdConnectDefaults.AuthenticationScheme) @@ -61,9 +57,9 @@ private static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebAp /// (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support /// several OpenID Connect identity providers. /// The authentication builder for chaining. - [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] - public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( - this MicrosoftWebAppAuthenticationBuilder builder, + [Obsolete("Rather use AddMicrosoftIdentityWebApp().CallsWebApi")] + public static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( + this MicrosoftIdentityWebAppAuthenticationBuilder builder, IConfiguration configuration, IEnumerable initialScopes, string configSectionName = Constants.AzureAd, @@ -87,9 +83,9 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi /// (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support /// several OpenID Connect identity providers. /// The authentication builder for chaining. - [Obsolete("Rather use MicrosoftAuthenticationBuilder.CallsWebApi")] - public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( - this MicrosoftWebAppAuthenticationBuilder builder, + [Obsolete("Rather use AddMicrosoftIdentityWebApp().CallsWebApi")] + public static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( + this MicrosoftIdentityWebAppAuthenticationBuilder builder, IEnumerable? initialScopes, Action configureMicrosoftIdentityOptions, Action configureConfidentialClientApplicationOptions, @@ -110,7 +106,7 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi throw new ArgumentNullException(nameof(configureConfidentialClientApplicationOptions)); } - MicrosoftWebAppAuthenticationBuilder.WebAppCallsWebApiImplementation( + MicrosoftIdentityWebAppAuthenticationBuilder.WebAppCallsWebApiImplementation( builder.Services, initialScopes, configureMicrosoftIdentityOptions, diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs similarity index 93% rename from src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs rename to src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs index 7b51b6625..f90603420 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs @@ -13,7 +13,7 @@ namespace Microsoft.Identity.Web /// /// Authentication builder for a web API. /// - public class MicrosoftWebApiAuthenticationBuilder : MicrosoftBaseAuthenticationBuilder + public class MicrosoftIdentityWebApiAuthenticationBuilder : MicrosoftIdentityBaseAuthenticationBuilder { /// /// Constructor. @@ -25,7 +25,7 @@ public class MicrosoftWebApiAuthenticationBuilder : MicrosoftBaseAuthenticationB /// the Microsoft identity options. /// Configuration section from which to /// get parameters. - internal MicrosoftWebApiAuthenticationBuilder( + internal MicrosoftIdentityWebApiAuthenticationBuilder( IServiceCollection services, string jwtBearerAuthenticationScheme, Action configureJwtBearerOptions, @@ -61,7 +61,7 @@ internal MicrosoftWebApiAuthenticationBuilder( /// /// The action to configure . /// The authentication builder to chain. - public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi( + public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi( Action configureConfidentialClientApplicationOptions) { if (configureConfidentialClientApplicationOptions == null) @@ -74,7 +74,7 @@ public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi( JwtBearerAuthenticationScheme, configureConfidentialClientApplicationOptions); - return new MicrososoftAppCallingWebApiAuthenticationBuilder( + return new MicrosoftIdentityAppCallingWebApiAuthenticationBuilder( Services, ConfigurationSection); } diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs similarity index 95% rename from src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs rename to src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs index 4248127d6..29706dea0 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs @@ -17,7 +17,7 @@ namespace Microsoft.Identity.Web /// /// Extensions for for startup initialization of web APIs. /// - public static partial class WebApiAuthenticationBuilderExtensions + public static partial class MicrosoftIdentityWebApiAuthenticationBuilderExtensions { /// /// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). @@ -31,7 +31,7 @@ public static partial class WebApiAuthenticationBuilderExtensions /// Set to true if you want to debug, or just understand the JWT bearer events. /// /// The authentication builder to chain. - public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoftIdentityPlatformWebApi( + public static MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration AddMicrosoftIdentityWebApi( this AuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -67,7 +67,7 @@ public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoft /// Set to true if you want to debug, or just understand the JWT bearer events. /// /// The authentication builder to chain. - public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoftWebApi( + public static MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration AddMicrosoftWebApi( this AuthenticationBuilder builder, IConfigurationSection configurationSection, string jwtBearerScheme = JwtBearerDefaults.AuthenticationScheme, @@ -90,7 +90,7 @@ public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoft jwtBearerScheme, subscribeToJwtBearerMiddlewareDiagnosticsEvents); - return new MicrosoftWebApiAuthenticationBuilderWithConfiguration( + return new MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration( builder.Services, jwtBearerScheme, options => configurationSection.Bind(options), @@ -108,7 +108,7 @@ public static MicrosoftWebApiAuthenticationBuilderWithConfiguration AddMicrosoft /// /// Set to true if you want to debug, or just understand the JWT bearer events. /// The authentication builder to chain. - public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftIdentityPlatformWebApi( + public static MicrosoftIdentityWebApiAuthenticationBuilder AddMicrosoftIdentityWebApi( this AuthenticationBuilder builder, Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions, @@ -137,7 +137,7 @@ public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftIdentityPlatformW jwtBearerScheme, subscribeToJwtBearerMiddlewareDiagnosticsEvents); - return new MicrosoftWebApiAuthenticationBuilder( + return new MicrosoftIdentityWebApiAuthenticationBuilder( builder.Services, jwtBearerScheme, configureJwtBearerOptions, diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilderWithConfiguration.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs similarity index 83% rename from src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilderWithConfiguration.cs rename to src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs index 0fad716a0..8a1d7b658 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftWebApiAuthenticationBuilderWithConfiguration.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs @@ -11,9 +11,9 @@ namespace Microsoft.Identity.Web /// /// Builder for Web API authentication with configuration. /// - public class MicrosoftWebApiAuthenticationBuilderWithConfiguration : MicrosoftWebApiAuthenticationBuilder + public class MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration : MicrosoftIdentityWebApiAuthenticationBuilder { - internal MicrosoftWebApiAuthenticationBuilderWithConfiguration( + internal MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration( IServiceCollection services, string jwtBearerAuthenticationScheme, Action configureJwtBearerOptions, @@ -32,7 +32,7 @@ internal MicrosoftWebApiAuthenticationBuilderWithConfiguration( /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. /// /// The authentication builder to chain. - public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi() + public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi() { return CallsWebApi(options => ConfigurationSection.Bind(options)); } diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiServiceCollectionExtensions.cs similarity index 86% rename from src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs rename to src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiServiceCollectionExtensions.cs index 4e16a9f26..fc6107500 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/WebApiServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiServiceCollectionExtensions.cs @@ -11,10 +11,10 @@ namespace Microsoft.Identity.Web /// /// Extension for IServiceCollection for startup initialization of Web APIs. /// - public static partial class WebApiServiceCollectionExtensions + public static partial class MicrosoftIdentityWebApiServiceCollectionExtensions { /// - /// Protects the Web API with Microsoft identity platform (formerly Azure AD v2.0) + /// Protects the web API with Microsoft identity platform (formerly Azure AD v2.0) /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. /// /// Service collection to which to add authentication. @@ -24,7 +24,7 @@ public static partial class WebApiServiceCollectionExtensions /// /// Set to true if you want to debug, or just understand the JwtBearer events. /// The authentication builder to chain extension methods. - public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftIdentityPlatformWebApiAuthentication( + public static MicrosoftIdentityWebApiAuthenticationBuilder AddMicrosoftIdentityWebApiAuthentication( this IServiceCollection services, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -32,7 +32,7 @@ public static MicrosoftWebApiAuthenticationBuilder AddMicrosoftIdentityPlatformW bool subscribeToJwtBearerMiddlewareDiagnosticsEvents = false) { AuthenticationBuilder builder = services.AddAuthentication(jwtBearerScheme); - return builder.AddMicrosoftIdentityPlatformWebApi( + return builder.AddMicrosoftIdentityWebApi( configuration, configSectionName, jwtBearerScheme, diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs similarity index 84% rename from src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs rename to src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs index d56a479ae..65a4a994c 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrososoftAppCallingWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs @@ -17,11 +17,11 @@ namespace Microsoft.Identity.Web { /// /// Authentication builder returned by the CallsWebApi methods - /// enabling to decide token cache implementations. + /// enabling you to decide token cache implementations. /// - public class MicrososoftAppCallingWebApiAuthenticationBuilder : MicrosoftBaseAuthenticationBuilder + public class MicrosoftIdentityAppCallingWebApiAuthenticationBuilder : MicrosoftIdentityBaseAuthenticationBuilder { - internal MicrososoftAppCallingWebApiAuthenticationBuilder( + internal MicrosoftIdentityAppCallingWebApiAuthenticationBuilder( IServiceCollection services, IConfigurationSection? configurationSection = null) : base(services, configurationSection) @@ -32,7 +32,7 @@ internal MicrososoftAppCallingWebApiAuthenticationBuilder( /// Add in memory token caches. /// /// the service collection. - public MicrososoftAppCallingWebApiAuthenticationBuilder AddInMemoryTokenCaches() + public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder AddInMemoryTokenCaches() { Services.AddMemoryCache(); Services.AddHttpContextAccessor(); @@ -44,7 +44,7 @@ public MicrososoftAppCallingWebApiAuthenticationBuilder AddInMemoryTokenCaches() /// Add distributed token caches. /// /// the service collection. - public MicrososoftAppCallingWebApiAuthenticationBuilder AddDistributedTokenCaches() + public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder AddDistributedTokenCaches() { Services.AddDistributedAppTokenCache(); Services.AddDistributedUserTokenCache(); @@ -55,7 +55,7 @@ public MicrososoftAppCallingWebApiAuthenticationBuilder AddDistributedTokenCache /// Add session token caches. /// /// the service collection. - public MicrososoftAppCallingWebApiAuthenticationBuilder AddSessionTokenCaches() + public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder AddSessionTokenCaches() { // Add session if you are planning to use session based token cache var sessionStoreService = Services.FirstOrDefault(x => x.ServiceType.Name == "ISessionStore"); diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs similarity index 92% rename from src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs rename to src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs index 73d58565f..626e338e3 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs @@ -14,19 +14,19 @@ namespace Microsoft.Identity.Web { /// - /// Authentication builder specific for Microsoft identity platform. + /// Authentication builder specific for Microsoft Identity. /// - public class MicrosoftWebAppAuthenticationBuilder : MicrosoftBaseAuthenticationBuilder + public class MicrosoftIdentityWebAppAuthenticationBuilder : MicrosoftIdentityBaseAuthenticationBuilder { /// /// Constructor. /// /// The services being configured. - /// Defaut scheme used for OpenIdConnect. + /// Default scheme used for OpenIdConnect. /// Action called to configure /// the Microsoft identity options. /// Optional configuration section. - internal MicrosoftWebAppAuthenticationBuilder( + internal MicrosoftIdentityWebAppAuthenticationBuilder( IServiceCollection services, string openIdConnectScheme, Action configureMicrosoftIdentityOptions, @@ -47,14 +47,14 @@ internal MicrosoftWebAppAuthenticationBuilder( private string OpenIdConnectScheme { get; set; } /// - /// The Web app calls a web api. This overrides enables you to specify the + /// The Web app calls a Web API. This override enables you to specify the /// ConfidentialClientApplicationOptions (from MSAL.NET) programmatically. /// /// Action to configure the /// MSAL.NET confidential client application options. /// Initial scopes. - /// the builder itself for chaining. - public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi( + /// The builder itself for chaining. + public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi( Action configureConfidentialClientApplicationOptions, IEnumerable? initialScopes = null) { @@ -69,7 +69,7 @@ public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi( ConfigureMicrosoftIdentityOptions, OpenIdConnectScheme, configureConfidentialClientApplicationOptions); - return new MicrososoftAppCallingWebApiAuthenticationBuilder( + return new MicrosoftIdentityAppCallingWebApiAuthenticationBuilder( Services, ConfigurationSection); } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs similarity index 92% rename from src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs rename to src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs index b99ea77dc..0fa8da65a 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs @@ -18,10 +18,10 @@ namespace Microsoft.Identity.Web /// /// Extensions for the for startup initialization. /// - public static partial class WebAppAuthenticationBuilderExtensions + public static partial class MicrosoftIdentityWebAppAuthenticationBuilderExtensions { /// - /// Add authentication to a Web app with Microsoft identity platform. + /// Add authentication to a web app with Microsoft Identity. /// This method expects the configuration file will have a section, named "AzureAd" as default, /// with the necessary settings to initialize authentication options. /// @@ -33,8 +33,8 @@ public static partial class WebAppAuthenticationBuilderExtensions /// /// Set to true if you want to debug, or just understand the OpenID Connect events. /// - /// The builder for chaining. - public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityPlatformWebApp( + /// The builder for chaining. + public static MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityWebApp( this AuthenticationBuilder builder, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -54,7 +54,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft IConfigurationSection configurationSection = configuration.GetSection(configSectionName); - return builder.AddMicrosoftIdentityPlatformWebApp( + return builder.AddMicrosoftIdentityWebApp( configurationSection, openIdConnectScheme, cookieScheme, @@ -62,7 +62,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft } /// - /// Add authentication with Microsoft identity platform. + /// Add authentication with Microsoft Identity. /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. /// /// The to which to add this configuration. @@ -73,7 +73,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft /// Set to true if you want to debug, or just understand the OpenID Connect events. /// /// The authentication builder for chaining. - public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityPlatformWebApp( + public static MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityWebApp( this AuthenticationBuilder builder, IConfigurationSection configurationSection, string openIdConnectScheme = OpenIdConnectDefaults.AuthenticationScheme, @@ -90,7 +90,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft throw new ArgumentException(nameof(configurationSection)); } - return builder.AddMicrosoftWebAppWithConfiguration( + return builder.AddMicrosoftIdentityWebAppWithConfiguration( options => configurationSection.Bind(options), null, openIdConnectScheme, @@ -100,7 +100,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft } /// - /// Add authentication with Microsoft identity platform. + /// Add authentication with Microsoft Identity. /// /// The to which to add this configuration. /// The action to configure . @@ -111,7 +111,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft /// Set to true if you want to debug, or just understand the OpenID Connect events. /// /// The authentication builder for chaining. - public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( + public static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebApp( this AuthenticationBuilder builder, Action configureMicrosoftIdentityOptions, Action? configureCookieAuthenticationOptions = null, @@ -133,7 +133,7 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( } /// - /// Add authentication with Microsoft identity platform. + /// Add authentication with Microsoft Identity. /// /// The to which to add this configuration. /// The action to configure . @@ -145,7 +145,7 @@ public static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebApp( /// /// Configuration section. /// The authentication builder for chaining. - private static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftWebAppWithConfiguration( + private static MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityWebAppWithConfiguration( this AuthenticationBuilder builder, Action configureMicrosoftIdentityOptions, Action? configureCookieAuthenticationOptions, @@ -154,7 +154,7 @@ private static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosof bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents, IConfigurationSection configurationSection) { - AddMicrosoftWebAppInternal( + AddMicrosoftIdentityWebAppInternal( builder, configureMicrosoftIdentityOptions, configureCookieAuthenticationOptions, @@ -162,7 +162,7 @@ private static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosof cookieScheme, subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); - return new MicrosoftWebAppAuthenticationBuilderWithConfiguration( + return new MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration( builder.Services, openIdConnectScheme, configureMicrosoftIdentityOptions, @@ -170,7 +170,7 @@ private static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosof } /// - /// Add authentication with Microsoft identity platform. + /// Add authentication with Microsoft Identity. /// /// The to which to add this configuration. /// The action to configure . @@ -181,7 +181,7 @@ private static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosof /// Set to true if you want to debug, or just understand the OpenID Connect events. /// /// The authentication builder for chaining. - private static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppWithoutConfiguration( + private static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebAppWithoutConfiguration( this AuthenticationBuilder builder, Action configureMicrosoftIdentityOptions, Action? configureCookieAuthenticationOptions, @@ -189,7 +189,7 @@ private static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppWithoutCon string cookieScheme, bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents) { - AddMicrosoftWebAppInternal( + AddMicrosoftIdentityWebAppInternal( builder, configureMicrosoftIdentityOptions, configureCookieAuthenticationOptions, @@ -197,14 +197,20 @@ private static MicrosoftWebAppAuthenticationBuilder AddMicrosoftWebAppWithoutCon cookieScheme, subscribeToOpenIdConnectMiddlewareDiagnosticsEvents); - return new MicrosoftWebAppAuthenticationBuilder( + return new MicrosoftIdentityWebAppAuthenticationBuilder( builder.Services, openIdConnectScheme, configureMicrosoftIdentityOptions, null); } - private static void AddMicrosoftWebAppInternal(AuthenticationBuilder builder, Action configureMicrosoftIdentityOptions, Action? configureCookieAuthenticationOptions, string openIdConnectScheme, string cookieScheme, bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents) + private static void AddMicrosoftIdentityWebAppInternal( + AuthenticationBuilder builder, + Action configureMicrosoftIdentityOptions, + Action? configureCookieAuthenticationOptions, + string openIdConnectScheme, + string cookieScheme, + bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents) { if (builder == null) { diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilderWithConfiguration.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs similarity index 75% rename from src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilderWithConfiguration.cs rename to src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs index fcbddb3c1..b3a4199d2 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftWebAppAuthenticationBuilderWithConfiguration.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs @@ -9,20 +9,20 @@ namespace Microsoft.Identity.Web { /// - /// Builder for a Microsoft web app authentication where configuration is + /// Builder for a Microsoft identity web app authentication where configuration is /// available for CallsWebApi. /// - public class MicrosoftWebAppAuthenticationBuilderWithConfiguration : MicrosoftWebAppAuthenticationBuilder + public class MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration : MicrosoftIdentityWebAppAuthenticationBuilder { /// /// Constructor. /// /// The services being configured. - /// Defaut scheme used for OpenIdConnect. + /// Default scheme used for OpenIdConnect. /// Action called to configure /// the Microsoft identity options. /// Optional configuration section. - internal MicrosoftWebAppAuthenticationBuilderWithConfiguration( + internal MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration( IServiceCollection services, string openIdConnectScheme, Action configureMicrosoftIdentityOptions, @@ -36,11 +36,11 @@ internal MicrosoftWebAppAuthenticationBuilderWithConfiguration( } /// - /// Add support for the Web app to acquire tokens to call an API. + /// Add support for the web app to acquire tokens to call an API. /// /// Optional initial scopes to request. /// The authentication builder for chaining. - public MicrososoftAppCallingWebApiAuthenticationBuilder CallsWebApi( + public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi( IEnumerable? initialScopes = null) { return CallsWebApi( diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppServiceCollectionExtensions.cs similarity index 88% rename from src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs rename to src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppServiceCollectionExtensions.cs index cc5555b6a..d22296550 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/WebAppServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppServiceCollectionExtensions.cs @@ -12,10 +12,10 @@ namespace Microsoft.Identity.Web /// /// Extension for IServiceCollection for startup initialization. /// - public static partial class WebAppServiceCollectionExtensions + public static partial class MicrosoftIdentityWebAppServiceCollectionExtensions { /// - /// Add authentication with Microsoft identity platform. + /// Add authentication with Microsoft Identity. /// This method expects the configuration file will have a section, (by default named "AzureAd"), with the necessary settings to /// initialize the authentication options. /// @@ -32,7 +32,7 @@ public static partial class WebAppServiceCollectionExtensions /// Set to true if you want to debug, or just understand the OpenIdConnect events. /// /// The authentication builder to chain extension methods. - public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityPlatformWebAppAuthentication( + public static MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration AddMicrosoftIdentityWebAppAuthentication( this IServiceCollection services, IConfiguration configuration, string configSectionName = Constants.AzureAd, @@ -41,7 +41,7 @@ public static MicrosoftWebAppAuthenticationBuilderWithConfiguration AddMicrosoft bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false) { AuthenticationBuilder builder = services.AddAuthentication(openIdConnectScheme); - return builder.AddMicrosoftIdentityPlatformWebApp( + return builder.AddMicrosoftIdentityWebApp( configuration, configSectionName, openIdConnectScheme, diff --git a/tests/B2CWebAppCallsWebApi/Client/Startup.cs b/tests/B2CWebAppCallsWebApi/Client/Startup.cs index c1a6a9336..849d6f6e1 100644 --- a/tests/B2CWebAppCallsWebApi/Client/Startup.cs +++ b/tests/B2CWebAppCallsWebApi/Client/Startup.cs @@ -43,7 +43,7 @@ public void ConfigureServices(IServiceCollection services) services.AddOptions(); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration, "AzureAdB2C") + .AddMicrosoftIdentityWebApp(Configuration, "AzureAdB2C") .CallsWebApi(initialScopes: new string[] { Configuration["TodoList:TodoListScope"] }) .AddInMemoryTokenCaches(); diff --git a/tests/B2CWebAppCallsWebApi/TodoListService/Startup.cs b/tests/B2CWebAppCallsWebApi/TodoListService/Startup.cs index dd859c0d6..4df8d5b83 100644 --- a/tests/B2CWebAppCallsWebApi/TodoListService/Startup.cs +++ b/tests/B2CWebAppCallsWebApi/TodoListService/Startup.cs @@ -34,7 +34,7 @@ public void ConfigureServices(IServiceCollection services) // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApi(options => + .AddMicrosoftIdentityWebApi(options => { Configuration.Bind(sectionName, options); options.TokenValidationParameters.NameClaimType = "name"; diff --git a/tests/BlazorServerCallsGraph/Startup.cs b/tests/BlazorServerCallsGraph/Startup.cs index 6e5d1dffd..e2abf4462 100644 --- a/tests/BlazorServerCallsGraph/Startup.cs +++ b/tests/BlazorServerCallsGraph/Startup.cs @@ -29,7 +29,7 @@ public void ConfigureServices(IServiceCollection services) { string[] scopes = Configuration.GetValue("CalledApi:CalledApiScopes")?.Split(' '); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration, "AzureAd") + .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") .CallsWebApi(scopes) .AddInMemoryTokenCaches(); diff --git a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs index 640f11d8d..d537cfc87 100644 --- a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs @@ -61,7 +61,7 @@ public void AddMicrosoftWebApi_WithConfigName() .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftIdentityPlatformWebApi(config, ConfigSectionName, JwtBearerScheme, true); + .AddMicrosoftIdentityWebApi(config, ConfigSectionName, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); @@ -80,7 +80,7 @@ public void AddMicrosoftWebApi_WithConfigActions() .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftIdentityPlatformWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, true); + .AddMicrosoftIdentityWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); @@ -106,7 +106,7 @@ public void AddMicrosoftWebApiAuthentication_WithConfigName() var services = new ServiceCollection() .AddLogging(); - services.AddMicrosoftIdentityPlatformWebApiAuthentication(config, ConfigSectionName, JwtBearerScheme, true); + services.AddMicrosoftIdentityWebApiAuthentication(config, ConfigSectionName, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); @@ -158,7 +158,7 @@ public void AddMicrosoftWebApi_WithConfigName_JwtBearerTokenValidatedEventCalled .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftIdentityPlatformWebApi(config, ConfigSectionName, JwtBearerScheme, true); + .AddMicrosoftIdentityWebApi(config, ConfigSectionName, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); @@ -181,7 +181,7 @@ public void AddMicrosoftWebApi_WithConfigActions_JwtBearerTokenValidatedEventCal .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftIdentityPlatformWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, true); + .AddMicrosoftIdentityWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, true); var provider = services.BuildServiceProvider(); @@ -233,7 +233,7 @@ public void AddMicrosoftWebApi_WithConfigName_SubscribesToDiagnostics(bool subsc .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftIdentityPlatformWebApi(config, ConfigSectionName, JwtBearerScheme, subscribeToDiagnostics); + .AddMicrosoftIdentityWebApi(config, ConfigSectionName, JwtBearerScheme, subscribeToDiagnostics); services.RemoveAll(); services.AddSingleton((provider) => diagnostics); @@ -263,7 +263,7 @@ public void AddMicrosoftWebApi_WithConfigActions_SubscribesToDiagnostics(bool su .AddLogging(); new AuthenticationBuilder(services) - .AddMicrosoftIdentityPlatformWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, subscribeToDiagnostics); + .AddMicrosoftIdentityWebApi(_configureJwtOptions, _configureMsOptions, JwtBearerScheme, subscribeToDiagnostics); services.RemoveAll(); services.AddSingleton((provider) => diagnostics); diff --git a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs index 5740a85cc..1aa938111 100644 --- a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs @@ -66,7 +66,7 @@ public void AddMicrosoftWebApp_WithConfigNameParameters(bool subscribeToDiagnost services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftIdentityPlatformWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, subscribeToDiagnostics); + .AddMicrosoftIdentityWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, subscribeToDiagnostics); var provider = services.BuildServiceProvider(); @@ -93,7 +93,7 @@ public void AddMicrosoftWebAppAuthentication_WithConfigNameParameters(bool subsc services.AddDataProtection(); - services.AddMicrosoftIdentityPlatformWebAppAuthentication( + services.AddMicrosoftIdentityWebAppAuthentication( configMock, ConfigSectionName, OidcScheme, @@ -157,7 +157,7 @@ public async Task AddMicrosoftWebApp_WithConfigNameParameters_TestRedirectToIden services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftIdentityPlatformWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); + .AddMicrosoftIdentityWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); await AddMicrosoftWebApp_TestRedirectToIdentityProviderEvent(services, redirectFunc).ConfigureAwait(false); } @@ -197,7 +197,7 @@ public async Task AddMicrosoftWebApp_WithConfigNameParameters_TestB2cSpecificSet services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftIdentityPlatformWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); + .AddMicrosoftIdentityWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); await AddMicrosoftWebApp_TestB2cSpecificSetup(services, remoteFailureFuncMock).ConfigureAwait(false); } @@ -242,7 +242,7 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigNameParameters() var services = new ServiceCollection(); var builder = services.AddAuthentication() - .AddMicrosoftIdentityPlatformWebApp(configMock, ConfigSectionName, OidcScheme) + .AddMicrosoftIdentityWebApp(configMock, ConfigSectionName, OidcScheme) .CallsWebApi(initialScopes); services.Configure(OidcScheme, (options) => { @@ -320,7 +320,7 @@ public void AddMicrosoftWebAppCallsWebApi_NoScopes() var services = new ServiceCollection(); services.AddAuthentication() - .AddMicrosoftIdentityPlatformWebApp(Substitute.For()) + .AddMicrosoftIdentityWebApp(Substitute.For()) .CallsWebApi(); var provider = services.BuildServiceProvider(); diff --git a/tests/WebAppCallsMicrosoftGraph/Startup.cs b/tests/WebAppCallsMicrosoftGraph/Startup.cs index 7f813cdcd..a5a10d8b3 100644 --- a/tests/WebAppCallsMicrosoftGraph/Startup.cs +++ b/tests/WebAppCallsMicrosoftGraph/Startup.cs @@ -28,7 +28,7 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) .CallsWebApi() .AddInMemoryTokenCaches(); // Add a delegate overload. Should return the parent builder diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs index 8e19e0187..0dd2f433b 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs @@ -44,7 +44,7 @@ public void ConfigureServices(IServiceCollection services) services.AddOptions(); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration, "AzureAd") + .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") .CallsWebApi() .AddInMemoryTokenCaches(); diff --git a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs index 665188228..97418cf3d 100644 --- a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs @@ -33,7 +33,7 @@ public void ConfigureServices(IServiceCollection services) // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApi(Configuration, "AzureAd") + .AddMicrosoftIdentityWebApi(Configuration, "AzureAd") .CallsWebApi() .AddInMemoryTokenCaches(); diff --git a/tests/blazorwasm2/Server/Startup.cs b/tests/blazorwasm2/Server/Startup.cs index dc1783229..b82acbc60 100644 --- a/tests/blazorwasm2/Server/Startup.cs +++ b/tests/blazorwasm2/Server/Startup.cs @@ -24,7 +24,7 @@ public Startup(IConfiguration configuration) public void ConfigureServices(IServiceCollection services) { // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api - services.AddMicrosoftIdentityPlatformWebApiAuthentication(Configuration, "AzureAd"); + services.AddMicrosoftIdentityWebApiAuthentication(Configuration, "AzureAd"); services.AddControllersWithViews(); services.AddRazorPages(); From 6bc76ba208e827f8999ca969fbd925e8eb58cd38 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Sat, 8 Aug 2020 20:49:19 -0700 Subject: [PATCH 12/28] merge conflicts + update templates --- .../templates/BlazorServerWeb-CSharp/Startup.cs | 4 ++-- .../ComponentsWebAssembly-CSharp/Server/Startup.cs | 4 ++-- .../templates/RazorPagesWeb-CSharp/Startup.cs | 4 ++-- ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs | 4 ++-- ProjectTemplates/templates/WebApi-CSharp/Startup.cs | 4 ++-- tests/WebAppCallsMicrosoftGraph/Startup.cs | 8 ++++---- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs b/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs index eb97e13cc..94266030f 100644 --- a/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs +++ b/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs @@ -76,7 +76,7 @@ public void ConfigureServices(IServiceCollection services) string[] scopes = Configuration.GetValue("CalledApi:CalledApiScopes")?.Split(' '); #endif services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) .CallsWebApi() .AddInMemoryTokenCaches(); @@ -95,7 +95,7 @@ public void ConfigureServices(IServiceCollection services) string[] scopes = Configuration.GetValue("CalledApi:CalledApiScopes")?.Split(' '); #endif services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAdB2C")) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) .CallsWebApi() .AddInMemoryTokenCaches(); diff --git a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs index ae4030760..f9a9d5583 100644 --- a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs +++ b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs @@ -62,7 +62,7 @@ public void ConfigureServices(IServiceCollection services) #endif #if (OrganizationalAuth) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAd")) + .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) .CallsWebApi() .AddInMemoryTokenCaches(); @@ -78,7 +78,7 @@ public void ConfigureServices(IServiceCollection services) #endif #elif (IndividualB2CAuth) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAdB2C")) + .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) .CallsWebApi() .AddInMemoryTokenCaches(); diff --git a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs index c47850c2d..3cd81f2b9 100644 --- a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs +++ b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs @@ -62,7 +62,7 @@ public void ConfigureServices(IServiceCollection services) .AddEntityFrameworkStores(); #elif (OrganizationalAuth) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) .CallsWebApi() .AddInMemoryTokenCaches(); @@ -78,7 +78,7 @@ public void ConfigureServices(IServiceCollection services) #endif #elif (IndividualB2CAuth) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAdB2C")) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) .CallsWebApi() .AddInMemoryTokenCaches(); diff --git a/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs b/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs index 895604d6b..872491972 100644 --- a/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs +++ b/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs @@ -62,7 +62,7 @@ public void ConfigureServices(IServiceCollection services) .AddEntityFrameworkStores(); #elif (OrganizationalAuth) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) .CallsWebApi() .AddInMemoryTokenCaches(); @@ -78,7 +78,7 @@ public void ConfigureServices(IServiceCollection services) #endif #elif (IndividualB2CAuth) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAdB2C")) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) .CallsWebApi() .AddInMemoryTokenCaches(); diff --git a/ProjectTemplates/templates/WebApi-CSharp/Startup.cs b/ProjectTemplates/templates/WebApi-CSharp/Startup.cs index ab3c75c7f..f348a2b72 100644 --- a/ProjectTemplates/templates/WebApi-CSharp/Startup.cs +++ b/ProjectTemplates/templates/WebApi-CSharp/Startup.cs @@ -36,7 +36,7 @@ public void ConfigureServices(IServiceCollection services) { #if (OrganizationalAuth) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAd")) + .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) .CallsWebApi() .AddInMemoryTokenCaches(); @@ -53,7 +53,7 @@ public void ConfigureServices(IServiceCollection services) #endif #elif (IndividualB2CAuth) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAdB2C")) + .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) .CallsWebApi() .AddInMemoryTokenCaches(); diff --git a/tests/WebAppCallsMicrosoftGraph/Startup.cs b/tests/WebAppCallsMicrosoftGraph/Startup.cs index a5a10d8b3..5fb62861e 100644 --- a/tests/WebAppCallsMicrosoftGraph/Startup.cs +++ b/tests/WebAppCallsMicrosoftGraph/Startup.cs @@ -34,23 +34,23 @@ public void ConfigureServices(IServiceCollection services) /* * services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftIdentityPlatformWebApp(Configuration.GetSection("AzureAd")) + .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) .CallsWebApi() .AddInMemoryTokenCaches() // Change the builder .AddAuthentication() - .AddMicrosoftIdentityPlatformWebApi(Configuration.GetSection("AzureAd")) + .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd")) */ /* OR - services.AddMicrosoftWebAppAuthentication(Configuration) + services.AddMicrosoftIdentityWebAppAuthentication(Configuration) .CallsWebApi() .AddInMemoryTokenCaches(); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) - .AddMicrosoftWebApp(options => + .AddMicrosoftIdentityWebApp(options => { Configuration.Bind("AzureAd", options); // do something From 83a292186b9e231067f7bc4128c74e77c255e52a Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Sun, 9 Aug 2020 11:03:49 +0200 Subject: [PATCH 13/28] Making the templates work with 0.3.*-* --- .../BlazorServerWeb-CSharp/BlazorServerWeb-CSharp.csproj | 4 ++-- .../Server/ComponentsWebAssembly-CSharp.Server.csproj | 2 +- .../RazorPagesWeb-CSharp/Company.WebApplication1.csproj | 4 ++-- .../StarterWeb-CSharp/Company.WebApplication1.csproj | 4 ++-- .../templates/WebApi-CSharp/Company.WebApplication1.csproj | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/ProjectTemplates/templates/BlazorServerWeb-CSharp/BlazorServerWeb-CSharp.csproj b/ProjectTemplates/templates/BlazorServerWeb-CSharp/BlazorServerWeb-CSharp.csproj index 73b6b51c8..6d09e2699 100644 --- a/ProjectTemplates/templates/BlazorServerWeb-CSharp/BlazorServerWeb-CSharp.csproj +++ b/ProjectTemplates/templates/BlazorServerWeb-CSharp/BlazorServerWeb-CSharp.csproj @@ -3,8 +3,8 @@ netcoreapp3.1; net5.0 - - + + diff --git a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/ComponentsWebAssembly-CSharp.Server.csproj b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/ComponentsWebAssembly-CSharp.Server.csproj index 869287892..f9e9a9aa6 100644 --- a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/ComponentsWebAssembly-CSharp.Server.csproj +++ b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/ComponentsWebAssembly-CSharp.Server.csproj @@ -4,7 +4,7 @@ - + diff --git a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Company.WebApplication1.csproj b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Company.WebApplication1.csproj index 8d4b8cdcb..1083772c5 100644 --- a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Company.WebApplication1.csproj +++ b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Company.WebApplication1.csproj @@ -3,8 +3,8 @@ netcoreapp3.1; net5.0 - - + + diff --git a/ProjectTemplates/templates/StarterWeb-CSharp/Company.WebApplication1.csproj b/ProjectTemplates/templates/StarterWeb-CSharp/Company.WebApplication1.csproj index 978b6fa04..b74b20735 100644 --- a/ProjectTemplates/templates/StarterWeb-CSharp/Company.WebApplication1.csproj +++ b/ProjectTemplates/templates/StarterWeb-CSharp/Company.WebApplication1.csproj @@ -3,8 +3,8 @@ netcoreapp3.1; net5.0 - - + + diff --git a/ProjectTemplates/templates/WebApi-CSharp/Company.WebApplication1.csproj b/ProjectTemplates/templates/WebApi-CSharp/Company.WebApplication1.csproj index f148aa19d..c5fc7f195 100644 --- a/ProjectTemplates/templates/WebApi-CSharp/Company.WebApplication1.csproj +++ b/ProjectTemplates/templates/WebApi-CSharp/Company.WebApplication1.csproj @@ -3,7 +3,7 @@ netcoreapp3.1; net5.0 - + From 242e5c427874751b35426996530c53cfe6e1826e Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Sun, 9 Aug 2020 18:33:07 -0700 Subject: [PATCH 14/28] few more updates --- .../Microsoft.Identity.Web.xml | 22 +++---- ...softIdentityWebApiAuthenticationBuilder.cs | 4 +- ...iAuthenticationBuilderWithConfiguration.cs | 2 +- ...tyAppCallingWebApiAuthenticationBuilder.cs | 10 +-- ...softIdentityWebAppAuthenticationBuilder.cs | 6 +- ...tyWebAppAuthenticationBuilderExtensions.cs | 10 +-- ...pAuthenticationBuilderWithConfiguration.cs | 2 +- ...entityWebAppServiceCollectionExtensions.cs | 2 +- .../WebApiExtensionsTests.cs | 39 ++++++----- .../WebAppExtensionsTests.cs | 64 +++++++++---------- 10 files changed, 80 insertions(+), 81 deletions(-) diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index e16200206..33c0d0fda 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1816,25 +1816,25 @@ Set to true if you want to debug, or just understand the JwtBearer events. The authentication builder to chain extension methods. - + Authentication builder returned by the CallsWebApi methods enabling you to decide token cache implementations. - + Add in memory token caches. the service collection. - + Add distributed token caches. the service collection. - + Add session token caches. @@ -1842,7 +1842,7 @@ - Authentication builder specific for Microsoft Identity. + Authentication builder specific for Microsoft identity platform. @@ -1872,7 +1872,7 @@ - Add authentication to a web app with Microsoft Identity. + Add authentication to a web app with Microsoft identity platform. This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. @@ -1888,7 +1888,7 @@ - Add authentication with Microsoft Identity. + Add authentication with Microsoft identity platform. This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. The to which to add this configuration. @@ -1902,7 +1902,7 @@ - Add authentication with Microsoft Identity. + Add authentication with Microsoft identity platform. The to which to add this configuration. The action to configure . @@ -1916,7 +1916,7 @@ - Add authentication with Microsoft Identity. + Add authentication with Microsoft identity platform. The to which to add this configuration. The action to configure . @@ -1931,7 +1931,7 @@ - Add authentication with Microsoft Identity. + Add authentication with Microsoft identity platform. The to which to add this configuration. The action to configure . @@ -1973,7 +1973,7 @@ - Add authentication with Microsoft Identity. + Add authentication with Microsoft identity platform. This method expects the configuration file will have a section, (by default named "AzureAd"), with the necessary settings to initialize the authentication options. diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs index f90603420..005ddafc4 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs @@ -61,7 +61,7 @@ internal MicrosoftIdentityWebApiAuthenticationBuilder( /// /// The action to configure . /// The authentication builder to chain. - public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi( + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder CallsWebApi( Action configureConfidentialClientApplicationOptions) { if (configureConfidentialClientApplicationOptions == null) @@ -74,7 +74,7 @@ public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi( JwtBearerAuthenticationScheme, configureConfidentialClientApplicationOptions); - return new MicrosoftIdentityAppCallingWebApiAuthenticationBuilder( + return new MicrosoftIdentityAppCallsWebApiAuthenticationBuilder( Services, ConfigurationSection); } diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs index 8a1d7b658..b7aa63a01 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs @@ -32,7 +32,7 @@ internal MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration( /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. /// /// The authentication builder to chain. - public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi() + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder CallsWebApi() { return CallsWebApi(options => ConfigurationSection.Bind(options)); } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs index 65a4a994c..b94a09535 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs @@ -19,9 +19,9 @@ namespace Microsoft.Identity.Web /// Authentication builder returned by the CallsWebApi methods /// enabling you to decide token cache implementations. /// - public class MicrosoftIdentityAppCallingWebApiAuthenticationBuilder : MicrosoftIdentityBaseAuthenticationBuilder + public class MicrosoftIdentityAppCallsWebApiAuthenticationBuilder : MicrosoftIdentityBaseAuthenticationBuilder { - internal MicrosoftIdentityAppCallingWebApiAuthenticationBuilder( + internal MicrosoftIdentityAppCallsWebApiAuthenticationBuilder( IServiceCollection services, IConfigurationSection? configurationSection = null) : base(services, configurationSection) @@ -32,7 +32,7 @@ internal MicrosoftIdentityAppCallingWebApiAuthenticationBuilder( /// Add in memory token caches. /// /// the service collection. - public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder AddInMemoryTokenCaches() + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddInMemoryTokenCaches() { Services.AddMemoryCache(); Services.AddHttpContextAccessor(); @@ -44,7 +44,7 @@ public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder AddInMemoryTokenCa /// Add distributed token caches. /// /// the service collection. - public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder AddDistributedTokenCaches() + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddDistributedTokenCaches() { Services.AddDistributedAppTokenCache(); Services.AddDistributedUserTokenCache(); @@ -55,7 +55,7 @@ public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder AddDistributedToke /// Add session token caches. /// /// the service collection. - public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder AddSessionTokenCaches() + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddSessionTokenCaches() { // Add session if you are planning to use session based token cache var sessionStoreService = Services.FirstOrDefault(x => x.ServiceType.Name == "ISessionStore"); diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs index 626e338e3..43749ea63 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs @@ -14,7 +14,7 @@ namespace Microsoft.Identity.Web { /// - /// Authentication builder specific for Microsoft Identity. + /// Authentication builder specific for Microsoft identity platform. /// public class MicrosoftIdentityWebAppAuthenticationBuilder : MicrosoftIdentityBaseAuthenticationBuilder { @@ -54,7 +54,7 @@ internal MicrosoftIdentityWebAppAuthenticationBuilder( /// MSAL.NET confidential client application options. /// Initial scopes. /// The builder itself for chaining. - public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi( + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder CallsWebApi( Action configureConfidentialClientApplicationOptions, IEnumerable? initialScopes = null) { @@ -69,7 +69,7 @@ public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi( ConfigureMicrosoftIdentityOptions, OpenIdConnectScheme, configureConfidentialClientApplicationOptions); - return new MicrosoftIdentityAppCallingWebApiAuthenticationBuilder( + return new MicrosoftIdentityAppCallsWebApiAuthenticationBuilder( Services, ConfigurationSection); } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs index 0fa8da65a..0300edcf9 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs @@ -21,7 +21,7 @@ namespace Microsoft.Identity.Web public static partial class MicrosoftIdentityWebAppAuthenticationBuilderExtensions { /// - /// Add authentication to a web app with Microsoft Identity. + /// Add authentication to a web app with Microsoft identity platform. /// This method expects the configuration file will have a section, named "AzureAd" as default, /// with the necessary settings to initialize authentication options. /// @@ -62,7 +62,7 @@ public static MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration AddM } /// - /// Add authentication with Microsoft Identity. + /// Add authentication with Microsoft identity platform. /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. /// /// The to which to add this configuration. @@ -100,7 +100,7 @@ public static MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration AddM } /// - /// Add authentication with Microsoft Identity. + /// Add authentication with Microsoft identity platform. /// /// The to which to add this configuration. /// The action to configure . @@ -133,7 +133,7 @@ public static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebApp( } /// - /// Add authentication with Microsoft Identity. + /// Add authentication with Microsoft identity platform. /// /// The to which to add this configuration. /// The action to configure . @@ -170,7 +170,7 @@ private static MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration Add } /// - /// Add authentication with Microsoft Identity. + /// Add authentication with Microsoft identity platform. /// /// The to which to add this configuration. /// The action to configure . diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs index b3a4199d2..5e6ba5f18 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs @@ -40,7 +40,7 @@ internal MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration( /// /// Optional initial scopes to request. /// The authentication builder for chaining. - public MicrosoftIdentityAppCallingWebApiAuthenticationBuilder CallsWebApi( + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder CallsWebApi( IEnumerable? initialScopes = null) { return CallsWebApi( diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppServiceCollectionExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppServiceCollectionExtensions.cs index d22296550..5a2e25413 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppServiceCollectionExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppServiceCollectionExtensions.cs @@ -15,7 +15,7 @@ namespace Microsoft.Identity.Web public static partial class MicrosoftIdentityWebAppServiceCollectionExtensions { /// - /// Add authentication with Microsoft Identity. + /// Add authentication with Microsoft identity platform. /// This method expects the configuration file will have a section, (by default named "AzureAd"), with the necessary settings to /// initialize the authentication options. /// diff --git a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs index d537cfc87..0d59b0e95 100644 --- a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs @@ -6,7 +6,6 @@ using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Claims; -using System.Security.Cryptography.X509Certificates; using System.Text.Json; using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; @@ -52,7 +51,7 @@ public WebApiExtensionsTests() } [Fact] - public void AddMicrosoftWebApi_WithConfigName() + public void AddMicrosoftIdentityWebApi_WithConfigName() { var config = Substitute.For(); config.Configure().GetSection(ConfigSectionName).Returns(_configSection); @@ -70,11 +69,11 @@ public void AddMicrosoftWebApi_WithConfigName() provider.GetRequiredService>().Create(string.Empty); config.Received(1).GetSection(ConfigSectionName); - AddMicrosoftWebApi_TestCommon(services, provider, false); + AddMicrosoftIdentityWebApi_TestCommon(services, provider, false); } [Fact] - public void AddMicrosoftWebApi_WithConfigActions() + public void AddMicrosoftIdentityWebApi_WithConfigActions() { var services = new ServiceCollection() .AddLogging(); @@ -94,11 +93,11 @@ public void AddMicrosoftWebApi_WithConfigActions() #endif Assert.Contains(configuredMsOptions, o => o.Action == _configureMsOptions); - AddMicrosoftWebApi_TestCommon(services, provider); + AddMicrosoftIdentityWebApi_TestCommon(services, provider); } [Fact] - public void AddMicrosoftWebApiAuthentication_WithConfigName() + public void AddMicrosoftIdentityWebApiAuthentication_WithConfigName() { var config = Substitute.For(); config.Configure().GetSection(ConfigSectionName).Returns(_configSection); @@ -115,10 +114,10 @@ public void AddMicrosoftWebApiAuthentication_WithConfigName() provider.GetRequiredService>().Create(string.Empty); config.Received(1).GetSection(ConfigSectionName); - AddMicrosoftWebApi_TestCommon(services, provider, false); + AddMicrosoftIdentityWebApi_TestCommon(services, provider, false); } - private void AddMicrosoftWebApi_TestCommon(IServiceCollection services, ServiceProvider provider, bool checkDecryptCertificate = true) + private void AddMicrosoftIdentityWebApi_TestCommon(IServiceCollection services, ServiceProvider provider, bool checkDecryptCertificate = true) { // Correct services added Assert.Contains(services, s => s.ServiceType == typeof(IHttpContextAccessor)); @@ -142,7 +141,7 @@ private void AddMicrosoftWebApi_TestCommon(IServiceCollection services, ServiceP } [Fact] - public void AddMicrosoftWebApi_WithConfigName_JwtBearerTokenValidatedEventCalled() + public void AddMicrosoftIdentityWebApi_WithConfigName_JwtBearerTokenValidatedEventCalled() { var config = Substitute.For(); config.Configure().GetSection(ConfigSectionName).Returns(_configSection); @@ -164,11 +163,11 @@ public void AddMicrosoftWebApi_WithConfigName_JwtBearerTokenValidatedEventCalled var jwtOptions = provider.GetRequiredService>().Create(JwtBearerScheme); - AddMicrosoftWebApi_TestJwtBearerTokenValidatedEvent(jwtOptions, tokenValidatedFunc); + AddMicrosoftIdentityWebApi_TestJwtBearerTokenValidatedEvent(jwtOptions, tokenValidatedFunc); } [Fact] - public void AddMicrosoftWebApi_WithConfigActions_JwtBearerTokenValidatedEventCalled() + public void AddMicrosoftIdentityWebApi_WithConfigActions_JwtBearerTokenValidatedEventCalled() { var tokenValidatedFunc = Substitute.For>(); @@ -187,10 +186,10 @@ public void AddMicrosoftWebApi_WithConfigActions_JwtBearerTokenValidatedEventCal var jwtOptions = provider.GetRequiredService>().Create(JwtBearerScheme); - AddMicrosoftWebApi_TestJwtBearerTokenValidatedEvent(jwtOptions, tokenValidatedFunc); + AddMicrosoftIdentityWebApi_TestJwtBearerTokenValidatedEvent(jwtOptions, tokenValidatedFunc); } - private async void AddMicrosoftWebApi_TestJwtBearerTokenValidatedEvent(JwtBearerOptions jwtOptions, Func tokenValidatedFunc) + private async void AddMicrosoftIdentityWebApi_TestJwtBearerTokenValidatedEvent(JwtBearerOptions jwtOptions, Func tokenValidatedFunc) { var scopeTypes = new[] { ClaimConstants.Scope, ClaimConstants.Scp, ClaimConstants.Roles, ClaimConstants.Role }; var expectedExceptionMessage = IDWebErrorMessage.NeitherScopeOrRolesClaimFoundInToken; @@ -222,7 +221,7 @@ private async void AddMicrosoftWebApi_TestJwtBearerTokenValidatedEvent(JwtBearer [Theory] [InlineData(true)] [InlineData(false)] - public void AddMicrosoftWebApi_WithConfigName_SubscribesToDiagnostics(bool subscribeToDiagnostics) + public void AddMicrosoftIdentityWebApi_WithConfigName_SubscribesToDiagnostics(bool subscribeToDiagnostics) { var config = Substitute.For(); config.Configure().GetSection(ConfigSectionName).Returns(_configSection); @@ -255,7 +254,7 @@ public void AddMicrosoftWebApi_WithConfigName_SubscribesToDiagnostics(bool subsc [Theory] [InlineData(true)] [InlineData(false)] - public void AddMicrosoftWebApi_WithConfigActions_SubscribesToDiagnostics(bool subscribeToDiagnostics) + public void AddMicrosoftIdentityWebApi_WithConfigActions_SubscribesToDiagnostics(bool subscribeToDiagnostics) { var diagnostics = Substitute.For(); @@ -307,7 +306,7 @@ private IConfigurationSection GetConfigSection(string configSectionName) } [Fact] - public async Task AddMicrosoftWebApiCallsWebApi_WithConfigName() + public async Task AddMicrosoftIdentityWebApiCallsWebApi_WithConfigName() { var config = Substitute.For(); var tokenValidatedFuncMock = Substitute.For>(); @@ -328,11 +327,11 @@ public async Task AddMicrosoftWebApiCallsWebApi_WithConfigName() config.Received(2).GetSection(ConfigSectionName); - await AddMicrosoftWebApiCallsWebApi_TestCommon(services, provider, tokenValidatedFuncMock).ConfigureAwait(false); + await AddMicrosoftIdentityWebApiCallsWebApi_TestCommon(services, provider, tokenValidatedFuncMock).ConfigureAwait(false); } [Fact] - public async Task AddMicrosoftWebApiCallsWebApi_WithConfigActions() + public async Task AddMicrosoftIdentityWebApiCallsWebApi_WithConfigActions() { var tokenValidatedFuncMock = Substitute.For>(); var services = new ServiceCollection() @@ -352,10 +351,10 @@ public async Task AddMicrosoftWebApiCallsWebApi_WithConfigActions() Assert.Contains(configuredAppOptions, o => o.Action == _configureAppOptions); Assert.Contains(configuredMsOptions, o => o.Action == _configureMsOptions); - await AddMicrosoftWebApiCallsWebApi_TestCommon(services, provider, tokenValidatedFuncMock).ConfigureAwait(false); + await AddMicrosoftIdentityWebApiCallsWebApi_TestCommon(services, provider, tokenValidatedFuncMock).ConfigureAwait(false); } - private async Task AddMicrosoftWebApiCallsWebApi_TestCommon(IServiceCollection services, ServiceProvider provider, Func tokenValidatedFuncMock) + private async Task AddMicrosoftIdentityWebApiCallsWebApi_TestCommon(IServiceCollection services, ServiceProvider provider, Func tokenValidatedFuncMock) { // Assert correct services added Assert.Contains(services, s => s.ServiceType == typeof(IHttpContextAccessor)); diff --git a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs index 1aa938111..335e076a0 100644 --- a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs @@ -54,7 +54,7 @@ public WebAppExtensionsTests() [Theory] [InlineData(true)] [InlineData(false)] - public void AddMicrosoftWebApp_WithConfigNameParameters(bool subscribeToDiagnostics) + public void AddMicrosoftIdentityWebApp_WithConfigNameParameters(bool subscribeToDiagnostics) { var configMock = Substitute.For(); configMock.Configure().GetSection(ConfigSectionName).Returns(_configSection); @@ -75,14 +75,14 @@ public void AddMicrosoftWebApp_WithConfigNameParameters(bool subscribeToDiagnost provider.GetRequiredService>().Create(string.Empty); configMock.Received(1).GetSection(ConfigSectionName); - AddMicrosoftWebApp_TestCommon(services, provider); - AddMicrosoftWebApp_TestSubscribesToDiagnostics(services, diagnosticsMock, subscribeToDiagnostics); + AddMicrosoftIdentityWebApp_TestCommon(services, provider); + AddMicrosoftIdentityWebApp_TestSubscribesToDiagnostics(services, diagnosticsMock, subscribeToDiagnostics); } [Theory] [InlineData(true)] [InlineData(false)] - public void AddMicrosoftWebAppAuthentication_WithConfigNameParameters(bool subscribeToDiagnostics) + public void AddMicrosoftIdentityWebAppAuthentication_WithConfigNameParameters(bool subscribeToDiagnostics) { var configMock = Substitute.For(); configMock.Configure().GetSection(ConfigSectionName).Returns(_configSection); @@ -107,14 +107,14 @@ public void AddMicrosoftWebAppAuthentication_WithConfigNameParameters(bool subsc provider.GetRequiredService>().Create(string.Empty); configMock.Received(1).GetSection(ConfigSectionName); - AddMicrosoftWebApp_TestCommon(services, provider); - AddMicrosoftWebApp_TestSubscribesToDiagnostics(services, diagnosticsMock, subscribeToDiagnostics); + AddMicrosoftIdentityWebApp_TestCommon(services, provider); + AddMicrosoftIdentityWebApp_TestSubscribesToDiagnostics(services, diagnosticsMock, subscribeToDiagnostics); } [Theory] [InlineData(true)] [InlineData(false)] - public void AddMicrosoftWebApp_WithConfigActionParameters(bool subscribeToDiagnostics) + public void AddMicrosoftIdentityWebApp_WithConfigActionParameters(bool subscribeToDiagnostics) { var diagnosticsMock = Substitute.For(); @@ -137,12 +137,12 @@ public void AddMicrosoftWebApp_WithConfigActionParameters(bool subscribeToDiagno Assert.Contains(configuredMsOptions, o => o.Action == _configureMsOptions); - AddMicrosoftWebApp_TestCommon(services, provider); - AddMicrosoftWebApp_TestSubscribesToDiagnostics(services, diagnosticsMock, subscribeToDiagnostics); + AddMicrosoftIdentityWebApp_TestCommon(services, provider); + AddMicrosoftIdentityWebApp_TestSubscribesToDiagnostics(services, diagnosticsMock, subscribeToDiagnostics); } [Fact] - public async Task AddMicrosoftWebApp_WithConfigNameParameters_TestRedirectToIdentityProviderEvent() + public async Task AddMicrosoftIdentityWebApp_WithConfigNameParameters_TestRedirectToIdentityProviderEvent() { var configMock = Substitute.For(); configMock.Configure().GetSection(ConfigSectionName).Returns(_configSection); @@ -159,11 +159,11 @@ public async Task AddMicrosoftWebApp_WithConfigNameParameters_TestRedirectToIden new AuthenticationBuilder(services) .AddMicrosoftIdentityWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); - await AddMicrosoftWebApp_TestRedirectToIdentityProviderEvent(services, redirectFunc).ConfigureAwait(false); + await AddMicrosoftIdentityWebApp_TestRedirectToIdentityProviderEvent(services, redirectFunc).ConfigureAwait(false); } [Fact] - public async Task AddMicrosoftWebApp_WithConfigActionParameters_TestRedirectToIdentityProviderEvent() + public async Task AddMicrosoftIdentityWebApp_WithConfigActionParameters_TestRedirectToIdentityProviderEvent() { var redirectFunc = Substitute.For>(); var services = new ServiceCollection() @@ -177,11 +177,11 @@ public async Task AddMicrosoftWebApp_WithConfigActionParameters_TestRedirectToId new AuthenticationBuilder(services) .AddMicrosoftWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme, false); - await AddMicrosoftWebApp_TestRedirectToIdentityProviderEvent(services, redirectFunc).ConfigureAwait(false); + await AddMicrosoftIdentityWebApp_TestRedirectToIdentityProviderEvent(services, redirectFunc).ConfigureAwait(false); } [Fact] - public async Task AddMicrosoftWebApp_WithConfigNameParameters_TestB2cSpecificSetup() + public async Task AddMicrosoftIdentityWebApp_WithConfigNameParameters_TestB2cSpecificSetup() { var configMock = Substitute.For(); _configSection = GetConfigSection(ConfigSectionName, true); @@ -199,7 +199,7 @@ public async Task AddMicrosoftWebApp_WithConfigNameParameters_TestB2cSpecificSet new AuthenticationBuilder(services) .AddMicrosoftIdentityWebApp(configMock, ConfigSectionName, OidcScheme, CookieScheme, false); - await AddMicrosoftWebApp_TestB2cSpecificSetup(services, remoteFailureFuncMock).ConfigureAwait(false); + await AddMicrosoftIdentityWebApp_TestB2cSpecificSetup(services, remoteFailureFuncMock).ConfigureAwait(false); } [Fact] @@ -226,7 +226,7 @@ public async Task AddMicrosoftWebApp_WithConfigActionParameters_B2cSpecificSetup new AuthenticationBuilder(services) .AddMicrosoftWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme, false); - await AddMicrosoftWebApp_TestB2cSpecificSetup(services, remoteFailureFuncMock).ConfigureAwait(false); + await AddMicrosoftIdentityWebApp_TestB2cSpecificSetup(services, remoteFailureFuncMock).ConfigureAwait(false); } [Fact] @@ -265,10 +265,10 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigNameParameters() var oidcOptions = provider.GetRequiredService>().Create(OidcScheme); - AddMicrosoftWebAppCallsWebApi_TestCommon(services, provider, oidcOptions, initialScopes); - await AddMicrosoftWebAppCallsWebApi_TestAuthorizationCodeReceivedEvent(provider, oidcOptions, authCodeReceivedFuncMock, tokenAcquisitionMock).ConfigureAwait(false); - await AddMicrosoftWebAppCallsWebApi_TestTokenValidatedEvent(provider, oidcOptions, tokenValidatedFuncMock).ConfigureAwait(false); - await AddMicrosoftWebAppCallsWebApi_TestRedirectToIdentityProviderForSignOutEvent(provider, oidcOptions, redirectFuncMock, tokenAcquisitionMock).ConfigureAwait(false); + AddMicrosoftIdentityWebAppCallsWebApi_TestCommon(services, provider, oidcOptions, initialScopes); + await AddMicrosoftIdentityWebAppCallsWebApi_TestAuthorizationCodeReceivedEvent(provider, oidcOptions, authCodeReceivedFuncMock, tokenAcquisitionMock).ConfigureAwait(false); + await AddMicrosoftIdentityWebAppCallsWebApi_TestTokenValidatedEvent(provider, oidcOptions, tokenValidatedFuncMock).ConfigureAwait(false); + await AddMicrosoftIdentityWebAppCallsWebApi_TestRedirectToIdentityProviderForSignOutEvent(provider, oidcOptions, redirectFuncMock, tokenAcquisitionMock).ConfigureAwait(false); } [Fact] @@ -307,10 +307,10 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigActionParameters() var oidcOptions = provider.GetRequiredService>().Create(OidcScheme); - AddMicrosoftWebAppCallsWebApi_TestCommon(services, provider, oidcOptions, initialScopes); - await AddMicrosoftWebAppCallsWebApi_TestAuthorizationCodeReceivedEvent(provider, oidcOptions, authCodeReceivedFuncMock, tokenAcquisitionMock).ConfigureAwait(false); - await AddMicrosoftWebAppCallsWebApi_TestTokenValidatedEvent(provider, oidcOptions, tokenValidatedFuncMock).ConfigureAwait(false); - await AddMicrosoftWebAppCallsWebApi_TestRedirectToIdentityProviderForSignOutEvent(provider, oidcOptions, redirectFuncMock, tokenAcquisitionMock).ConfigureAwait(false); + AddMicrosoftIdentityWebAppCallsWebApi_TestCommon(services, provider, oidcOptions, initialScopes); + await AddMicrosoftIdentityWebAppCallsWebApi_TestAuthorizationCodeReceivedEvent(provider, oidcOptions, authCodeReceivedFuncMock, tokenAcquisitionMock).ConfigureAwait(false); + await AddMicrosoftIdentityWebAppCallsWebApi_TestTokenValidatedEvent(provider, oidcOptions, tokenValidatedFuncMock).ConfigureAwait(false); + await AddMicrosoftIdentityWebAppCallsWebApi_TestRedirectToIdentityProviderForSignOutEvent(provider, oidcOptions, redirectFuncMock, tokenAcquisitionMock).ConfigureAwait(false); } [Fact] @@ -369,7 +369,7 @@ public async void AddMicrosoftWebApp_RedirectUri(string expectedUri) Assert.Equal(expectedUri, redirectContext.ProtocolMessage.RedirectUri); } - private void AddMicrosoftWebApp_TestCommon(IServiceCollection services, ServiceProvider provider) + private void AddMicrosoftIdentityWebApp_TestCommon(IServiceCollection services, ServiceProvider provider) { // Assert correct services added Assert.Contains(services, s => s.ServiceType == typeof(IConfigureOptions)); @@ -385,7 +385,7 @@ private void AddMicrosoftWebApp_TestCommon(IServiceCollection services, ServiceP Assert.Equal(ClaimConstants.PreferredUserName, oidcOptions.TokenValidationParameters.NameClaimType); } - private async Task AddMicrosoftWebApp_TestRedirectToIdentityProviderEvent(IServiceCollection services, Func redirectFunc) + private async Task AddMicrosoftIdentityWebApp_TestRedirectToIdentityProviderEvent(IServiceCollection services, Func redirectFunc) { var provider = services.BuildServiceProvider(); @@ -410,7 +410,7 @@ private async Task AddMicrosoftWebApp_TestRedirectToIdentityProviderEvent(IServi Assert.False(redirectContext.Properties.Parameters.ContainsKey(OpenIdConnectParameterNames.DomainHint)); } - private void AddMicrosoftWebApp_TestSubscribesToDiagnostics(IServiceCollection services, IOpenIdConnectMiddlewareDiagnostics diagnosticsMock, bool subscribeToDiagnostics) + private void AddMicrosoftIdentityWebApp_TestSubscribesToDiagnostics(IServiceCollection services, IOpenIdConnectMiddlewareDiagnostics diagnosticsMock, bool subscribeToDiagnostics) { services.RemoveAll(); services.AddSingleton((provider) => diagnosticsMock); @@ -430,7 +430,7 @@ private void AddMicrosoftWebApp_TestSubscribesToDiagnostics(IServiceCollection s } } - private async Task AddMicrosoftWebApp_TestB2cSpecificSetup(IServiceCollection services, Func remoteFailureFuncMock) + private async Task AddMicrosoftIdentityWebApp_TestB2cSpecificSetup(IServiceCollection services, Func remoteFailureFuncMock) { var provider = services.BuildServiceProvider(); @@ -461,7 +461,7 @@ private async Task AddMicrosoftWebApp_TestB2cSpecificSetup(IServiceCollection se Assert.Equal(Constants.One, redirectContext.ProtocolMessage.Parameters[ClaimConstants.ClientInfo].ToString(CultureInfo.InvariantCulture)); } - private void AddMicrosoftWebAppCallsWebApi_TestCommon(IServiceCollection services, ServiceProvider provider, OpenIdConnectOptions oidcOptions, IEnumerable initialScopes) + private void AddMicrosoftIdentityWebAppCallsWebApi_TestCommon(IServiceCollection services, ServiceProvider provider, OpenIdConnectOptions oidcOptions, IEnumerable initialScopes) { // Assert correct services added Assert.Contains(services, s => s.ServiceType == typeof(IHttpContextAccessor)); @@ -481,7 +481,7 @@ private void AddMicrosoftWebAppCallsWebApi_TestCommon(IServiceCollection service Assert.All(initialScopes, scope => Assert.Contains(scope, oidcOptions.Scope)); } - private async Task AddMicrosoftWebAppCallsWebApi_TestAuthorizationCodeReceivedEvent( + private async Task AddMicrosoftIdentityWebAppCallsWebApi_TestAuthorizationCodeReceivedEvent( IServiceProvider provider, OpenIdConnectOptions oidcOptions, Func authCodeReceivedFuncMock, @@ -496,7 +496,7 @@ private async Task AddMicrosoftWebAppCallsWebApi_TestAuthorizationCodeReceivedEv await tokenAcquisitionMock.ReceivedWithAnyArgs().AddAccountToCacheFromAuthorizationCodeAsync(Arg.Any(), Arg.Any>()).ConfigureAwait(false); } - private async Task AddMicrosoftWebAppCallsWebApi_TestTokenValidatedEvent(IServiceProvider provider, OpenIdConnectOptions oidcOptions, Func tokenValidatedFuncMock) + private async Task AddMicrosoftIdentityWebAppCallsWebApi_TestTokenValidatedEvent(IServiceProvider provider, OpenIdConnectOptions oidcOptions, Func tokenValidatedFuncMock) { var (httpContext, authScheme, authProperties) = CreateContextParameters(provider); @@ -517,7 +517,7 @@ private async Task AddMicrosoftWebAppCallsWebApi_TestTokenValidatedEvent(IServic Assert.True(tokenValidatedContext.Principal.HasClaim(c => c.Type == ClaimConstants.UniqueObjectIdentifier)); } - private async Task AddMicrosoftWebAppCallsWebApi_TestRedirectToIdentityProviderForSignOutEvent( + private async Task AddMicrosoftIdentityWebAppCallsWebApi_TestRedirectToIdentityProviderForSignOutEvent( IServiceProvider provider, OpenIdConnectOptions oidcOptions, Func redirectFuncMock, From e493c5a6278bf182f0b46ec3d9bfefbe682fef7c Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Mon, 10 Aug 2020 21:13:33 +0200 Subject: [PATCH 15/28] Make GetTokenForAppAsync less confusing and allow to pass tenantId #413 (#424) * Make GetTokenForAppAsync less confusing and allow to pass tenantId #413 Checked with @hpsin and here is what we agreed to: - Change the signature of `GetAccessTokenForUserAsync` to take a `string` (instead of a `IEnumerable`) as there is only one possible string for a given resource of App Id URI AppIdUri: "AppIdUri/.default". Check that the resource ends in "./default" - Add an additional optional parameter `tenant` to support this scenario, and verify that this tenant is not organizations (and of course common and consumers, which don't make sense) ```CSharp public async Task GetAccessTokenForAppAsync(string scope, string? tenant = null) ``` * Update src/Microsoft.Identity.Web/ITokenAcquisition.cs Co-authored-by: jennyf19 * Addressing PR feedback: - Adding an aka.ms link to the error messages (https://aka.ms/ms-id-web/daemon-scenarios) - using constants for the meta-tenants - Testing all the meta tenant Thanks @jennyf19 for this PR feedback * Addressing @hpsin 's PR feedback. --- .../Constants/Constants.cs | 1 + .../Constants/IDWebErrorMessage.cs | 4 ++ .../ITokenAcquisition.cs | 9 +++-- .../Microsoft.Identity.Web.xml | 23 ++++++++--- .../TokenAcquisition.cs | 38 ++++++++++++++++--- .../TestConstants.cs | 5 +-- .../AcquireTokenForAppIntegrationTests.cs | 29 +++++++++++--- 7 files changed, 84 insertions(+), 25 deletions(-) diff --git a/src/Microsoft.Identity.Web/Constants/Constants.cs b/src/Microsoft.Identity.Web/Constants/Constants.cs index c59f5a42a..e417617ad 100644 --- a/src/Microsoft.Identity.Web/Constants/Constants.cs +++ b/src/Microsoft.Identity.Web/Constants/Constants.cs @@ -31,6 +31,7 @@ internal static class Constants public const string MsaTenantId = "9188040d-6c67-4c5b-b112-36a304b66dad"; public const string Consumers = "consumers"; public const string Organizations = "organizations"; + public const string Common = "common"; // ClientInfo public const string ClientInfo = "client_info"; diff --git a/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs b/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs index a11689b57..41355123c 100644 --- a/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs +++ b/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs @@ -42,6 +42,10 @@ internal static class IDWebErrorMessage public const string TenantIdClaimNotPresentInToken = "IDW10401: Neither `tid` nor `tenantId` claim is present in the token obtained from Microsoft identity platform. "; public const string ClientInfoReturnedFromServerIsNull = "IDW10402: Client info returned from the server is null. "; public const string TokenIsNotJwtToken = "IDW10403: Token is not JWT token. "; + public const string ClientCredentialScopeParameterShouldEndInDotDefault = + "IDW10404: 'scope' parameter should be of the form 'AppIdUri/.default'. See https://aka.ms/ms-id-web/daemon-scenarios."; + public const string ClientCredentialTenantShouldBeTenanted = + "IDW10405: 'tenant' parameter should be a tenant ID or domain name, not 'common', or 'organizations'. See https://aka.ms/ms-id-web/daemon-scenarios."; // MSAL IDW10500 = "IDW10500:" public const string ExceptionAcquiringTokenForConfidentialClient = "IDW10501: Exception acquiring token for a confidential client. "; diff --git a/src/Microsoft.Identity.Web/ITokenAcquisition.cs b/src/Microsoft.Identity.Web/ITokenAcquisition.cs index f47d11659..81fcb4667 100644 --- a/src/Microsoft.Identity.Web/ITokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/ITokenAcquisition.cs @@ -37,12 +37,15 @@ Task GetAccessTokenForUserAsync( /// Acquires a token from the authority configured in the app, for the confidential client itself (not on behalf of a user) /// using the client credentials flow. See https://aka.ms/msal-net-client-credentials. /// - /// scopes requested to access a protected API. For this flow (client credentials), the scopes + /// The scope requested to access a protected API. For this flow (client credentials), the scope /// should be of the form "{ResourceIdUri/.default}" for instance https://management.azure.net/.default or, for Microsoft /// Graph, https://graph.microsoft.com/.default as the requested scopes are defined statically with the application registration - /// in the portal, and cannot be overridden in the application. + /// in the portal, cannot be overridden in the application, as you can request a token for only one resource at a time (use + /// several calls to get tokens for other resources). + /// Enables overriding of the tenant/account for the same identity. This is useful in the + /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. /// An access token for the app itself, based on its scopes. - Task GetAccessTokenForAppAsync(IEnumerable scopes); + Task GetAccessTokenForAppAsync(string scope, string? tenant); /// /// Used in Web APIs (which therefore cannot have an interaction with the user). diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 24ea03127..763e34188 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -658,15 +658,18 @@ cases where a given account is guest in other tenants, and you want to acquire tokens for a specific tenant, like where the user is a guest in. An access token to call on behalf of the user, the downstream API characterized by its scopes. - + Acquires a token from the authority configured in the app, for the confidential client itself (not on behalf of a user) using the client credentials flow. See https://aka.ms/msal-net-client-credentials. - scopes requested to access a protected API. For this flow (client credentials), the scopes + The scope requested to access a protected API. For this flow (client credentials), the scope should be of the form "{ResourceIdUri/.default}" for instance https://management.azure.net/.default or, for Microsoft Graph, https://graph.microsoft.com/.default as the requested scopes are defined statically with the application registration - in the portal, and cannot be overridden in the application. + in the portal, cannot be overridden in the application, as you can request a token for only one resource at a time (use + several calls to get tokens for other resources). + Enables overriding of the tenant/account for the same identity. This is useful in the + cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. An access token for the app itself, based on its scopes. @@ -1150,6 +1153,11 @@ Scopes which are already requested by MSAL.NET. They should not be re-requested;. + + + meta-tenant identifiers which are not allowed in client credentials. + + This handler is executed after the authorization code is received (once the user signs-in and consents) during the @@ -1224,15 +1232,18 @@ you have previously called AddAccountToCacheFromAuthorizationCodeAsync from a method called by OpenIdConnectOptions.Events.OnAuthorizationCodeReceived. - + Acquires a token from the authority configured in the app, for the confidential client itself (not on behalf of a user) using the client credentials flow. See https://aka.ms/msal-net-client-credentials. - scopes requested to access a protected API. For this flow (client credentials), the scopes + The scope requested to access a protected API. For this flow (client credentials), the scope should be of the form "{ResourceIdUri/.default}" for instance https://management.azure.net/.default or, for Microsoft Graph, https://graph.microsoft.com/.default as the requested scopes are defined statically with the application registration - in the portal, and cannot be overridden in the application. + in the portal, cannot be overridden in the application, as you can request a token for only one resource at a time (use + several calls to get tokens for other resources). + Enables overriding of the tenant/account for the same identity. This is useful + for multi tenant apps or daemons. An access token for the app itself, based on its scopes. diff --git a/src/Microsoft.Identity.Web/TokenAcquisition.cs b/src/Microsoft.Identity.Web/TokenAcquisition.cs index 39bcc2d6a..2cd3212e9 100644 --- a/src/Microsoft.Identity.Web/TokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/TokenAcquisition.cs @@ -81,6 +81,17 @@ public TokenAcquisition( OidcConstants.ScopeOfflineAccess, }; + /// + /// meta-tenant identifiers which are not allowed in client credentials. + /// + private readonly ISet _metaTenantIdentifiers = new HashSet( + new[] + { + Constants.Organizations, + Constants.Consumers, + }, + StringComparer.OrdinalIgnoreCase); + /// /// This handler is executed after the authorization code is received (once the user signs-in and consents) during the /// Authorization code flow grant flow in a web app. @@ -293,25 +304,40 @@ public async Task GetAccessTokenForUserAsync( /// Acquires a token from the authority configured in the app, for the confidential client itself (not on behalf of a user) /// using the client credentials flow. See https://aka.ms/msal-net-client-credentials. /// - /// scopes requested to access a protected API. For this flow (client credentials), the scopes + /// The scope requested to access a protected API. For this flow (client credentials), the scope /// should be of the form "{ResourceIdUri/.default}" for instance https://management.azure.net/.default or, for Microsoft /// Graph, https://graph.microsoft.com/.default as the requested scopes are defined statically with the application registration - /// in the portal, and cannot be overridden in the application. + /// in the portal, cannot be overridden in the application, as you can request a token for only one resource at a time (use + /// several calls to get tokens for other resources). + /// Enables overriding of the tenant/account for the same identity. This is useful + /// for multi tenant apps or daemons. /// An access token for the app itself, based on its scopes. - public async Task GetAccessTokenForAppAsync(IEnumerable scopes) + public async Task GetAccessTokenForAppAsync(string scope, string? tenant = null) { - if (scopes == null) + if (string.IsNullOrEmpty(scope)) { - throw new ArgumentNullException(nameof(scopes)); + throw new ArgumentNullException(nameof(scope)); + } + + if (!scope.EndsWith("/.default", true, CultureInfo.InvariantCulture)) + { + throw new ArgumentException(IDWebErrorMessage.ClientCredentialScopeParameterShouldEndInDotDefault, nameof(scope)); + } + + if (!string.IsNullOrEmpty(tenant) && _metaTenantIdentifiers.Contains(tenant)) + { + throw new ArgumentException(IDWebErrorMessage.ClientCredentialTenantShouldBeTenanted, nameof(tenant)); } // Use MSAL to get the right token to call the API _application = await GetOrBuildConfidentialClientApplicationAsync().ConfigureAwait(false); + string authority = CreateAuthorityBasedOnTenantIfProvided(_application, tenant); AuthenticationResult result; result = await _application - .AcquireTokenForClient(scopes.Except(_scopesRequestedByMsal)) + .AcquireTokenForClient(new string[] { scope }.Except(_scopesRequestedByMsal)) .WithSendX5C(_microsoftIdentityOptions.SendX5C) + .WithAuthority(authority) .ExecuteAsync() .ConfigureAwait(false); diff --git a/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs b/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs index b6c97162f..30cd5a240 100644 --- a/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs +++ b/tests/Microsoft.Identity.Web.Test.Common/TestConstants.cs @@ -78,10 +78,7 @@ public static class TestConstants ProductionNotPrefEnvironmentAlias, }; - public static readonly IEnumerable s_scopesForApp = new[] - { - "https://graph.microsoft.com/.default", - }; + public static readonly string s_scopeForApp = "https://graph.microsoft.com/.default"; public static readonly IEnumerable s_scopesForUser = new[] { diff --git a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForAppIntegrationTests.cs b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForAppIntegrationTests.cs index f41991c50..4a2fbd6ef 100644 --- a/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForAppIntegrationTests.cs +++ b/tests/Microsoft.Identity.Web.Test.Integration/AcquireTokenForAppIntegrationTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.Linq; using System.Net.Http; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -61,7 +62,7 @@ public async Task GetAccessTokenForApp_ReturnsAccessTokenAsync() // Act string token = - await _tokenAcquisition.GetAccessTokenForAppAsync(TestConstants.s_scopesForApp).ConfigureAwait(false); + await _tokenAcquisition.GetAccessTokenForAppAsync(TestConstants.s_scopeForApp).ConfigureAwait(false); // Assert Assert.NotNull(token); @@ -69,6 +70,24 @@ public async Task GetAccessTokenForApp_ReturnsAccessTokenAsync() AssertAppTokenInMemoryCache(TestConstants.ConfidentialClientId, 1); } + [Theory] + [InlineData(Constants.Organizations)] + [InlineData(Constants.Consumers)] + public async Task GetAccessTokenForApp_WithMetaTenant(string metaTenant) + { + // Arrange + InitializeTokenAcquisitionObjects(); + + Assert.Equal(0, _msalTestTokenCacheProvider.Count); + + async Task result() => + await _tokenAcquisition.GetAccessTokenForAppAsync(TestConstants.s_scopeForApp, metaTenant).ConfigureAwait(false); + + ArgumentException ex = await Assert.ThrowsAsync(result).ConfigureAwait(false); + Assert.Contains(IDWebErrorMessage.ClientCredentialTenantShouldBeTenanted, ex.Message); + Assert.Equal(0, _msalTestTokenCacheProvider.Count); + } + [Fact] public async Task GetAccessTokenForApp_WithUserScope_MsalServiceExceptionThrownAsync() { @@ -77,13 +96,11 @@ public async Task GetAccessTokenForApp_WithUserScope_MsalServiceExceptionThrownA // Act & Assert async Task result() => - await _tokenAcquisition.GetAccessTokenForAppAsync(TestConstants.s_scopesForUser).ConfigureAwait(false); + await _tokenAcquisition.GetAccessTokenForAppAsync(TestConstants.s_scopesForUser.FirstOrDefault()).ConfigureAwait(false); - MsalServiceException ex = await Assert.ThrowsAsync(result).ConfigureAwait(false); + ArgumentException ex = await Assert.ThrowsAsync(result).ConfigureAwait(false); - Assert.Contains(TestConstants.InvalidScopeError, ex.Message); - Assert.Equal(TestConstants.InvalidScope, ex.ErrorCode); - Assert.StartsWith(TestConstants.InvalidScopeErrorcode, ex.Message); + Assert.Contains(IDWebErrorMessage.ClientCredentialScopeParameterShouldEndInDotDefault, ex.Message); Assert.Equal(0, _msalTestTokenCacheProvider.Count); } From eb198b2cd76751bbb47aebdb3b9299a55344df79 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Mon, 10 Aug 2020 12:38:21 -0700 Subject: [PATCH 16/28] fix tests --- .../HttpContextExtensions.cs | 1 + ...tyWebApiAuthenticationBuilderExtensions.cs | 10 +++--- .../WebApiExtensionsTests.cs | 36 ++++++++++++++----- 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/Microsoft.Identity.Web/HttpContextExtensions.cs b/src/Microsoft.Identity.Web/HttpContextExtensions.cs index 693c7439c..92d33df3a 100644 --- a/src/Microsoft.Identity.Web/HttpContextExtensions.cs +++ b/src/Microsoft.Identity.Web/HttpContextExtensions.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using Microsoft.AspNetCore.Http; diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs index 29706dea0..df12e60ab 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs @@ -50,7 +50,7 @@ public static MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration AddM IConfigurationSection configurationSection = configuration.GetSection(configSectionName); - return builder.AddMicrosoftWebApi( + return builder.AddMicrosoftIdentityWebApi( configurationSection, jwtBearerScheme, subscribeToJwtBearerMiddlewareDiagnosticsEvents); @@ -67,7 +67,7 @@ public static MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration AddM /// Set to true if you want to debug, or just understand the JWT bearer events. /// /// The authentication builder to chain. - public static MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration AddMicrosoftWebApi( + public static MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration AddMicrosoftIdentityWebApi( this AuthenticationBuilder builder, IConfigurationSection configurationSection, string jwtBearerScheme = JwtBearerDefaults.AuthenticationScheme, @@ -83,7 +83,7 @@ public static MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration AddM throw new ArgumentNullException(nameof(builder)); } - AddMicrosoftWebApiImplementation( + AddMicrosoftIdentityWebApiImplementation( builder, options => configurationSection.Bind(options), options => configurationSection.Bind(options), @@ -130,7 +130,7 @@ public static MicrosoftIdentityWebApiAuthenticationBuilder AddMicrosoftIdentityW throw new ArgumentNullException(nameof(configureMicrosoftIdentityOptions)); } - AddMicrosoftWebApiImplementation( + AddMicrosoftIdentityWebApiImplementation( builder, configureJwtBearerOptions, configureMicrosoftIdentityOptions, @@ -145,7 +145,7 @@ public static MicrosoftIdentityWebApiAuthenticationBuilder AddMicrosoftIdentityW null); } - private static void AddMicrosoftWebApiImplementation(AuthenticationBuilder builder, Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions, string jwtBearerScheme, bool subscribeToJwtBearerMiddlewareDiagnosticsEvents) + private static void AddMicrosoftIdentityWebApiImplementation(AuthenticationBuilder builder, Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions, string jwtBearerScheme, bool subscribeToJwtBearerMiddlewareDiagnosticsEvents) { builder.AddJwtBearer(jwtBearerScheme, configureJwtBearerOptions); builder.Services.Configure(configureMicrosoftIdentityOptions); diff --git a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs index 0d59b0e95..36406e56f 100644 --- a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs @@ -193,7 +193,6 @@ private async void AddMicrosoftIdentityWebApi_TestJwtBearerTokenValidatedEvent(J { var scopeTypes = new[] { ClaimConstants.Scope, ClaimConstants.Scp, ClaimConstants.Roles, ClaimConstants.Role }; var expectedExceptionMessage = IDWebErrorMessage.NeitherScopeOrRolesClaimFoundInToken; - var scopeValue = "scope"; var httpContext = HttpContextUtilities.CreateHttpContext(); var authScheme = new AuthenticationScheme(JwtBearerDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme, typeof(JwtBearerHandler)); @@ -210,7 +209,7 @@ private async void AddMicrosoftIdentityWebApi_TestJwtBearerTokenValidatedEvent(J tokenValidatedContext.Principal = new ClaimsPrincipal( new ClaimsIdentity(new Claim[] { - new Claim(scopeType, scopeValue), + new Claim(scopeType, Constants.Scope), })); await jwtOptions.Events.TokenValidated(tokenValidatedContext).ConfigureAwait(false); } @@ -308,7 +307,8 @@ private IConfigurationSection GetConfigSection(string configSectionName) [Fact] public async Task AddMicrosoftIdentityWebApiCallsWebApi_WithConfigName() { - var config = Substitute.For(); + var configMock = Substitute.For(); + configMock.Configure().GetSection(ConfigSectionName).Returns(_configSection); var tokenValidatedFuncMock = Substitute.For>(); var services = new ServiceCollection() @@ -317,7 +317,13 @@ public async Task AddMicrosoftIdentityWebApiCallsWebApi_WithConfigName() options.Events ??= new JwtBearerEvents(); options.Events.OnTokenValidated += tokenValidatedFuncMock; }); - new AuthenticationBuilder(services).AddMicrosoftWebApiCallsWebApi(config, ConfigSectionName, JwtBearerScheme); + + services.AddAuthentication(JwtBearerScheme) + .AddMicrosoftIdentityWebApi( + configMock, + ConfigSectionName, + JwtBearerScheme) + .CallsWebApi(_configureAppOptions); var provider = services.BuildServiceProvider(); @@ -325,7 +331,7 @@ public async Task AddMicrosoftIdentityWebApiCallsWebApi_WithConfigName() provider.GetRequiredService>().Create(string.Empty); provider.GetRequiredService>().Create(string.Empty); - config.Received(2).GetSection(ConfigSectionName); + configMock.Received(1).GetSection(ConfigSectionName); await AddMicrosoftIdentityWebApiCallsWebApi_TestCommon(services, provider, tokenValidatedFuncMock).ConfigureAwait(false); } @@ -340,8 +346,16 @@ public async Task AddMicrosoftIdentityWebApiCallsWebApi_WithConfigActions() options.Events ??= new JwtBearerEvents(); options.Events.OnTokenValidated += tokenValidatedFuncMock; }); - new AuthenticationBuilder(services).AddMicrosoftWebApiCallsWebApi(_configureAppOptions, _configureMsOptions, JwtBearerScheme); - + services.AddAuthentication(JwtBearerScheme) + .AddMicrosoftIdentityWebApi( + (options) => + { + options.Events ??= new JwtBearerEvents(); + options.Events.OnTokenValidated += tokenValidatedFuncMock; + }, + _configureMsOptions, + JwtBearerScheme) + .CallsWebApi(_configureAppOptions); var provider = services.BuildServiceProvider(); // Assert configure options actions added correctly @@ -367,12 +381,16 @@ private async Task AddMicrosoftIdentityWebApiCallsWebApi_TestCommon(IServiceColl var jwtOptions = provider.GetRequiredService>().Create(JwtBearerScheme); var httpContext = HttpContextUtilities.CreateHttpContext(); var authScheme = new AuthenticationScheme(JwtBearerDefaults.AuthenticationScheme, JwtBearerDefaults.AuthenticationScheme, typeof(JwtBearerHandler)); + var tokenValidatedContext = new TokenValidatedContext(httpContext, authScheme, jwtOptions) { SecurityToken = new JwtSecurityToken(), - Principal = new ClaimsPrincipal(), }; - + tokenValidatedContext.Principal = new ClaimsPrincipal( + new ClaimsIdentity(new Claim[] + { + new Claim(ClaimConstants.Scope, Constants.Scope), + })); await jwtOptions.Events.TokenValidated(tokenValidatedContext).ConfigureAwait(false); // Assert events called From 843d416f06ccdc88409c644ff78baefc810ae52b Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Mon, 10 Aug 2020 12:40:15 -0700 Subject: [PATCH 17/28] add xml comments --- src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 33c0d0fda..f16c06e08 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1761,7 +1761,7 @@ The authentication builder to chain. - + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. From 01fd1793128b2a7037869244db7b44fed1d0df56 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Mon, 10 Aug 2020 17:54:20 -0700 Subject: [PATCH 18/28] few spelling changes --- .../MicrosoftIdentityWebApiAuthenticationBuilder.cs | 6 +++--- ...crosoftIdentityWebApiAuthenticationBuilderExtensions.cs | 7 ++++++- ...IdentityWebAppAuthenticationBuilderWithConfiguration.cs | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs index 005ddafc4..bbc936e05 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs @@ -16,10 +16,10 @@ namespace Microsoft.Identity.Web public class MicrosoftIdentityWebApiAuthenticationBuilder : MicrosoftIdentityBaseAuthenticationBuilder { /// - /// Constructor. + /// Constructor. /// - /// The services being configured. - /// Defaut scheme used for OpenIdConnect. + /// The services being configured. + /// Default scheme used for OpenIdConnect. /// ACtion called to configure the JwtBearer options. /// Action called to configure /// the Microsoft identity options. diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs index df12e60ab..0fb4761fb 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderExtensions.cs @@ -145,7 +145,12 @@ public static MicrosoftIdentityWebApiAuthenticationBuilder AddMicrosoftIdentityW null); } - private static void AddMicrosoftIdentityWebApiImplementation(AuthenticationBuilder builder, Action configureJwtBearerOptions, Action configureMicrosoftIdentityOptions, string jwtBearerScheme, bool subscribeToJwtBearerMiddlewareDiagnosticsEvents) + private static void AddMicrosoftIdentityWebApiImplementation( + AuthenticationBuilder builder, + Action configureJwtBearerOptions, + Action configureMicrosoftIdentityOptions, + string jwtBearerScheme, + bool subscribeToJwtBearerMiddlewareDiagnosticsEvents) { builder.AddJwtBearer(jwtBearerScheme, configureJwtBearerOptions); builder.Services.Configure(configureMicrosoftIdentityOptions); diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs index 5e6ba5f18..4f655c543 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs @@ -15,7 +15,7 @@ namespace Microsoft.Identity.Web public class MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration : MicrosoftIdentityWebAppAuthenticationBuilder { /// - /// Constructor. + /// Constructor. /// /// The services being configured. /// Default scheme used for OpenIdConnect. From e6f346b028bfdd378f39a25f90a3fbba458725d0 Mon Sep 17 00:00:00 2001 From: Jenny Ferries Date: Tue, 11 Aug 2020 14:30:53 -0700 Subject: [PATCH 19/28] renaming of CallsWebApi to EnableTokenAcquisitionToCallDownstreamApi --- .../BlazorServerWeb-CSharp/Startup.cs | 4 ++-- .../Server/Startup.cs | 4 ++-- .../templates/RazorPagesWeb-CSharp/Startup.cs | 4 ++-- .../templates/StarterWeb-CSharp/Startup.cs | 4 ++-- .../templates/WebApi-CSharp/Startup.cs | 4 ++-- .../Microsoft.Identity.Web.xml | 20 +++++++++---------- ...lsWebApiAuthenticationBuilderExtensions.cs | 4 ++-- ...lsWebApiAuthenticationBuilderExtensions.cs | 6 +++--- .../DistributedTokenCacheAdapterExtension.cs | 2 +- .../InMemoryTokenCacheProviderExtension.cs | 2 +- .../SessionTokenCacheProviderExtension.cs | 2 +- ...softIdentityWebApiAuthenticationBuilder.cs | 2 +- ...iAuthenticationBuilderWithConfiguration.cs | 4 ++-- ...tyAppCallingWebApiAuthenticationBuilder.cs | 2 +- ...softIdentityWebAppAuthenticationBuilder.cs | 2 +- ...pAuthenticationBuilderWithConfiguration.cs | 6 +++--- tests/B2CWebAppCallsWebApi/Client/Startup.cs | 2 +- tests/BlazorServerCallsGraph/Startup.cs | 2 +- .../WebApiExtensionsTests.cs | 4 ++-- .../WebAppExtensionsTests.cs | 6 +++--- tests/WebAppCallsMicrosoftGraph/Startup.cs | 8 ++++---- .../Client/Startup.cs | 2 +- .../TodoListService/Startup.cs | 2 +- 23 files changed, 49 insertions(+), 49 deletions(-) diff --git a/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs b/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs index 94266030f..f65862e28 100644 --- a/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs +++ b/ProjectTemplates/templates/BlazorServerWeb-CSharp/Startup.cs @@ -78,7 +78,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); #else ; @@ -97,7 +97,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); diff --git a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs index f9a9d5583..9f2e33a95 100644 --- a/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs +++ b/ProjectTemplates/templates/ComponentsWebAssembly-CSharp/Server/Startup.cs @@ -64,7 +64,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); #else ; @@ -80,7 +80,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); diff --git a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs index 3cd81f2b9..0fc9dc9b2 100644 --- a/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs +++ b/ProjectTemplates/templates/RazorPagesWeb-CSharp/Startup.cs @@ -64,7 +64,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); #else ; @@ -80,7 +80,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); diff --git a/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs b/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs index 872491972..92772bd99 100644 --- a/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs +++ b/ProjectTemplates/templates/StarterWeb-CSharp/Startup.cs @@ -64,7 +64,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); #else ; @@ -80,7 +80,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); diff --git a/ProjectTemplates/templates/WebApi-CSharp/Startup.cs b/ProjectTemplates/templates/WebApi-CSharp/Startup.cs index f348a2b72..bef5b3249 100644 --- a/ProjectTemplates/templates/WebApi-CSharp/Startup.cs +++ b/ProjectTemplates/templates/WebApi-CSharp/Startup.cs @@ -38,7 +38,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd")) #if (GenerateApiOrGraph) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); #else @@ -55,7 +55,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAdB2C")) #if (GenerateApi) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 08108f5a1..88adfb363 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1736,17 +1736,17 @@ - Constructor. + Constructor. - The services being configured. - Defaut scheme used for OpenIdConnect. + The services being configured. + Default scheme used for OpenIdConnect. ACtion called to configure the JwtBearer options. Action called to configure the Microsoft identity options. Configuration section from which to get parameters. - + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). @@ -1802,7 +1802,7 @@ Builder for Web API authentication with configuration. - + Protects the web API with Microsoft identity platform (formerly Azure AD v2.0). This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. @@ -1829,7 +1829,7 @@ - Authentication builder returned by the CallsWebApi methods + Authentication builder returned by the EnableTokenAcquisitionToCallDownstreamApi methods enabling you to decide token cache implementations. @@ -1866,7 +1866,7 @@ the Microsoft identity options. Optional configuration section. - + The Web app calls a Web API. This override enables you to specify the ConfidentialClientApplicationOptions (from MSAL.NET) programmatically. @@ -1957,12 +1957,12 @@ Builder for a Microsoft identity web app authentication where configuration is - available for CallsWebApi. + available for EnableTokenAcquisitionToCallDownstreamApi. - Constructor. + Constructor. The services being configured. Default scheme used for OpenIdConnect. @@ -1970,7 +1970,7 @@ the Microsoft identity options. Optional configuration section. - + Add support for the web app to acquire tokens to call an API. diff --git a/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs index 55e612285..953a7b3f1 100644 --- a/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs @@ -24,7 +24,7 @@ public static partial class MicrosoftIdentityWebApiCallsWebApiAuthenticationBuil /// The section name in the config file (by default "AzureAd"). /// The scheme for the JWT bearer token. /// The authentication builder to chain. - [Obsolete("Rather use AddMicrosoftIdentityWebApi().CallsWebApi")] + [Obsolete("Rather use AddMicrosoftIdentityWebApi().EnableTokenAcquisitionToCallDownstreamApi")] public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( this AuthenticationBuilder builder, IConfiguration configuration, @@ -45,7 +45,7 @@ public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( /// The action to configure . /// The scheme for the JWT bearer token. /// The authentication builder to chain. - [Obsolete("Rather use AddMicrosoftIdentityWebApi().CallsWebApi")] + [Obsolete("Rather use AddMicrosoftIdentityWebApi().EnableTokenAcquisitionToCallDownstreamApi")] public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( this AuthenticationBuilder builder, Action configureConfidentialClientApplicationOptions, diff --git a/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExtensions.cs index a91ea953a..56c26f5e7 100644 --- a/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExtensions.cs @@ -31,7 +31,7 @@ public static class MicrosoftIdentityWebAppCallsWebApiAuthenticationBuilderExten /// This method cannot be used with Azure AD B2C, as with B2C an initial scope needs /// to be provided. /// - [Obsolete("Rather use AddMicrosoftIdentityWebApp().CallsWebApi")] + [Obsolete("Rather use AddMicrosoftIdentityWebApp().EnableTokenAcquisitionToCallDownstreamApi")] private static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( this MicrosoftIdentityWebAppAuthenticationBuilder builder, IConfiguration configuration, @@ -57,7 +57,7 @@ private static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebAppCa /// (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support /// several OpenID Connect identity providers. /// The authentication builder for chaining. - [Obsolete("Rather use AddMicrosoftIdentityWebApp().CallsWebApi")] + [Obsolete("Rather use AddMicrosoftIdentityWebApp().EnableTokenAcquisitionToCallDownstreamApi")] public static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( this MicrosoftIdentityWebAppAuthenticationBuilder builder, IConfiguration configuration, @@ -83,7 +83,7 @@ public static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebAppCal /// (by default, OpenIdConnectDefaults.AuthenticationScheme). This can be specified when you want to support /// several OpenID Connect identity providers. /// The authentication builder for chaining. - [Obsolete("Rather use AddMicrosoftIdentityWebApp().CallsWebApi")] + [Obsolete("Rather use AddMicrosoftIdentityWebApp().EnableTokenAcquisitionToCallDownstreamApi")] public static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebAppCallsWebApi( this MicrosoftIdentityWebAppAuthenticationBuilder builder, IEnumerable? initialScopes, diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs index 2bf76d67e..da923d54b 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/Distributed/DistributedTokenCacheAdapterExtension.cs @@ -15,7 +15,7 @@ public static class DistributedTokenCacheAdapterExtension /// Adds both the app and per-user in-memory token caches. /// The services collection to add to. /// A to chain. - [Obsolete("Rather use .CallsWebApi().AddDistributedTokenCaches()")] + [Obsolete("Rather use .EnableTokenAcquisitionToCallDownstreamApi().AddDistributedTokenCaches()")] internal static IServiceCollection AddDistributedTokenCaches( this IServiceCollection services) { diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs index 820bbca03..765b7e742 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/InMemory/InMemoryTokenCacheProviderExtension.cs @@ -15,7 +15,7 @@ public static class InMemoryTokenCacheProviderExtension /// Adds both the app and per-user in-memory token caches. /// The services collection to add to. /// the services (for chaining). - [Obsolete("Rather use .CallsWebApi().AddInMemoryTokenCaches()")] + [Obsolete("Rather use .EnableTokenAcquisitionToCallDownstreamApi().AddInMemoryTokenCaches()")] internal static IServiceCollection AddInMemoryTokenCaches( this IServiceCollection services) { diff --git a/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs b/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs index 6474de9dd..5116a7799 100644 --- a/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs +++ b/src/Microsoft.Identity.Web/TokenCacheProviders/Session/SessionTokenCacheProviderExtension.cs @@ -38,7 +38,7 @@ public static class SessionTokenCacheProviderExtension /// /// The services collection to add to. /// The service collection. - [Obsolete("Rather use .CallsWebApi().AddSessionTokenCaches()")] + [Obsolete("Rather use .EnableTokenAcquisitionToCallDownstreamApi().AddSessionTokenCaches()")] internal static IServiceCollection AddSessionTokenCaches(this IServiceCollection services) { if (services == null) diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs index bbc936e05..a6ea74611 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilder.cs @@ -61,7 +61,7 @@ internal MicrosoftIdentityWebApiAuthenticationBuilder( /// /// The action to configure . /// The authentication builder to chain. - public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder CallsWebApi( + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder EnableTokenAcquisitionToCallDownstreamApi( Action configureConfidentialClientApplicationOptions) { if (configureConfidentialClientApplicationOptions == null) diff --git a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs index b7aa63a01..3ad582ba8 100644 --- a/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs +++ b/src/Microsoft.Identity.Web/WebApiExtensions/MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration.cs @@ -32,9 +32,9 @@ internal MicrosoftIdentityWebApiAuthenticationBuilderWithConfiguration( /// This method expects the configuration file will have a section, named "AzureAd" as default, with the necessary settings to initialize authentication options. /// /// The authentication builder to chain. - public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder CallsWebApi() + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder EnableTokenAcquisitionToCallDownstreamApi() { - return CallsWebApi(options => ConfigurationSection.Bind(options)); + return EnableTokenAcquisitionToCallDownstreamApi(options => ConfigurationSection.Bind(options)); } } } diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs index b94a09535..af096ff25 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityAppCallingWebApiAuthenticationBuilder.cs @@ -16,7 +16,7 @@ namespace Microsoft.Identity.Web { /// - /// Authentication builder returned by the CallsWebApi methods + /// Authentication builder returned by the EnableTokenAcquisitionToCallDownstreamApi methods /// enabling you to decide token cache implementations. /// public class MicrosoftIdentityAppCallsWebApiAuthenticationBuilder : MicrosoftIdentityBaseAuthenticationBuilder diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs index 43749ea63..45abddeb5 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilder.cs @@ -54,7 +54,7 @@ internal MicrosoftIdentityWebAppAuthenticationBuilder( /// MSAL.NET confidential client application options. /// Initial scopes. /// The builder itself for chaining. - public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder CallsWebApi( + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder EnableTokenAcquisitionToCallDownstreamApi( Action configureConfidentialClientApplicationOptions, IEnumerable? initialScopes = null) { diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs index 4f655c543..0ea59eacf 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration.cs @@ -10,7 +10,7 @@ namespace Microsoft.Identity.Web { /// /// Builder for a Microsoft identity web app authentication where configuration is - /// available for CallsWebApi. + /// available for EnableTokenAcquisitionToCallDownstreamApi. /// public class MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration : MicrosoftIdentityWebAppAuthenticationBuilder { @@ -40,10 +40,10 @@ internal MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration( /// /// Optional initial scopes to request. /// The authentication builder for chaining. - public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder CallsWebApi( + public MicrosoftIdentityAppCallsWebApiAuthenticationBuilder EnableTokenAcquisitionToCallDownstreamApi( IEnumerable? initialScopes = null) { - return CallsWebApi( + return EnableTokenAcquisitionToCallDownstreamApi( options => ConfigurationSection.Bind(options), initialScopes); } diff --git a/tests/B2CWebAppCallsWebApi/Client/Startup.cs b/tests/B2CWebAppCallsWebApi/Client/Startup.cs index 8d65e4384..399c1a256 100644 --- a/tests/B2CWebAppCallsWebApi/Client/Startup.cs +++ b/tests/B2CWebAppCallsWebApi/Client/Startup.cs @@ -43,7 +43,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration, "AzureAdB2C") - .CallsWebApi(initialScopes: new string[] { Configuration["TodoList:TodoListScope"] }) + .EnableTokenAcquisitionToCallDownstreamApi(initialScopes: new string[] { Configuration["TodoList:TodoListScope"] }) .AddInMemoryTokenCaches(); // Add APIs diff --git a/tests/BlazorServerCallsGraph/Startup.cs b/tests/BlazorServerCallsGraph/Startup.cs index 89727bfed..9e4db9853 100644 --- a/tests/BlazorServerCallsGraph/Startup.cs +++ b/tests/BlazorServerCallsGraph/Startup.cs @@ -29,7 +29,7 @@ public void ConfigureServices(IServiceCollection services) string[] scopes = Configuration.GetValue("CalledApi:CalledApiScopes")?.Split(' '); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") - .CallsWebApi(scopes) + .EnableTokenAcquisitionToCallDownstreamApi(scopes) .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); diff --git a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs index 36406e56f..187067a28 100644 --- a/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebApiExtensionsTests.cs @@ -323,7 +323,7 @@ public async Task AddMicrosoftIdentityWebApiCallsWebApi_WithConfigName() configMock, ConfigSectionName, JwtBearerScheme) - .CallsWebApi(_configureAppOptions); + .EnableTokenAcquisitionToCallDownstreamApi(_configureAppOptions); var provider = services.BuildServiceProvider(); @@ -355,7 +355,7 @@ public async Task AddMicrosoftIdentityWebApiCallsWebApi_WithConfigActions() }, _configureMsOptions, JwtBearerScheme) - .CallsWebApi(_configureAppOptions); + .EnableTokenAcquisitionToCallDownstreamApi(_configureAppOptions); var provider = services.BuildServiceProvider(); // Assert configure options actions added correctly diff --git a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs index 335e076a0..dd7512dcf 100644 --- a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs @@ -243,7 +243,7 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigNameParameters() var builder = services.AddAuthentication() .AddMicrosoftIdentityWebApp(configMock, ConfigSectionName, OidcScheme) - .CallsWebApi(initialScopes); + .EnableTokenAcquisitionToCallDownstreamApi(initialScopes); services.Configure(OidcScheme, (options) => { options.Events ??= new OpenIdConnectEvents(); @@ -284,7 +284,7 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigActionParameters() var builder = services.AddAuthentication() .AddMicrosoftWebApp(_configureMsOptions, null, OidcScheme) - .CallsWebApi(_configureAppOptions, initialScopes); + .EnableTokenAcquisitionToCallDownstreamApi(_configureAppOptions, initialScopes); services.Configure(OidcScheme, (options) => { options.Events ??= new OpenIdConnectEvents(); @@ -321,7 +321,7 @@ public void AddMicrosoftWebAppCallsWebApi_NoScopes() services.AddAuthentication() .AddMicrosoftIdentityWebApp(Substitute.For()) - .CallsWebApi(); + .EnableTokenAcquisitionToCallDownstreamApi(); var provider = services.BuildServiceProvider(); diff --git a/tests/WebAppCallsMicrosoftGraph/Startup.cs b/tests/WebAppCallsMicrosoftGraph/Startup.cs index 5fb62861e..dc09bff53 100644 --- a/tests/WebAppCallsMicrosoftGraph/Startup.cs +++ b/tests/WebAppCallsMicrosoftGraph/Startup.cs @@ -29,13 +29,13 @@ public void ConfigureServices(IServiceCollection services) { services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); // Add a delegate overload. Should return the parent builder /* * services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches() // Change the builder .AddAuthentication() @@ -46,7 +46,7 @@ public void ConfigureServices(IServiceCollection services) /* OR services.AddMicrosoftIdentityWebAppAuthentication(Configuration) - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) @@ -55,7 +55,7 @@ public void ConfigureServices(IServiceCollection services) Configuration.Bind("AzureAd", options); // do something }) - .CallsWebApi(options => + .EnableTokenAcquisitionToCallDownstreamApi(options => { Configuration.Bind("AzureAd", options); // do something diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs index 0fbe55a2e..4bd54969d 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs @@ -44,7 +44,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); // Add APIs diff --git a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs index 7fc348fee..0d459f6c7 100644 --- a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Startup.cs @@ -33,7 +33,7 @@ public void ConfigureServices(IServiceCollection services) // Adds Microsoft Identity platform (AAD v2.0) support to protect this Api services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(Configuration, "AzureAd") - .CallsWebApi() + .EnableTokenAcquisitionToCallDownstreamApi() .AddInMemoryTokenCaches(); services.AddControllers(); From fbffb7185ea81bb6ad6c2dabfff0571cbe81e4e2 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Wed, 12 Aug 2020 10:55:31 +0200 Subject: [PATCH 20/28] - Adding a missing renaming for AddMicrosoftWebApp => AddMicrosoftIdentityWebApp - Updating the ITokenAcquisition.GetTokenForAppAsync signature to match the class. --- src/Microsoft.Identity.Web/ITokenAcquisition.cs | 2 +- src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml | 2 +- ...WebApiCallsWebApiAuthenticationBuilderExtensions.cs | 2 ++ ...oftIdentityWebAppAuthenticationBuilderExtensions.cs | 2 +- .../WebAppExtensionsTests.cs | 10 +++++----- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/Microsoft.Identity.Web/ITokenAcquisition.cs b/src/Microsoft.Identity.Web/ITokenAcquisition.cs index 81fcb4667..6e4c233f2 100644 --- a/src/Microsoft.Identity.Web/ITokenAcquisition.cs +++ b/src/Microsoft.Identity.Web/ITokenAcquisition.cs @@ -45,7 +45,7 @@ Task GetAccessTokenForUserAsync( /// Enables overriding of the tenant/account for the same identity. This is useful in the /// cases where a given account is a guest in other tenants, and you want to acquire tokens for a specific tenant. /// An access token for the app itself, based on its scopes. - Task GetAccessTokenForAppAsync(string scope, string? tenant); + Task GetAccessTokenForAppAsync(string scope, string? tenant = null); /// /// Used in Web APIs (which therefore cannot have an interaction with the user). diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 88adfb363..2e45f8524 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -1911,7 +1911,7 @@ The authentication builder for chaining. - + Add authentication with Microsoft identity platform. diff --git a/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs index 953a7b3f1..00ba1cb06 100644 --- a/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/MigrationAid/MicrosoftIdentityWebApiCallsWebApiAuthenticationBuilderExtensions.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System; +using System.ComponentModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Configuration; @@ -25,6 +26,7 @@ public static partial class MicrosoftIdentityWebApiCallsWebApiAuthenticationBuil /// The scheme for the JWT bearer token. /// The authentication builder to chain. [Obsolete("Rather use AddMicrosoftIdentityWebApi().EnableTokenAcquisitionToCallDownstreamApi")] + [EditorBrowsable(EditorBrowsableState.Never)] public static AuthenticationBuilder AddMicrosoftWebApiCallsWebApi( this AuthenticationBuilder builder, IConfiguration configuration, diff --git a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs index 4a4d1cb42..4e51966b2 100644 --- a/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs +++ b/src/Microsoft.Identity.Web/WebAppExtensions/MicrosoftIdentityWebAppAuthenticationBuilderExtensions.cs @@ -111,7 +111,7 @@ public static MicrosoftIdentityWebAppAuthenticationBuilderWithConfiguration AddM /// Set to true if you want to debug, or just understand the OpenID Connect events. /// /// The authentication builder for chaining. - public static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftWebApp( + public static MicrosoftIdentityWebAppAuthenticationBuilder AddMicrosoftIdentityWebApp( this AuthenticationBuilder builder, Action configureMicrosoftIdentityOptions, Action? configureCookieAuthenticationOptions = null, diff --git a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs index dd7512dcf..6fc9993ba 100644 --- a/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs +++ b/tests/Microsoft.Identity.Web.Test/WebAppExtensionsTests.cs @@ -122,7 +122,7 @@ public void AddMicrosoftIdentityWebApp_WithConfigActionParameters(bool subscribe services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme, subscribeToDiagnostics); + .AddMicrosoftIdentityWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme, subscribeToDiagnostics); var provider = services.BuildServiceProvider(); @@ -175,7 +175,7 @@ public async Task AddMicrosoftIdentityWebApp_WithConfigActionParameters_TestRedi services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme, false); + .AddMicrosoftIdentityWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme, false); await AddMicrosoftIdentityWebApp_TestRedirectToIdentityProviderEvent(services, redirectFunc).ConfigureAwait(false); } @@ -224,7 +224,7 @@ public async Task AddMicrosoftWebApp_WithConfigActionParameters_B2cSpecificSetup services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme, false); + .AddMicrosoftIdentityWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme, false); await AddMicrosoftIdentityWebApp_TestB2cSpecificSetup(services, remoteFailureFuncMock).ConfigureAwait(false); } @@ -283,7 +283,7 @@ public async Task AddMicrosoftWebAppCallsWebApi_WithConfigActionParameters() var services = new ServiceCollection(); var builder = services.AddAuthentication() - .AddMicrosoftWebApp(_configureMsOptions, null, OidcScheme) + .AddMicrosoftIdentityWebApp(_configureMsOptions, null, OidcScheme) .EnableTokenAcquisitionToCallDownstreamApi(_configureAppOptions, initialScopes); services.Configure(OidcScheme, (options) => { @@ -348,7 +348,7 @@ public async void AddMicrosoftWebApp_RedirectUri(string expectedUri) var services = new ServiceCollection(); services.AddDataProtection(); new AuthenticationBuilder(services) - .AddMicrosoftWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme); + .AddMicrosoftIdentityWebApp(_configureMsOptions, _configureCookieOptions, OidcScheme, CookieScheme); var provider = services.BuildServiceProvider(); From 3c71db7476f7ad4f9bd2aebefd609e70581178ed Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Wed, 12 Aug 2020 11:20:41 +0200 Subject: [PATCH 21/28] Fixing the TodoListService controller in WebAppCallsWebApiCallsGraph --- .../TodoListService/Controllers/TodoListController.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Controllers/TodoListController.cs b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Controllers/TodoListController.cs index feb0b959e..fb588d91c 100644 --- a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Controllers/TodoListController.cs +++ b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Controllers/TodoListController.cs @@ -76,7 +76,7 @@ public IActionResult Post([FromBody] Todo todo) { HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi); int id = TodoStore.Values.OrderByDescending(x => x.Id).FirstOrDefault().Id + 1; - Todo todonew = new Todo() { Id = id, Owner = HttpContext.User.Identity.Name, Title = todo.Title }; + Todo todonew = new Todo() { Id = id, Owner = User.GetDisplayName(), Title = todo.Title }; TodoStore.Add(id, todonew); return Ok(todo); From ee38779f4a58d3614c485fdc8af0be3f7cf47770 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Wed, 12 Aug 2020 11:54:23 +0200 Subject: [PATCH 22/28] Smaller PR for MicrosoftGraphClientService --- .../Microsoft.Identity.Web.csproj | 1 + .../Microsoft.Identity.Web.xml | 61 ++++++++++++ .../MicrosoftGraph/MicrosoftGraphOptions.cs | 24 +++++ .../MicrosoftGraphServiceExtensions.cs | 93 +++++++++++++++++++ .../TokenAcquisitionCredentialProvider.cs | 22 +++-- .../Client/TodoListClient.csproj | 1 - .../MicrosoftGraphServiceExtensions.cs | 36 ------- tests/BlazorServerCallsGraph/Startup.cs | 6 +- tests/BlazorServerCallsGraph/appsettings.json | 4 + tests/BlazorServerCallsGraph/blazor.csproj | 1 - .../MicrosoftGraphServiceExtensions.cs | 43 --------- tests/WebAppCallsMicrosoftGraph/Startup.cs | 4 +- .../TokenAcquisitionCredentialProvider.cs | 30 ------ .../WebAppCallsMicrosoftGraph.csproj | 3 - .../appsettings.json | 6 +- .../Client/TodoListClient.csproj | 1 - .../Controllers/TodoListController.cs | 2 +- 17 files changed, 208 insertions(+), 130 deletions(-) create mode 100644 src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphOptions.cs create mode 100644 src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphServiceExtensions.cs rename {tests/BlazorServerCallsGraph/Services => src/Microsoft.Identity.Web/MicrosoftGraph}/TokenAcquisitionCredentialProvider.cs (54%) delete mode 100644 tests/BlazorServerCallsGraph/Services/MicrosoftGraphServiceExtensions.cs delete mode 100644 tests/WebAppCallsMicrosoftGraph/MicrosoftGraphServiceExtensions.cs delete mode 100644 tests/WebAppCallsMicrosoftGraph/TokenAcquisitionCredentialProvider.cs diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj index 54ca38968..aaaf01e96 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.csproj @@ -94,6 +94,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + all diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 2e45f8524..ab6114de2 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -727,6 +727,67 @@ OpenID Connect event. A that represents a completed remove from cache operation. + + + Options passed-in to call Microsoft Graph. + + + + + Base URL for the Microsoft Graph API. By default: "https://graph.microsoft.com/v1.0/" + but it can be changed to use the Microsoft Graph Beta endpoint or national cloud versions + of MicrosoftGraph. + + + + + Space separated scopes used to call Microsoft Graph, + for instance user.read mail.read. + + + + + Extensions methods on a MicrososoftAppCallingWebApiAuthenticationBuilder builder + to add support to call Microsoft Graph. + + + + + Add support to calls Microsoft graph. From a named option and a configuration section. + + Builder. + Configuraiton section. + The builder to chain. + + + + Add support to calls Microsoft graph. From a base graph Url and a default scope. + + Builder. + Named instance of option. + Configuraiton section. + The builder to chain. + + + + Add support to calls Microsoft graph. From a named options and a configuraiton method. + + Builder. + Method to configure the options. + The builder to chain. + + + + Authentication provider based on MSAL.NET. + + + + + Adds a bearer header to an HttpRequestMessage. + + HttpRequest message to authenticate. + A Task (as this is an async method). + Base class for Web app and Web API Microsoft Identity authentication diff --git a/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphOptions.cs b/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphOptions.cs new file mode 100644 index 000000000..26e4db521 --- /dev/null +++ b/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphOptions.cs @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Identity.Web +{ + /// + /// Options passed-in to call Microsoft Graph. + /// + public class MicrosoftGraphOptions + { + /// + /// Base URL for the Microsoft Graph API. By default: "https://graph.microsoft.com/v1.0/" + /// but it can be changed to use the Microsoft Graph Beta endpoint or national cloud versions + /// of MicrosoftGraph. + /// + public string BaseUrl { get; set; } = "https://graph.microsoft.com/v1.0/"; + + /// + /// Space separated scopes used to call Microsoft Graph, + /// for instance user.read mail.read. + /// + public string? Scopes { get; set; } = "user.read"; + } +} diff --git a/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphServiceExtensions.cs b/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphServiceExtensions.cs new file mode 100644 index 000000000..af08ebb5c --- /dev/null +++ b/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphServiceExtensions.cs @@ -0,0 +1,93 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.Graph; + +namespace Microsoft.Identity.Web +{ + /// + /// Extensions methods on a MicrososoftAppCallingWebApiAuthenticationBuilder builder + /// to add support to call Microsoft Graph. + /// + public static class MicrosoftGraphServiceExtensions + { + /// + /// Add support to calls Microsoft graph. From a named option and a configuration section. + /// + /// Builder. + /// Configuraiton section. + /// The builder to chain. + public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddMicrosoftGraphServiceClient( + this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, + IConfigurationSection configurationSection) + { + return builder.AddMicrosoftGraphServiceClient( + options => configurationSection.Bind(options)); + } + + /// + /// Add support to calls Microsoft graph. From a base graph Url and a default scope. + /// + /// Builder. + /// Named instance of option. + /// Configuraiton section. + /// The builder to chain. + public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddMicrosoftGraphServiceClient( + this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, + string graphBaseUrl = "https://graph.microsoft.com/v1.0", + string defaultScopes = "user.read") + { + return builder.AddMicrosoftGraphServiceClient( + options => + { + options.BaseUrl = graphBaseUrl; + options.Scopes = defaultScopes; + }); + } + + /// + /// Add support to calls Microsoft graph. From a named options and a configuraiton method. + /// + /// Builder. + /// Method to configure the options. + /// The builder to chain. + public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddMicrosoftGraphServiceClient( + this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, + Action configureMicrosoftGraphOptions) + { + if (builder == null) + { + throw new ArgumentNullException(nameof(builder)); + } + + // https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests + builder.Services.AddOptions().Configure(configureMicrosoftGraphOptions); + builder.Services.AddTokenAcquisition(true); + + builder.Services.AddSingleton(serviceProvider => + { + var tokenAquisitionService = serviceProvider.GetRequiredService(); + var options = serviceProvider.GetRequiredService>(); + + var microsoftGraphOptions = options.Value; + if (microsoftGraphOptions.Scopes == null) + { + throw new ArgumentException("CalledApiScopes should not be null."); + } + + string graphBaseUrl = microsoftGraphOptions.BaseUrl; + string[] initialScopes = microsoftGraphOptions.Scopes.Split(' '); + + GraphServiceClient client = string.IsNullOrWhiteSpace(graphBaseUrl) ? + new GraphServiceClient(new TokenAcquisitionCredentialProvider(tokenAquisitionService, initialScopes)) : + new GraphServiceClient(graphBaseUrl, new TokenAcquisitionCredentialProvider(tokenAquisitionService, initialScopes)); + return client; + }); + return builder; + } + } +} diff --git a/tests/BlazorServerCallsGraph/Services/TokenAcquisitionCredentialProvider.cs b/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs similarity index 54% rename from tests/BlazorServerCallsGraph/Services/TokenAcquisitionCredentialProvider.cs rename to src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs index d34bc65ac..73a8681d0 100644 --- a/tests/BlazorServerCallsGraph/Services/TokenAcquisitionCredentialProvider.cs +++ b/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs @@ -1,14 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -using Microsoft.Graph; -using Microsoft.Identity.Web; using System.Collections.Generic; using System.Net.Http; using System.Threading.Tasks; +using Microsoft.Graph; -namespace blazor +namespace Microsoft.Identity.Web { + /// + /// Authentication provider based on MSAL.NET. + /// internal class TokenAcquisitionCredentialProvider : IAuthenticationProvider { public TokenAcquisitionCredentialProvider(ITokenAcquisition tokenAcquisition, IEnumerable initialScopes) @@ -17,13 +19,19 @@ public TokenAcquisitionCredentialProvider(ITokenAcquisition tokenAcquisition, IE _initialScopes = initialScopes; } - ITokenAcquisition _tokenAcquisition; - IEnumerable _initialScopes; + private ITokenAcquisition _tokenAcquisition; + private IEnumerable _initialScopes; + /// + /// Adds a bearer header to an HttpRequestMessage. + /// + /// HttpRequest message to authenticate. + /// A Task (as this is an async method). public async Task AuthenticateRequestAsync(HttpRequestMessage request) { - request.Headers.Add("Authorization", - $"Bearer {await _tokenAcquisition.GetAccessTokenForUserAsync(_initialScopes)}"); + request.Headers.Add( + "Authorization", + $"Bearer {await _tokenAcquisition.GetAccessTokenForUserAsync(_initialScopes).ConfigureAwait(false)}"); } } } diff --git a/tests/B2CWebAppCallsWebApi/Client/TodoListClient.csproj b/tests/B2CWebAppCallsWebApi/Client/TodoListClient.csproj index be2bf0cdb..58fd87996 100644 --- a/tests/B2CWebAppCallsWebApi/Client/TodoListClient.csproj +++ b/tests/B2CWebAppCallsWebApi/Client/TodoListClient.csproj @@ -23,7 +23,6 @@ - diff --git a/tests/BlazorServerCallsGraph/Services/MicrosoftGraphServiceExtensions.cs b/tests/BlazorServerCallsGraph/Services/MicrosoftGraphServiceExtensions.cs deleted file mode 100644 index ee0233a9b..000000000 --- a/tests/BlazorServerCallsGraph/Services/MicrosoftGraphServiceExtensions.cs +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Collections.Generic; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Graph; -using Microsoft.Identity.Web; - -namespace blazor -{ - public static class MicrosoftGraphServiceExtensions - { - /// - /// Adds the Microsoft Graph client as a singleton. - /// - /// Service collection. - /// Initial scopes. - /// Base URL for Microsoft graph. This can be - /// changed for instance for applications running in national clouds - public static IServiceCollection AddMicrosoftGraph(this IServiceCollection services, - IEnumerable initialScopes, - string graphBaseUrl = "https://graph.microsoft.com/v1.0") - { - services.AddTokenAcquisition(true); - services.AddSingleton(serviceProvider => - { - var tokenAquisitionService = serviceProvider.GetService(); - GraphServiceClient client = string.IsNullOrWhiteSpace(graphBaseUrl) ? - new GraphServiceClient(new TokenAcquisitionCredentialProvider(tokenAquisitionService, initialScopes)) : - new GraphServiceClient(graphBaseUrl, new TokenAcquisitionCredentialProvider(tokenAquisitionService, initialScopes)); - return client; - }); - return services; - } - } -} diff --git a/tests/BlazorServerCallsGraph/Startup.cs b/tests/BlazorServerCallsGraph/Startup.cs index 9e4db9853..70772ff4e 100644 --- a/tests/BlazorServerCallsGraph/Startup.cs +++ b/tests/BlazorServerCallsGraph/Startup.cs @@ -26,15 +26,13 @@ public Startup(IConfiguration configuration) // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940 public void ConfigureServices(IServiceCollection services) { - string[] scopes = Configuration.GetValue("CalledApi:CalledApiScopes")?.Split(' '); services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") - .EnableTokenAcquisitionToCallDownstreamApi(scopes) + .EnableTokenAcquisitionToCallDownstreamApi() + .AddMicrosoftGraphServiceClient(Configuration.GetSection("GraphBeta")) .AddInMemoryTokenCaches(); services.AddDownstreamWebApiService(Configuration); - services.AddMicrosoftGraph(scopes, - Configuration.GetValue("CalledApi:CalledApiUrl")); services.AddControllersWithViews() .AddMicrosoftIdentityUI(); diff --git a/tests/BlazorServerCallsGraph/appsettings.json b/tests/BlazorServerCallsGraph/appsettings.json index b5704df74..ea0cda6c5 100644 --- a/tests/BlazorServerCallsGraph/appsettings.json +++ b/tests/BlazorServerCallsGraph/appsettings.json @@ -10,6 +10,10 @@ // To call an API "ClientSecret": "secret-goes-here" }, + "GraphBeta": { + "BaseUrl": "https://graph.microsoft.com/beta", + "Scopes": "user.read" + }, "CalledApi": { /* 'CalledApiScopes' contains space separated scopes of the Web API you want to call. This can be: diff --git a/tests/BlazorServerCallsGraph/blazor.csproj b/tests/BlazorServerCallsGraph/blazor.csproj index 64711ac92..6f39697f6 100644 --- a/tests/BlazorServerCallsGraph/blazor.csproj +++ b/tests/BlazorServerCallsGraph/blazor.csproj @@ -4,7 +4,6 @@ 66e5c3c7-f757-4032-bfcf-68bd81948618 - diff --git a/tests/WebAppCallsMicrosoftGraph/MicrosoftGraphServiceExtensions.cs b/tests/WebAppCallsMicrosoftGraph/MicrosoftGraphServiceExtensions.cs deleted file mode 100644 index f8591dd17..000000000 --- a/tests/WebAppCallsMicrosoftGraph/MicrosoftGraphServiceExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Collections.Generic; -using System.Linq; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Graph; -using Microsoft.Identity.Web; - -namespace WebAppCallsMicrosoftGraph -{ - public static class MicrosoftGraphServiceExtensions - { - /// - /// Adds the Microsoft Graph client as a singleton. - /// - /// Service collection. - /// Configuration for Microsoft Graph. - /// Initial scopes. - /// Base URL for Microsoft graph. This can be - /// changed for instance for applications running in national clouds - public static void AddMicrosoftGraph(this IServiceCollection services, - IConfiguration configuration, - IEnumerable initialScopes, - string graphBaseUrlKey = "MicrosoftGraphBaseUrl") - { - // Graph base URL - string graphBaseUrl = configuration.GetValue(graphBaseUrlKey); - - services.AddTokenAcquisition(true); - services.AddSingleton(serviceProvider => - { - var tokenAquisitionService = serviceProvider.GetService(); - GraphServiceClient client = string.IsNullOrWhiteSpace(graphBaseUrl) ? - new GraphServiceClient(new TokenAcquisitionCredentialProvider(tokenAquisitionService, initialScopes)) : - new GraphServiceClient(graphBaseUrl, new TokenAcquisitionCredentialProvider(tokenAquisitionService, initialScopes)); - return client; - }); - } - } -} diff --git a/tests/WebAppCallsMicrosoftGraph/Startup.cs b/tests/WebAppCallsMicrosoftGraph/Startup.cs index dc09bff53..ec5d23b9d 100644 --- a/tests/WebAppCallsMicrosoftGraph/Startup.cs +++ b/tests/WebAppCallsMicrosoftGraph/Startup.cs @@ -30,7 +30,8 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd")) .EnableTokenAcquisitionToCallDownstreamApi() - .AddInMemoryTokenCaches(); // Add a delegate overload. Should return the parent builder + .AddMicrosoftGraphServiceClient(Configuration.GetSection("GraphBeta")) + .AddInMemoryTokenCaches(); /* * services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) @@ -63,7 +64,6 @@ public void ConfigureServices(IServiceCollection services) ) .AddInMemoryTokenCaches(); */ - services.AddMicrosoftGraph(Configuration, new string[] { "user.read" }); services.AddRazorPages().AddMvcOptions(options => { diff --git a/tests/WebAppCallsMicrosoftGraph/TokenAcquisitionCredentialProvider.cs b/tests/WebAppCallsMicrosoftGraph/TokenAcquisitionCredentialProvider.cs deleted file mode 100644 index 87c333983..000000000 --- a/tests/WebAppCallsMicrosoftGraph/TokenAcquisitionCredentialProvider.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using Microsoft.Graph; -using Microsoft.Identity.Web; -using System.Collections; -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; - -namespace WebAppCallsMicrosoftGraph -{ - internal class TokenAcquisitionCredentialProvider : IAuthenticationProvider - { - public TokenAcquisitionCredentialProvider(ITokenAcquisition tokenAcquisition, IEnumerable initialScopes) - { - _tokenAcquisition = tokenAcquisition; - _initialScopes = initialScopes; - } - - ITokenAcquisition _tokenAcquisition; - IEnumerable _initialScopes; - - public async Task AuthenticateRequestAsync(HttpRequestMessage request) - { - request.Headers.Add("Authorization", - $"Bearer {await _tokenAcquisition.GetAccessTokenForUserAsync(_initialScopes)}"); - } - } -} diff --git a/tests/WebAppCallsMicrosoftGraph/WebAppCallsMicrosoftGraph.csproj b/tests/WebAppCallsMicrosoftGraph/WebAppCallsMicrosoftGraph.csproj index d71ade55d..7cad3f275 100644 --- a/tests/WebAppCallsMicrosoftGraph/WebAppCallsMicrosoftGraph.csproj +++ b/tests/WebAppCallsMicrosoftGraph/WebAppCallsMicrosoftGraph.csproj @@ -3,9 +3,6 @@ netcoreapp3.1; net5.0 aspnet-WebApp_OpenIDConnect_DotNet-81EA87AD-E64D-4755-A1CC-5EA47F49B5D8 - - - diff --git a/tests/WebAppCallsMicrosoftGraph/appsettings.json b/tests/WebAppCallsMicrosoftGraph/appsettings.json index f0e0b5b9d..2a1f0a9fb 100644 --- a/tests/WebAppCallsMicrosoftGraph/appsettings.json +++ b/tests/WebAppCallsMicrosoftGraph/appsettings.json @@ -7,7 +7,11 @@ "ClientSecret": "[Copy the client secret added to the app from the Azure portal]", "CallbackPath": "/signin-oidc" }, - "MicrosoftGraphBaseUrl": "https://graph.microsoft.com/beta", + + "GraphBeta": { + "BaseUrl": "https://graph.microsoft.com/beta", + "Scopes": "user.read" + }, "Logging": { "LogLevel": { diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/TodoListClient.csproj b/tests/WebAppCallsWebApiCallsGraph/Client/TodoListClient.csproj index e429fcaab..a5d48f1dd 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/TodoListClient.csproj +++ b/tests/WebAppCallsWebApiCallsGraph/Client/TodoListClient.csproj @@ -23,7 +23,6 @@ - diff --git a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Controllers/TodoListController.cs b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Controllers/TodoListController.cs index feb0b959e..fb588d91c 100644 --- a/tests/WebAppCallsWebApiCallsGraph/TodoListService/Controllers/TodoListController.cs +++ b/tests/WebAppCallsWebApiCallsGraph/TodoListService/Controllers/TodoListController.cs @@ -76,7 +76,7 @@ public IActionResult Post([FromBody] Todo todo) { HttpContext.VerifyUserHasAnyAcceptedScope(scopeRequiredByApi); int id = TodoStore.Values.OrderByDescending(x => x.Id).FirstOrDefault().Id + 1; - Todo todonew = new Todo() { Id = id, Owner = HttpContext.User.Identity.Name, Title = todo.Title }; + Todo todonew = new Todo() { Id = id, Owner = User.GetDisplayName(), Title = todo.Title }; TodoStore.Add(id, todonew); return Ok(todo); From 789fd51c9665ca2109e6b2d616402e2c791a41e7 Mon Sep 17 00:00:00 2001 From: jennyf19 Date: Thu, 13 Aug 2020 00:36:11 -0700 Subject: [PATCH 23/28] fix PR feedback for xml comments and constants (#442) * fix PR feedback for xml comments and constants * fix spelling + add more const --- .../Constants/Constants.cs | 7 ++++++- .../Constants/IDWebErrorMessage.cs | 1 + .../MicrosoftGraphServiceExtensions.cs | 18 +++++++++--------- .../TokenAcquisitionCredentialProvider.cs | 9 +++++++-- 4 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/Microsoft.Identity.Web/Constants/Constants.cs b/src/Microsoft.Identity.Web/Constants/Constants.cs index e417617ad..377475bb6 100644 --- a/src/Microsoft.Identity.Web/Constants/Constants.cs +++ b/src/Microsoft.Identity.Web/Constants/Constants.cs @@ -58,8 +58,13 @@ internal static class Constants public const string Bearer = "Bearer"; public const string LoginHint = "loginHint"; public const string DomainHint = "domainHint"; + public const string Authorization = "Authorization"; - // Blazor challenge uri + // Blazor challenge URI public const string BlazorChallengeUri = "MicrosoftIdentity/Account/Challenge?redirectUri="; + + // Microsoft Graph + public const string UserReadScope = "user.read"; + public const string GraphBaseUrlV1 = "https://graph.microsoft.com/v1.0"; } } diff --git a/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs b/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs index 41355123c..5c6eb766f 100644 --- a/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs +++ b/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs @@ -31,6 +31,7 @@ internal static class IDWebErrorMessage public const string UnauthenticatedUser = "IDW10204:The user is unauthenticated. The HttpContext does not contain any claims. "; public const string BlazorServerBaseUriNotSet = "IDW10205: Using Blazor server but the base URI was not properly set. "; public const string BlazorServerUserNotSet = "IDW10206: Using Blazor server but the user was not properly set. "; + public const string CalledApiScopesAreNull = "IDW10207: The CalledApiScopes cannot be null. "; // Token Validation IDW10300 = "IDW10300:" public const string IssuerMetadataUrlIsRequired = "IDW10301: Azure AD Issuer metadata address URL is required. "; diff --git a/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphServiceExtensions.cs b/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphServiceExtensions.cs index af08ebb5c..404c98da4 100644 --- a/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphServiceExtensions.cs +++ b/src/Microsoft.Identity.Web/MicrosoftGraph/MicrosoftGraphServiceExtensions.cs @@ -10,16 +10,16 @@ namespace Microsoft.Identity.Web { /// - /// Extensions methods on a MicrososoftAppCallingWebApiAuthenticationBuilder builder + /// Extensions methods on a MicrosoftIdentityAppCallingWebApiAuthenticationBuilder builder /// to add support to call Microsoft Graph. /// public static class MicrosoftGraphServiceExtensions { /// - /// Add support to calls Microsoft graph. From a named option and a configuration section. + /// Add support to call Microsoft Graph. From a named option and a configuration section. /// /// Builder. - /// Configuraiton section. + /// Configuration section. /// The builder to chain. public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddMicrosoftGraphServiceClient( this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, @@ -30,16 +30,16 @@ public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddMicrosoftG } /// - /// Add support to calls Microsoft graph. From a base graph Url and a default scope. + /// Add support to call Microsoft Graph. From a base Graph URL and a default scope. /// /// Builder. /// Named instance of option. - /// Configuraiton section. + /// Configuration section. /// The builder to chain. public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddMicrosoftGraphServiceClient( this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, - string graphBaseUrl = "https://graph.microsoft.com/v1.0", - string defaultScopes = "user.read") + string graphBaseUrl = Constants.GraphBaseUrlV1, + string defaultScopes = Constants.UserReadScope) { return builder.AddMicrosoftGraphServiceClient( options => @@ -50,7 +50,7 @@ public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddMicrosoftG } /// - /// Add support to calls Microsoft graph. From a named options and a configuraiton method. + /// Add support to call Microsoft Graph. From a named options and a configuration method. /// /// Builder. /// Method to configure the options. @@ -76,7 +76,7 @@ public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddMicrosoftG var microsoftGraphOptions = options.Value; if (microsoftGraphOptions.Scopes == null) { - throw new ArgumentException("CalledApiScopes should not be null."); + throw new ArgumentException(IDWebErrorMessage.CalledApiScopesAreNull); } string graphBaseUrl = microsoftGraphOptions.BaseUrl; diff --git a/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs b/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs index 73a8681d0..59e5594bd 100644 --- a/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs +++ b/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. using System.Collections.Generic; +using System.Globalization; using System.Net.Http; using System.Threading.Tasks; using Microsoft.Graph; @@ -30,8 +31,12 @@ public TokenAcquisitionCredentialProvider(ITokenAcquisition tokenAcquisition, IE public async Task AuthenticateRequestAsync(HttpRequestMessage request) { request.Headers.Add( - "Authorization", - $"Bearer {await _tokenAcquisition.GetAccessTokenForUserAsync(_initialScopes).ConfigureAwait(false)}"); + Constants.Authorization, + string.Format( + CultureInfo.InvariantCulture, + "{0}{1}", + Constants.Bearer, + await _tokenAcquisition.GetAccessTokenForUserAsync(_initialScopes).ConfigureAwait(false))); } } } From 0aed39a1b38d2bab4ef29fa5e430837265890704 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Thu, 13 Aug 2020 16:06:11 +0200 Subject: [PATCH 24/28] Addressing PR feedback --- .../MicrosoftGraph/TokenAcquisitionCredentialProvider.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs b/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs index 73a8681d0..7f477b97a 100644 --- a/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs +++ b/src/Microsoft.Identity.Web/MicrosoftGraph/TokenAcquisitionCredentialProvider.cs @@ -9,7 +9,7 @@ namespace Microsoft.Identity.Web { /// - /// Authentication provider based on MSAL.NET. + /// Authentication provider based on ITokenAcquisition. /// internal class TokenAcquisitionCredentialProvider : IAuthenticationProvider { From e1edd34030da289b83e459412c2d4fbbfec83bdb Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Thu, 13 Aug 2020 18:41:11 +0200 Subject: [PATCH 25/28] Branch with less changes, just for the DownstreamApiService --- .../DownstreamApiOptions.cs | 86 +++++++++ .../DownstreamApiSupport/DownstreamWebApi.cs | 172 ++++++++++++++++++ .../DownstreamWebApiExtensions.cs | 65 +++++++ .../DownstreamApiSupport/IDownstreamWebApi.cs | 108 +++++++++++ .../GlobalSuppressions.cs | 11 ++ .../Microsoft.Identity.Web.xml | 165 ++++++++++++++++- .../Pages/CallWebApi.razor | 14 +- .../Services/DownstreamWebApi.cs | 75 -------- tests/BlazorServerCallsGraph/Startup.cs | 2 +- tests/BlazorServerCallsGraph/appsettings.json | 22 +-- .../Client/Controllers/TodoListController.cs | 8 +- .../Client/Services/TodoListService.cs | 158 +++++----------- .../Client/Startup.cs | 6 +- .../Client/appsettings.json | 4 +- 14 files changed, 681 insertions(+), 215 deletions(-) create mode 100644 src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamApiOptions.cs create mode 100644 src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApi.cs create mode 100644 src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApiExtensions.cs create mode 100644 src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs create mode 100644 src/Microsoft.Identity.Web/GlobalSuppressions.cs delete mode 100644 tests/BlazorServerCallsGraph/Services/DownstreamWebApi.cs diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamApiOptions.cs b/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamApiOptions.cs new file mode 100644 index 000000000..313966aee --- /dev/null +++ b/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamApiOptions.cs @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Net.Http; + +namespace Microsoft.Identity.Web +{ + /// + /// Options passed-in to call web APIs. To call Microsoft Graph, see rather + /// . + /// + public class DownstreamApiOptions + { + /// + /// Base URL for the called Web API. For instance "https://graph.microsoft.com/beta/".. + /// + public string BaseUrl { get; set; } = "https://graph.microsoft.com/v1.0"; + + /// + /// Path relative to the (for instance "me"). + /// + public string RelativePath { get; set; } = string.Empty; + + /// + /// Space separated scopes required to call the Web API. + /// For instance "user.read mail.read". + /// + public string? Scopes { get; set; } = null; + + /// + /// [Optional] tenant ID. This is used for specific scenarios where + /// the application needs to call a Web API on behalf of a user in several tenants. + /// It would mostly be used from code, not from the configuration. + /// + public string? Tenant { get; set; } = null; + + /// + /// [Optional]. User flow (in the case of a B2C Web API). If not + /// specified, the B2C web API will be called with the default user flow from + /// . + /// + public string? UserFlow { get; set; } = null; + + /// + /// Http method used to call this API (by default Get). + /// + public HttpMethod HttpMethod { get; set; } = HttpMethod.Get; + + /// + /// Clone the options (to be able to override them). + /// + /// A clone of the options. + public DownstreamApiOptions Clone() + { + return new DownstreamApiOptions + { + BaseUrl = BaseUrl, + RelativePath = RelativePath, + Scopes = Scopes, + Tenant = Tenant, + UserFlow = UserFlow, + HttpMethod = HttpMethod, + }; + } + + /// + /// Return the Api URL. + /// + /// URL of the API. +#pragma warning disable CA1055 // Uri return values should not be strings + public string GetApiUrl() +#pragma warning restore CA1055 // Uri return values should not be strings + { + return BaseUrl?.TrimEnd('/') + $"/{RelativePath}"; + } + + /// + /// Returns the scopes. + /// + /// Scopes. + public string[] GetScopes() + { + return string.IsNullOrWhiteSpace(Scopes) ? new string[0] : Scopes.Split(' '); + } + } +} diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApi.cs b/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApi.cs new file mode 100644 index 000000000..46c52a1c6 --- /dev/null +++ b/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApi.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Net; +using System.Net.Http; +using System.Security.Claims; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using Microsoft.Graph; +using Microsoft.Identity.Web; + +namespace Microsoft.Identity.Web +{ + /// + /// Implementation for the downstream API. + /// + public class DownstreamWebApi : IDownstreamWebApi + { + private readonly ITokenAcquisition _tokenAcquisition; + private readonly HttpClient _httpClient; + private readonly IOptionsMonitor _namedOptions; + private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true, + }; + + /// + /// Constructor. + /// + /// Token acquisition service. + /// Named options provider. + /// Http client. + public DownstreamWebApi( + ITokenAcquisition tokenAcquisition, + IOptionsMonitor namedOptions, + HttpClient httpClient) + { + _tokenAcquisition = tokenAcquisition; + _namedOptions = namedOptions; + _httpClient = httpClient; + } + + /// + public async Task CallWebApiForUserAsync( + string optionsInstanceName, + Action? calledApiOptionsOverride, + ClaimsPrincipal? user, + StringContent? requestContent) + { + DownstreamApiOptions effectiveOptions = MergeOptions(optionsInstanceName, calledApiOptionsOverride); + + // verify scopes is not null + if (string.IsNullOrEmpty(effectiveOptions.Scopes)) + { + throw new ArgumentException("Scopes need to be passed-in either by configuration or by the delegate overring it."); + } + + string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(effectiveOptions.GetScopes(), effectiveOptions.Tenant) + .ConfigureAwait(false); + + HttpResponseMessage response; + using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(effectiveOptions.HttpMethod, effectiveOptions.GetApiUrl())) + { + if (requestContent != null) + { + httpRequestMessage.Content = requestContent; + } + + httpRequestMessage.Headers.Add("Authorization", $"bearer {accessToken}"); + response = await _httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false); + } + + return response; + } + + /// + /// Merge the options from configuration and override from caller. + /// + /// Named configuration. + /// Delegate to override the configuration. + internal /* for tests */ DownstreamApiOptions MergeOptions( + string optionsInstanceName, + Action? calledApiOptionsOverride) + { + // Gets the options from configuration (or default value) + DownstreamApiOptions options; + if (optionsInstanceName != null) + { + options = _namedOptions.Get(optionsInstanceName); + } + else + { + options = _namedOptions.CurrentValue; + } + + // Give a chance to the called to override defaults for this call + DownstreamApiOptions clonedOptions = options.Clone(); + calledApiOptionsOverride?.Invoke(clonedOptions); + return clonedOptions; + } + + /// + public async Task CallWebApiForUserAsync( + string optionsInstanceName, + TInput input, + Action? downstreamApiOptionsOverride = null, + ClaimsPrincipal? user = null) + where TOutput : class + { + StringContent? jsoncontent; + if (input != null) + { + var jsonRequest = JsonSerializer.Serialize(input); + jsoncontent = new StringContent(jsonRequest, Encoding.UTF8, "application/json"); +// case of patch? jsoncontent = new StringContent(jsonRequest, Encoding.UTF8, "application/json-patch+json"); + } + else + { + jsoncontent = null; + } + + HttpResponseMessage response = await CallWebApiForUserAsync( + optionsInstanceName, + downstreamApiOptionsOverride, + user, + jsoncontent).ConfigureAwait(false); + + if (response.StatusCode == HttpStatusCode.OK) + { + string content = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + TOutput? output = JsonSerializer.Deserialize(content, _jsonOptions); + return output; + } + else + { + string error = await response.Content.ReadAsStringAsync().ConfigureAwait(false); + throw new HttpRequestException($"Invalid status code in the HttpResponseMessage: {response.StatusCode}: {error}"); + } + } + + /// + public async Task CallWebApiForAppAsync( + string optionsInstanceName, + Action? downstreamApiOptionsOverride = null, + StringContent? requestContent = null) + { + DownstreamApiOptions effectiveOptions = MergeOptions(optionsInstanceName, downstreamApiOptionsOverride); + + if (effectiveOptions.Scopes == null) + { + throw new ArgumentException("Scopes need to be passed-in either by configuration or by the delegate overring it."); + } + + string accessToken = await _tokenAcquisition.GetAccessTokenForAppAsync(effectiveOptions.Scopes, effectiveOptions.Tenant) + .ConfigureAwait(false); + + HttpResponseMessage response; + using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(effectiveOptions.HttpMethod, effectiveOptions.GetApiUrl())) + { + httpRequestMessage.Headers.Add("Authorization", $"bearer {accessToken}"); + response = await _httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false); + } + + return response; + } + } +} diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApiExtensions.cs b/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApiExtensions.cs new file mode 100644 index 000000000..d6ec11895 --- /dev/null +++ b/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApiExtensions.cs @@ -0,0 +1,65 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Microsoft.Identity.Web +{ + /// + /// Extension methods to support downstream api services. + /// + public static class DownstreamApiServiceExtensions + { + /// + /// Adds a named downstream API service related to a specific configuration section. + /// + /// Builder. + /// Name of the configuration for the service. + /// This is the name which will be used when calling the service from controller/pages. + /// Configuration. + /// The builder for chaining. + public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddDownstreamApiService( + this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, + string optionsInstanceName, + IConfiguration configuration) + { + if (builder is null) + { + throw new ArgumentNullException(nameof(builder)); + } + + builder.Services.Configure(optionsInstanceName, configuration); + builder.Services.AddHttpClient(); + return builder; + } + + /// + /// Adds a named downstream API service initialized with delegates. + /// + /// Builder. + /// Name of the configuration for the service. + /// This is the name which will be used when calling the service from controller/pages. + /// Action to configure the options. + /// The builder for chaining. + public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddDownstreamApiService( + this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, + string optionsInstanceName, + Action configureOptions) + { + if (builder is null) + { + throw new ArgumentNullException(nameof(builder)); + } + + builder.Services.Configure(optionsInstanceName, configureOptions); + + // https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests + builder.Services.AddHttpClient(); + builder.Services.Configure(optionsInstanceName, configureOptions); + return builder; + } + } +} diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs b/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs new file mode 100644 index 000000000..caa3035e0 --- /dev/null +++ b/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Net.Http; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Microsoft.Identity.Web +{ + /// + /// Interface used to call a downstream web API, for instance from controllers. + /// + public interface IDownstreamWebApi + { + /// + /// Calls the Web API for the user, based on a description of the + /// web API in the configuration. + /// + /// Name of the options instance describing the API. There can + /// be several configuration namedsections mapped to a , + /// each for one API. You can pass-in null, but in that case + /// need to be set. + /// Overides the options proposed in the configuration described + /// by . + /// [Optional] claims representing a user. This is useful in scenarios like Blazor + /// or Azure Signal R where the HttpContext is not available. In the other scenarios, the library + /// will find the user itself. + /// Http content in the case where is + /// , , . + /// An that the application will process. + public Task CallWebApiForUserAsync( + string optionsInstanceName, + Action? calledApiOptionsOverride = null, + ClaimsPrincipal? user = null, + StringContent? content = null); + + /// + /// Calls a Web API consuming JSon with some data and returns data. + /// + /// Input type. + /// Output type. + /// Name of the options instance describing the API. There can + /// be several configuration namedsections mapped to a , + /// each for one API. You can pass-in null, but in that case + /// need to be set. + /// Input parameter to the API. + /// Overides the options proposed in the configuration described + /// by . + /// [Optional] claims representing a user. This is useful in scenarios like Blazor + /// or Azure Signal R where the HttpContext is not available. In the other scenarios, the library + /// will find the user itself. + /// The value returned by the API. + /// + /// A list method that returns an IEnumerable<Todo>> + /// + /// public async Task<IEnumerable<Todo>> GetAsync() + /// { + /// return await _downstreamWebApi.CallWebApiForUserAsync<object, IEnumerable<Todo>>( + /// ServiceName, + /// null, + /// options => + /// { + /// options.RelativePath = $"api/todolist"; + /// }); + /// } + /// + /// + /// Example of editing. + /// + /// public async Task<Todo> EditAsync(Todo todo) + /// { + /// return await _downstreamWebApi.CallWebApiForUserAsync<Todo, Todo>( + /// ServiceName, + /// todo, + /// options => + /// { + /// options.HttpMethod = HttpMethod.Patch; + /// options.RelativePath = $"api/todolist/{todo.Id}"; + /// }); + /// } + /// + /// + public Task CallWebApiForUserAsync( + string optionsInstanceName, + TInput input, + Action? downstreamApiOptionsOverride = null, + ClaimsPrincipal? user = null) + where TOutput : class; + + /// + /// Calls the Web API for the app, with the required scopes. + /// + /// Name of the options instance describing the API. There can + /// be several configuration namedsections mapped to a , + /// each for one API. You can pass-in null, but in that case + /// need to be set. + /// Overides the options proposed in the configuration described + /// by . + /// Http content in the case where is + /// , , . + /// An that the application will process. + public Task CallWebApiForAppAsync( + string optionsInstanceName, + Action? downstreamApiOptionsOverride = null, + StringContent? content = null); + } +} diff --git a/src/Microsoft.Identity.Web/GlobalSuppressions.cs b/src/Microsoft.Identity.Web/GlobalSuppressions.cs new file mode 100644 index 000000000..be01584b6 --- /dev/null +++ b/src/Microsoft.Identity.Web/GlobalSuppressions.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Design", "CA1055:Uri return values should not be strings", Justification = "We want a string.", Scope = "member", Target = "~M:Microsoft.Identity.Web.CalledApiOptions.GetApiUrl~System.String")] diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index ab6114de2..86b63e227 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -530,6 +530,157 @@ True, if the user agent does not allow "SameSite=None" cookie; otherwise, false. + + + Options passed-in to call web APIs. To call Microsoft Graph, see rather + . + + + + + Base URL for the called Web API. For instance "https://graph.microsoft.com/beta/".. + + + + + Path relative to the (for instance "me"). + + + + + Space separated scopes required to call the Web API. + For instance "user.read mail.read". + + + + + [Optional] tenant ID. This is used for specific scenarios where + the application needs to call a Web API on behalf of a user in several tenants. + It would mostly be used from code, not from the configuration. + + + + + [Optional]. User flow (in the case of a B2C Web API). If not + specified, the B2C web API will be called with the default user flow from + . + + + + + Http method used to call this API (by default Get). + + + + + Clone the options (to be able to override them). + + A clone of the options. + + + + Return the Api URL. + + URL of the API. + + + + Returns the scopes. + + Scopes. + + + + Implementation for the downstream API. + + + + + Constructor. + + Token acquisition service. + Named options provider. + Http client. + + + + + + + Merge the options from configuration and override from caller. + + Named configuration. + Delegate to override the configuration. + + + + + + + + + + Extension methods to support downstream api services. + + + + + Adds a named downstream API service related to a specific configuration section. + + Builder. + Name of the configuration for the service. + This is the name which will be used when calling the service from controller/pages. + Configuration. + The builder for chaining. + + + + Adds a named downstream API service initialized with delegates. + + Builder. + Name of the configuration for the service. + This is the name which will be used when calling the service from controller/pages. + Action to configure the options. + The builder for chaining. + + + + Interface used to call a downstream web API, for instance from controllers. + + + + + Calls the Web API for the user, based on a description of the + web API in the configuration. + + Name of the options instance describing the API. There can + be several configuration namedsections mapped to a , + each for one API. You can pass-in null, but in that case + need to be set. + Overides the options proposed in the configuration described + by . + [Optional] claims representing a user. This is useful in scenarios like Blazor + or Azure Signal R where the HttpContext is not available. In the other scenarios, the library + will find the user itself. + Http content in the case where is + , , . + An that the application will process. + + + + + Calls the Web API for the app, with the required scopes. + + Name of the options instance describing the API. There can + be several configuration namedsections mapped to a , + each for one API. You can pass-in null, but in that case + need to be set. + Overides the options proposed in the configuration described + by . + Http content in the case where is + , , . + An that the application will process. + Extension methods. @@ -747,30 +898,30 @@ - Extensions methods on a MicrososoftAppCallingWebApiAuthenticationBuilder builder + Extensions methods on a MicrosoftIdentityAppCallingWebApiAuthenticationBuilder builder to add support to call Microsoft Graph. - Add support to calls Microsoft graph. From a named option and a configuration section. + Add support to call Microsoft Graph. From a named option and a configuration section. Builder. - Configuraiton section. + Configuration section. The builder to chain. - Add support to calls Microsoft graph. From a base graph Url and a default scope. + Add support to call Microsoft Graph. From a base Graph URL and a default scope. Builder. Named instance of option. - Configuraiton section. + Configuration section. The builder to chain. - Add support to calls Microsoft graph. From a named options and a configuraiton method. + Add support to call Microsoft Graph. From a named options and a configuration method. Builder. Method to configure the options. @@ -778,7 +929,7 @@ - Authentication provider based on MSAL.NET. + Authentication provider based on ITokenAcquisition. diff --git a/tests/BlazorServerCallsGraph/Pages/CallWebApi.razor b/tests/BlazorServerCallsGraph/Pages/CallWebApi.razor index 6b06cde64..27e7b6892 100644 --- a/tests/BlazorServerCallsGraph/Pages/CallWebApi.razor +++ b/tests/BlazorServerCallsGraph/Pages/CallWebApi.razor @@ -20,13 +20,25 @@ else } @code { + private HttpResponseMessage response; private string apiResult; protected override async Task OnInitializedAsync() { try { - apiResult = await downstreamAPI.CallWebApiAsync("me"); + response = await downstreamAPI.CallWebApiForUserAsync( + "CalledApi", + options => options.RelativePath = "me"); + + if (response.StatusCode == System.Net.HttpStatusCode.OK) + { + apiResult = await response.Content.ReadAsStringAsync(); + } + else + { + apiResult = "Failed to call the web API"; + } } catch (Exception ex) { diff --git a/tests/BlazorServerCallsGraph/Services/DownstreamWebApi.cs b/tests/BlazorServerCallsGraph/Services/DownstreamWebApi.cs deleted file mode 100644 index 26646081f..000000000 --- a/tests/BlazorServerCallsGraph/Services/DownstreamWebApi.cs +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Net; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Identity.Web; - -namespace blazor -{ - public interface IDownstreamWebApi - { - Task CallWebApiAsync(string relativeEndpoint = "", string[] requiredScopes = null); - } - - public static class DownstreamWebApiExtensions - { - public static void AddDownstreamWebApiService(this IServiceCollection services, IConfiguration configuration) - { - // https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests - services.AddHttpClient(); - } - } - - public class DownstreamWebApi : IDownstreamWebApi - { - private readonly ITokenAcquisition _tokenAcquisition; - - private readonly IConfiguration _configuration; - - private readonly HttpClient _httpClient; - - public DownstreamWebApi( - ITokenAcquisition tokenAcquisition, - IConfiguration configuration, - HttpClient httpClient) - { - _tokenAcquisition = tokenAcquisition; - _configuration = configuration; - _httpClient = httpClient; - } - - /// - /// Calls the Web API with the required scopes - /// - /// [Optional] Scopes required to call the Web API. If - /// not specified, uses scopes from the configuration - /// Endpoint relative to the CalledApiUrl configuration - /// A JSON string representing the result of calling the Web API - public async Task CallWebApiAsync(string relativeEndpoint = "", string[] requiredScopes = null) - { - string[] scopes = requiredScopes ?? _configuration["CalledApi:CalledApiScopes"]?.Split(' '); - string apiUrl = (_configuration["CalledApi:CalledApiUrl"] as string)?.TrimEnd('/') + $"/{relativeEndpoint}"; - - string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes); - HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Get, apiUrl); - httpRequestMessage.Headers.Add("Authorization", $"bearer {accessToken}"); - - string apiResult; - var response = await _httpClient.SendAsync(httpRequestMessage); - if (response.StatusCode == HttpStatusCode.OK) - { - apiResult = await response.Content.ReadAsStringAsync(); - } - else - { - apiResult = $"Error calling the API '{apiUrl}'"; - } - - return apiResult; - } - } -} diff --git a/tests/BlazorServerCallsGraph/Startup.cs b/tests/BlazorServerCallsGraph/Startup.cs index 70772ff4e..282162d04 100644 --- a/tests/BlazorServerCallsGraph/Startup.cs +++ b/tests/BlazorServerCallsGraph/Startup.cs @@ -30,9 +30,9 @@ public void ConfigureServices(IServiceCollection services) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") .EnableTokenAcquisitionToCallDownstreamApi() .AddMicrosoftGraphServiceClient(Configuration.GetSection("GraphBeta")) + .AddDownstreamApiService("CalledApi", Configuration.GetSection("CalledApi")) .AddInMemoryTokenCaches(); - services.AddDownstreamWebApiService(Configuration); services.AddControllersWithViews() .AddMicrosoftIdentityUI(); diff --git a/tests/BlazorServerCallsGraph/appsettings.json b/tests/BlazorServerCallsGraph/appsettings.json index ea0cda6c5..bb607fb60 100644 --- a/tests/BlazorServerCallsGraph/appsettings.json +++ b/tests/BlazorServerCallsGraph/appsettings.json @@ -22,15 +22,15 @@ 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/beta/" - }, - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*" + "Scopes": "user.read", + "BaseUrl": "https://graph.microsoft.com/v1.0/" + }, + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft": "Warning", + "Microsoft.Hosting.Lifetime": "Information" + } + }, + "AllowedHosts": "*" } diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Controllers/TodoListController.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Controllers/TodoListController.cs index 2c86cdc47..3f3fc0a36 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Controllers/TodoListController.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Controllers/TodoListController.cs @@ -14,13 +14,13 @@ public class TodoListController : Controller { private ITodoListService _todoListService; - public TodoListController(ITodoListService todoListService) + public TodoListController(IDownstreamWebApi downstreamWebApi) { - _todoListService = todoListService; + _todoListService = new Services.TodoListService(downstreamWebApi); } // GET: TodoList - [AuthorizeForScopes(ScopeKeySection = "TodoList:TodoListScope")] + [AuthorizeForScopes(ScopeKeySection = "TodoList:Scopes")] public async Task Index() { return View(await _todoListService.GetAsync()); @@ -92,4 +92,4 @@ public async Task Delete(int id, [Bind("Id,Title,Owner")] Todo tod return RedirectToAction("Index"); } } -} \ No newline at end of file +} diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Services/TodoListService.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Services/TodoListService.cs index 68008ddfd..80cb49801 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Services/TodoListService.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Services/TodoListService.cs @@ -2,14 +2,8 @@ // Licensed under the MIT License. using System.Collections.Generic; -using System.Diagnostics; -using System.Net; using System.Net.Http; -using System.Net.Http.Headers; -using System.Text; -using System.Text.Json; using System.Threading.Tasks; -using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Identity.Web; @@ -19,10 +13,14 @@ namespace TodoListClient.Services { public static class TodoListServiceExtensions { - public static void AddTodoListService(this IServiceCollection services, IConfiguration configuration) + public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddTodoListService( + this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, + IConfiguration configuration) { + builder.AddDownstreamApiService(TodoListService.ServiceName, configuration); // https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests - services.AddHttpClient(); + builder.Services.AddHttpClient(); + return builder; } } @@ -30,130 +28,70 @@ public static void AddTodoListService(this IServiceCollection services, IConfigu /// public class TodoListService : ITodoListService { - private readonly IHttpContextAccessor _contextAccessor; - private readonly HttpClient _httpClient; - private readonly string _TodoListScope = string.Empty; - private readonly string _TodoListBaseAddress = string.Empty; - private readonly ITokenAcquisition _tokenAcquisition; - private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions - { - PropertyNameCaseInsensitive = true - }; + private readonly IDownstreamWebApi _downstreamWebApi; + public const string ServiceName = "TodoList"; - public TodoListService(ITokenAcquisition tokenAcquisition, HttpClient httpClient, IConfiguration configuration, IHttpContextAccessor contextAccessor) + public TodoListService(IDownstreamWebApi downstreamWebApi) { - _httpClient = httpClient; - _tokenAcquisition = tokenAcquisition; - _contextAccessor = contextAccessor; - _TodoListScope = configuration["TodoList:TodoListScope"]; - _TodoListBaseAddress = configuration["TodoList:TodoListBaseAddress"]; + _downstreamWebApi = downstreamWebApi; } public async Task AddAsync(Todo todo) { - var httpRequestMessage = await PrepareAuthenticatedClient( - $"{ _TodoListBaseAddress}/api/todolist", - HttpMethod.Post); - - var jsonRequest = JsonSerializer.Serialize(todo); - var jsoncontent = new StringContent(jsonRequest, Encoding.UTF8, "application/json"); - httpRequestMessage.Content = jsoncontent; - - var response = await _httpClient.SendAsync(httpRequestMessage); - - if (response.StatusCode == HttpStatusCode.OK) - { - var content = await response.Content.ReadAsStringAsync(); - todo = JsonSerializer.Deserialize(content, _jsonOptions); - - return todo; - } - - throw new HttpRequestException($"Invalid status code in the HttpResponseMessage: {response.StatusCode}."); + return await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + todo, + options => + { + options.HttpMethod = HttpMethod.Post; + options.RelativePath = "api/todolist"; + }); } public async Task DeleteAsync(int id) { - var httpRequestMessage = await PrepareAuthenticatedClient( - $"{ _TodoListBaseAddress}/api/todolist/{id}", - HttpMethod.Delete); - - var response = await _httpClient.SendAsync(httpRequestMessage); - - if (response.StatusCode == HttpStatusCode.OK) - { - return; - } - - throw new HttpRequestException($"Invalid status code in the HttpResponseMessage: {response.StatusCode}."); + await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + options => + { + options.HttpMethod = HttpMethod.Delete; + options.RelativePath = $"api/todolist/{id}"; + }); } public async Task EditAsync(Todo todo) { - var httpRequestMessage = await PrepareAuthenticatedClient( - $"{ _TodoListBaseAddress}/api/todolist/{todo.Id}", - HttpMethod.Patch); - - var jsonRequest = JsonSerializer.Serialize(todo); - var jsoncontent = new StringContent(jsonRequest, Encoding.UTF8, "application/json-patch+json"); - - httpRequestMessage.Content = jsoncontent; - var response = await _httpClient.SendAsync(httpRequestMessage); - - if (response.StatusCode == HttpStatusCode.OK) - { - var content = await response.Content.ReadAsStringAsync(); - todo = JsonSerializer.Deserialize(content, _jsonOptions); - - return todo; - } - - throw new HttpRequestException($"Invalid status code in the HttpResponseMessage: {response.StatusCode}."); + return await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + todo, + options => + { + options.HttpMethod = HttpMethod.Patch; + options.RelativePath = $"api/todolist/{todo.Id}"; + }); } public async Task> GetAsync() { - var httpRequestMessage = await PrepareAuthenticatedClient( - $"{ _TodoListBaseAddress}/api/todolist", - HttpMethod.Get); - var response = await _httpClient.SendAsync(httpRequestMessage); - var content = await response.Content.ReadAsStringAsync(); - - if (response.StatusCode == HttpStatusCode.OK) - { - IEnumerable todolist = JsonSerializer.Deserialize>(content, _jsonOptions); - return todolist; - } - throw new HttpRequestException($"Invalid status code in the HttpResponseMessage: {response.StatusCode}. Cause: {content}"); + return await _downstreamWebApi.CallWebApiForUserAsync>( + ServiceName, + null, + options => + { + options.RelativePath = $"api/todolist"; + }); } public async Task GetAsync(int id) { - var httpRequestMessage = await PrepareAuthenticatedClient( - $"{ _TodoListBaseAddress}/api/todolist/{id}", - HttpMethod.Get); - var response = await _httpClient.SendAsync(httpRequestMessage); - if (response.StatusCode == HttpStatusCode.OK) - { - var content = await response.Content.ReadAsStringAsync(); - Todo todo = JsonSerializer.Deserialize(content, _jsonOptions); - - return todo; - } - - throw new HttpRequestException($"Invalid status code in the HttpResponseMessage: {response.StatusCode}."); - } - - private async Task PrepareAuthenticatedClient( - string url, - HttpMethod httpMethod) - { - var accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(new[] { _TodoListScope }); - Debug.WriteLine($"access token-{accessToken}"); - HttpRequestMessage httpRequestMessage = new HttpRequestMessage(httpMethod, url); - httpRequestMessage.Headers.Add("Authorization", $"bearer {accessToken}"); - httpRequestMessage.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); - return httpRequestMessage; + return await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + null, + options => + { + options.HttpMethod = HttpMethod.Get; + options.RelativePath = $"api/todolist/{id}"; + }); } } } diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs index 4bd54969d..c3bb3f3a7 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs @@ -45,10 +45,8 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") .EnableTokenAcquisitionToCallDownstreamApi() - .AddInMemoryTokenCaches(); - - // Add APIs - services.AddTodoListService(Configuration); + .AddTodoListService(Configuration.GetSection("TodoList")) + .AddInMemoryTokenCaches(); services.AddControllersWithViews(options => { diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/appsettings.json b/tests/WebAppCallsWebApiCallsGraph/Client/appsettings.json index 497e32707..81da6e45e 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/appsettings.json +++ b/tests/WebAppCallsWebApiCallsGraph/Client/appsettings.json @@ -24,8 +24,8 @@ - a scope corresponding to a V1 application (for instance /user_impersonation, where is the clientId of a V1 application, created in the https://portal.azure.com portal. */ - "TodoListScope": "api://a4c2469b-cf84-4145-8f5f-cb7bacf814bc/access_as_user", - "TodoListBaseAddress": "https://localhost:44351" + "Scopes": "api://a4c2469b-cf84-4145-8f5f-cb7bacf814bc/access_as_user", + "BaseUrl": "https://localhost:44351" }, "Logging": { From c1688f867d423f921992b21af160dad92fa85478 Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Thu, 13 Aug 2020 18:44:54 +0200 Subject: [PATCH 26/28] Update src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs --- .../DownstreamApiSupport/IDownstreamWebApi.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs b/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs index caa3035e0..88ff1a320 100644 --- a/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs +++ b/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs @@ -52,7 +52,7 @@ public Task CallWebApiForUserAsync( /// will find the user itself. /// The value returned by the API. /// - /// A list method that returns an IEnumerable<Todo>> + /// A list method that returns an IEnumerable<Todo>>. /// /// public async Task<IEnumerable<Todo>> GetAsync() /// { From 6c0c8801542423ee336d57d3a3dd4a1bff250d6e Mon Sep 17 00:00:00 2001 From: Jean-Marc Prieur Date: Thu, 13 Aug 2020 21:08:03 +0200 Subject: [PATCH 27/28] Fixes a XML comment --- .../DownstreamApiSupport/IDownstreamWebApi.cs | 2 +- .../Microsoft.Identity.Web.xml | 49 ++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs b/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs index caa3035e0..88ff1a320 100644 --- a/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs +++ b/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs @@ -52,7 +52,7 @@ public Task CallWebApiForUserAsync( /// will find the user itself. /// The value returned by the API. /// - /// A list method that returns an IEnumerable<Todo>> + /// A list method that returns an IEnumerable<Todo>>. /// /// public async Task<IEnumerable<Todo>> GetAsync() /// { diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index 86b63e227..fc2067132 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -666,7 +666,54 @@ , , . An that the application will process. - + + + Calls a Web API consuming JSon with some data and returns data. + + Input type. + Output type. + Name of the options instance describing the API. There can + be several configuration namedsections mapped to a , + each for one API. You can pass-in null, but in that case + need to be set. + Input parameter to the API. + Overides the options proposed in the configuration described + by . + [Optional] claims representing a user. This is useful in scenarios like Blazor + or Azure Signal R where the HttpContext is not available. In the other scenarios, the library + will find the user itself. + The value returned by the API. + + A list method that returns an IEnumerable<Todo>>. + + public async Task<IEnumerable<Todo>> GetAsync() + { + return await _downstreamWebApi.CallWebApiForUserAsync<object, IEnumerable<Todo>>( + ServiceName, + null, + options => + { + options.RelativePath = $"api/todolist"; + }); + } + + + Example of editing. + + public async Task<Todo> EditAsync(Todo todo) + { + return await _downstreamWebApi.CallWebApiForUserAsync<Todo, Todo>( + ServiceName, + todo, + options => + { + options.HttpMethod = HttpMethod.Patch; + options.RelativePath = $"api/todolist/{todo.Id}"; + }); + } + + + Calls the Web API for the app, with the required scopes. From 3989e4e74af86bbb4a29cc5dc4f36c4f5376deef Mon Sep 17 00:00:00 2001 From: jennyf19 Date: Thu, 13 Aug 2020 12:49:47 -0700 Subject: [PATCH 28/28] update sample to use downstream api & some spelling fixes (#449) Co-authored-by: Jean-Marc Prieur --- .../Constants/Constants.cs | 1 + .../Constants/IDWebErrorMessage.cs | 4 +- .../DownstreamApiSupport/IDownstreamWebApi.cs | 108 --------- .../DownstreamWebApi.cs | 88 +++++--- .../DownstreamWebApiExtensions.cs | 31 ++- .../DownstreamWebApiOptions.cs} | 24 +- .../IDownstreamWebApi.cs | 108 +++++++++ .../Microsoft.Identity.Web.xml | 212 +++++++++++++++++- tests/BlazorServerCallsGraph/Startup.cs | 2 +- .../Client/Controllers/TodoListController.cs | 75 ++++++- .../Client/Services/ITodoListService.cs | 22 -- .../Client/Services/TodoListService.cs | 97 -------- .../Client/Startup.cs | 3 +- 13 files changed, 463 insertions(+), 312 deletions(-) delete mode 100644 src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs rename src/Microsoft.Identity.Web/{DownstreamApiSupport => DownstreamWebApiSupport}/DownstreamWebApi.cs (59%) rename src/Microsoft.Identity.Web/{DownstreamApiSupport => DownstreamWebApiSupport}/DownstreamWebApiExtensions.cs (63%) rename src/Microsoft.Identity.Web/{DownstreamApiSupport/DownstreamApiOptions.cs => DownstreamWebApiSupport/DownstreamWebApiOptions.cs} (71%) create mode 100644 src/Microsoft.Identity.Web/DownstreamWebApiSupport/IDownstreamWebApi.cs delete mode 100644 tests/WebAppCallsWebApiCallsGraph/Client/Services/ITodoListService.cs delete mode 100644 tests/WebAppCallsWebApiCallsGraph/Client/Services/TodoListService.cs diff --git a/src/Microsoft.Identity.Web/Constants/Constants.cs b/src/Microsoft.Identity.Web/Constants/Constants.cs index 377475bb6..13fc02503 100644 --- a/src/Microsoft.Identity.Web/Constants/Constants.cs +++ b/src/Microsoft.Identity.Web/Constants/Constants.cs @@ -59,6 +59,7 @@ internal static class Constants public const string LoginHint = "loginHint"; public const string DomainHint = "domainHint"; public const string Authorization = "Authorization"; + public const string ApplicationJson = "application/json"; // Blazor challenge URI public const string BlazorChallengeUri = "MicrosoftIdentity/Account/Challenge?redirectUri="; diff --git a/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs b/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs index 5c6eb766f..31d9805eb 100644 --- a/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs +++ b/src/Microsoft.Identity.Web/Constants/IDWebErrorMessage.cs @@ -11,6 +11,7 @@ internal static class IDWebErrorMessage // General IDW10000 = "IDW10000:" public const string HttpContextIsNull = "IDW10001: HttpContext is null. "; public const string HttpContextAndHttpResponseAreNull = "IDW10002: Current HttpContext and HttpResponse argument are null. Pass an HttpResponse argument. "; + public const string InvalidHttpStatusCodeInResponse = "IDW10003: Invalid status code in the HttpResponseMessage. Status code: {0}, Error message: {1} ."; // Configuration IDW10100 = "IDW10100:" public const string ProvideEitherScopeKeySectionOrScopes = "IDW10101: Either provide the '{0}' or the '{1}' to the 'AuthorizeForScopes'. "; @@ -22,7 +23,8 @@ internal static class IDWebErrorMessage "For instance, in the appsettings.json file. "; public const string BothClientSecretAndCertificateProvided = "IDW10105: Both client secret and client certificate, " + "cannot be included in the configuration of the web app when calling a web API. "; - public const string ConfigurationOptionRequired = "The '{0}' option must be provided. "; + public const string ConfigurationOptionRequired = "IDW10106: The '{0}' option must be provided. "; + public const string ScopesNotConfiguredInConfigurationOrViaDelegate = "IDW10107: Scopes need to be passed-in either by configuration or by the delegate overriding it. "; // Authorization IDW10200 = "IDW10200:" public const string NeitherScopeOrRolesClaimFoundInToken = "IDW10201: Neither scope or roles claim was found in the bearer token. "; diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs b/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs deleted file mode 100644 index 88ff1a320..000000000 --- a/src/Microsoft.Identity.Web/DownstreamApiSupport/IDownstreamWebApi.cs +++ /dev/null @@ -1,108 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System; -using System.Net.Http; -using System.Security.Claims; -using System.Threading.Tasks; - -namespace Microsoft.Identity.Web -{ - /// - /// Interface used to call a downstream web API, for instance from controllers. - /// - public interface IDownstreamWebApi - { - /// - /// Calls the Web API for the user, based on a description of the - /// web API in the configuration. - /// - /// Name of the options instance describing the API. There can - /// be several configuration namedsections mapped to a , - /// each for one API. You can pass-in null, but in that case - /// need to be set. - /// Overides the options proposed in the configuration described - /// by . - /// [Optional] claims representing a user. This is useful in scenarios like Blazor - /// or Azure Signal R where the HttpContext is not available. In the other scenarios, the library - /// will find the user itself. - /// Http content in the case where is - /// , , . - /// An that the application will process. - public Task CallWebApiForUserAsync( - string optionsInstanceName, - Action? calledApiOptionsOverride = null, - ClaimsPrincipal? user = null, - StringContent? content = null); - - /// - /// Calls a Web API consuming JSon with some data and returns data. - /// - /// Input type. - /// Output type. - /// Name of the options instance describing the API. There can - /// be several configuration namedsections mapped to a , - /// each for one API. You can pass-in null, but in that case - /// need to be set. - /// Input parameter to the API. - /// Overides the options proposed in the configuration described - /// by . - /// [Optional] claims representing a user. This is useful in scenarios like Blazor - /// or Azure Signal R where the HttpContext is not available. In the other scenarios, the library - /// will find the user itself. - /// The value returned by the API. - /// - /// A list method that returns an IEnumerable<Todo>>. - /// - /// public async Task<IEnumerable<Todo>> GetAsync() - /// { - /// return await _downstreamWebApi.CallWebApiForUserAsync<object, IEnumerable<Todo>>( - /// ServiceName, - /// null, - /// options => - /// { - /// options.RelativePath = $"api/todolist"; - /// }); - /// } - /// - /// - /// Example of editing. - /// - /// public async Task<Todo> EditAsync(Todo todo) - /// { - /// return await _downstreamWebApi.CallWebApiForUserAsync<Todo, Todo>( - /// ServiceName, - /// todo, - /// options => - /// { - /// options.HttpMethod = HttpMethod.Patch; - /// options.RelativePath = $"api/todolist/{todo.Id}"; - /// }); - /// } - /// - /// - public Task CallWebApiForUserAsync( - string optionsInstanceName, - TInput input, - Action? downstreamApiOptionsOverride = null, - ClaimsPrincipal? user = null) - where TOutput : class; - - /// - /// Calls the Web API for the app, with the required scopes. - /// - /// Name of the options instance describing the API. There can - /// be several configuration namedsections mapped to a , - /// each for one API. You can pass-in null, but in that case - /// need to be set. - /// Overides the options proposed in the configuration described - /// by . - /// Http content in the case where is - /// , , . - /// An that the application will process. - public Task CallWebApiForAppAsync( - string optionsInstanceName, - Action? downstreamApiOptionsOverride = null, - StringContent? content = null); - } -} diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApi.cs b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApi.cs similarity index 59% rename from src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApi.cs rename to src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApi.cs index 46c52a1c6..d449913d3 100644 --- a/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApi.cs +++ b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApi.cs @@ -2,28 +2,25 @@ // Licensed under the MIT License. using System; +using System.Globalization; using System.Net; using System.Net.Http; using System.Security.Claims; using System.Text; using System.Text.Json; using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; -using Microsoft.Graph; -using Microsoft.Identity.Web; namespace Microsoft.Identity.Web { /// - /// Implementation for the downstream API. + /// Implementation for the downstream web API. /// public class DownstreamWebApi : IDownstreamWebApi { private readonly ITokenAcquisition _tokenAcquisition; private readonly HttpClient _httpClient; - private readonly IOptionsMonitor _namedOptions; + private readonly IOptionsMonitor _namedDownstreamWebApiOptions; private readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, @@ -33,45 +30,54 @@ public class DownstreamWebApi : IDownstreamWebApi /// Constructor. /// /// Token acquisition service. - /// Named options provider. - /// Http client. + /// Named options provider. + /// HTTP client. public DownstreamWebApi( ITokenAcquisition tokenAcquisition, - IOptionsMonitor namedOptions, + IOptionsMonitor namedDownstreamWebApiOptions, HttpClient httpClient) { _tokenAcquisition = tokenAcquisition; - _namedOptions = namedOptions; + _namedDownstreamWebApiOptions = namedDownstreamWebApiOptions; _httpClient = httpClient; } /// public async Task CallWebApiForUserAsync( string optionsInstanceName, - Action? calledApiOptionsOverride, + Action? calledDownstreamApiOptionsOverride, ClaimsPrincipal? user, StringContent? requestContent) { - DownstreamApiOptions effectiveOptions = MergeOptions(optionsInstanceName, calledApiOptionsOverride); + DownstreamWebApiOptions effectiveOptions = MergeOptions(optionsInstanceName, calledDownstreamApiOptionsOverride); - // verify scopes is not null if (string.IsNullOrEmpty(effectiveOptions.Scopes)) { - throw new ArgumentException("Scopes need to be passed-in either by configuration or by the delegate overring it."); + throw new ArgumentException(IDWebErrorMessage.ScopesNotConfiguredInConfigurationOrViaDelegate); } - string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(effectiveOptions.GetScopes(), effectiveOptions.Tenant) + string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync( + effectiveOptions.GetScopes(), + effectiveOptions.Tenant) .ConfigureAwait(false); HttpResponseMessage response; - using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(effectiveOptions.HttpMethod, effectiveOptions.GetApiUrl())) + using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage( + effectiveOptions.HttpMethod, + effectiveOptions.GetApiUrl())) { if (requestContent != null) { httpRequestMessage.Content = requestContent; } - httpRequestMessage.Headers.Add("Authorization", $"bearer {accessToken}"); + httpRequestMessage.Headers.Add( + Constants.Authorization, + string.Format( + CultureInfo.InvariantCulture, + "{0} {1}", + Constants.Bearer, + accessToken)); response = await _httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false); } @@ -83,23 +89,22 @@ public async Task CallWebApiForUserAsync( /// /// Named configuration. /// Delegate to override the configuration. - internal /* for tests */ DownstreamApiOptions MergeOptions( + internal /* for tests */ DownstreamWebApiOptions MergeOptions( string optionsInstanceName, - Action? calledApiOptionsOverride) + Action? calledApiOptionsOverride) { // Gets the options from configuration (or default value) - DownstreamApiOptions options; + DownstreamWebApiOptions options; if (optionsInstanceName != null) { - options = _namedOptions.Get(optionsInstanceName); + options = _namedDownstreamWebApiOptions.Get(optionsInstanceName); } else { - options = _namedOptions.CurrentValue; + options = _namedDownstreamWebApiOptions.CurrentValue; } - // Give a chance to the called to override defaults for this call - DownstreamApiOptions clonedOptions = options.Clone(); + DownstreamWebApiOptions clonedOptions = options.Clone(); calledApiOptionsOverride?.Invoke(clonedOptions); return clonedOptions; } @@ -108,7 +113,7 @@ public async Task CallWebApiForUserAsync( public async Task CallWebApiForUserAsync( string optionsInstanceName, TInput input, - Action? downstreamApiOptionsOverride = null, + Action? downstreamWebApiOptionsOverride = null, ClaimsPrincipal? user = null) where TOutput : class { @@ -116,8 +121,7 @@ public async Task CallWebApiForUserAsync( if (input != null) { var jsonRequest = JsonSerializer.Serialize(input); - jsoncontent = new StringContent(jsonRequest, Encoding.UTF8, "application/json"); -// case of patch? jsoncontent = new StringContent(jsonRequest, Encoding.UTF8, "application/json-patch+json"); + jsoncontent = new StringContent(jsonRequest, Encoding.UTF8, Constants.ApplicationJson); } else { @@ -126,7 +130,7 @@ public async Task CallWebApiForUserAsync( HttpResponseMessage response = await CallWebApiForUserAsync( optionsInstanceName, - downstreamApiOptionsOverride, + downstreamWebApiOptionsOverride, user, jsoncontent).ConfigureAwait(false); @@ -139,30 +143,44 @@ public async Task CallWebApiForUserAsync( else { string error = await response.Content.ReadAsStringAsync().ConfigureAwait(false); - throw new HttpRequestException($"Invalid status code in the HttpResponseMessage: {response.StatusCode}: {error}"); + throw new HttpRequestException(string.Format( + CultureInfo.InvariantCulture, + IDWebErrorMessage.InvalidHttpStatusCodeInResponse, + response.StatusCode, + error)); } } /// public async Task CallWebApiForAppAsync( string optionsInstanceName, - Action? downstreamApiOptionsOverride = null, + Action? downstreamApiOptionsOverride = null, StringContent? requestContent = null) { - DownstreamApiOptions effectiveOptions = MergeOptions(optionsInstanceName, downstreamApiOptionsOverride); + DownstreamWebApiOptions effectiveOptions = MergeOptions(optionsInstanceName, downstreamApiOptionsOverride); if (effectiveOptions.Scopes == null) { - throw new ArgumentException("Scopes need to be passed-in either by configuration or by the delegate overring it."); + throw new ArgumentException(IDWebErrorMessage.ScopesNotConfiguredInConfigurationOrViaDelegate); } - string accessToken = await _tokenAcquisition.GetAccessTokenForAppAsync(effectiveOptions.Scopes, effectiveOptions.Tenant) + string accessToken = await _tokenAcquisition.GetAccessTokenForAppAsync( + effectiveOptions.Scopes, + effectiveOptions.Tenant) .ConfigureAwait(false); HttpResponseMessage response; - using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage(effectiveOptions.HttpMethod, effectiveOptions.GetApiUrl())) + using (HttpRequestMessage httpRequestMessage = new HttpRequestMessage( + effectiveOptions.HttpMethod, + effectiveOptions.GetApiUrl())) { - httpRequestMessage.Headers.Add("Authorization", $"bearer {accessToken}"); + httpRequestMessage.Headers.Add( + Constants.Authorization, + string.Format( + CultureInfo.InvariantCulture, + "{0} {1}", + Constants.Bearer, + accessToken)); response = await _httpClient.SendAsync(httpRequestMessage).ConfigureAwait(false); } diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApiExtensions.cs b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiExtensions.cs similarity index 63% rename from src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApiExtensions.cs rename to src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiExtensions.cs index d6ec11895..a46c85bb8 100644 --- a/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamWebApiExtensions.cs +++ b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiExtensions.cs @@ -4,26 +4,25 @@ using System; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; namespace Microsoft.Identity.Web { /// - /// Extension methods to support downstream api services. + /// Extension methods to support downstream web API services. /// - public static class DownstreamApiServiceExtensions + public static class DownstreamWebApiServiceExtensions { /// - /// Adds a named downstream API service related to a specific configuration section. + /// Adds a named downstream web API service related to a specific configuration section. /// /// Builder. - /// Name of the configuration for the service. - /// This is the name which will be used when calling the service from controller/pages. + /// Name of the configuration for the service. + /// This is the name used when calling the service from controller/pages. /// Configuration. /// The builder for chaining. - public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddDownstreamApiService( + public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddDownstreamWebApiService( this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, - string optionsInstanceName, + string serviceName, IConfiguration configuration) { if (builder is null) @@ -31,34 +30,34 @@ public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddDownstream throw new ArgumentNullException(nameof(builder)); } - builder.Services.Configure(optionsInstanceName, configuration); + builder.Services.Configure(serviceName, configuration); builder.Services.AddHttpClient(); return builder; } /// - /// Adds a named downstream API service initialized with delegates. + /// Adds a named downstream web API service initialized with delegates. /// /// Builder. - /// Name of the configuration for the service. + /// Name of the configuration for the service. /// This is the name which will be used when calling the service from controller/pages. /// Action to configure the options. /// The builder for chaining. - public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddDownstreamApiService( + public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddDownstreamWebApiService( this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, - string optionsInstanceName, - Action configureOptions) + string serviceName, + Action configureOptions) { if (builder is null) { throw new ArgumentNullException(nameof(builder)); } - builder.Services.Configure(optionsInstanceName, configureOptions); + builder.Services.Configure(serviceName, configureOptions); // https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests builder.Services.AddHttpClient(); - builder.Services.Configure(optionsInstanceName, configureOptions); + builder.Services.Configure(serviceName, configureOptions); return builder; } } diff --git a/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamApiOptions.cs b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs similarity index 71% rename from src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamApiOptions.cs rename to src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs index 313966aee..eb9e3f154 100644 --- a/src/Microsoft.Identity.Web/DownstreamApiSupport/DownstreamApiOptions.cs +++ b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/DownstreamWebApiOptions.cs @@ -6,13 +6,13 @@ namespace Microsoft.Identity.Web { /// - /// Options passed-in to call web APIs. To call Microsoft Graph, see rather + /// Options passed-in to call downstream web APIs. To call Microsoft Graph, see rather /// . /// - public class DownstreamApiOptions + public class DownstreamWebApiOptions { /// - /// Base URL for the called Web API. For instance "https://graph.microsoft.com/beta/".. + /// Base URL for the called downstream web API. For instance "https://graph.microsoft.com/beta/".. /// public string BaseUrl { get; set; } = "https://graph.microsoft.com/v1.0"; @@ -22,27 +22,27 @@ public class DownstreamApiOptions public string RelativePath { get; set; } = string.Empty; /// - /// Space separated scopes required to call the Web API. + /// Space separated scopes required to call the downstream web API. /// For instance "user.read mail.read". /// public string? Scopes { get; set; } = null; /// /// [Optional] tenant ID. This is used for specific scenarios where - /// the application needs to call a Web API on behalf of a user in several tenants. + /// the application needs to call a downstream web API on behalf of a user in several tenants. /// It would mostly be used from code, not from the configuration. /// public string? Tenant { get; set; } = null; /// - /// [Optional]. User flow (in the case of a B2C Web API). If not - /// specified, the B2C web API will be called with the default user flow from + /// [Optional]. User flow (in the case of a B2C downstream web API). If not + /// specified, the B2C downstream web API will be called with the default user flow from /// . /// public string? UserFlow { get; set; } = null; /// - /// Http method used to call this API (by default Get). + /// HTTP method used to call this downstream web API (by default Get). /// public HttpMethod HttpMethod { get; set; } = HttpMethod.Get; @@ -50,9 +50,9 @@ public class DownstreamApiOptions /// Clone the options (to be able to override them). /// /// A clone of the options. - public DownstreamApiOptions Clone() + public DownstreamWebApiOptions Clone() { - return new DownstreamApiOptions + return new DownstreamWebApiOptions { BaseUrl = BaseUrl, RelativePath = RelativePath, @@ -64,9 +64,9 @@ public DownstreamApiOptions Clone() } /// - /// Return the Api URL. + /// Return the downstream web API URL. /// - /// URL of the API. + /// URL of the downstream web API. #pragma warning disable CA1055 // Uri return values should not be strings public string GetApiUrl() #pragma warning restore CA1055 // Uri return values should not be strings diff --git a/src/Microsoft.Identity.Web/DownstreamWebApiSupport/IDownstreamWebApi.cs b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/IDownstreamWebApi.cs new file mode 100644 index 000000000..2c940a224 --- /dev/null +++ b/src/Microsoft.Identity.Web/DownstreamWebApiSupport/IDownstreamWebApi.cs @@ -0,0 +1,108 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Net.Http; +using System.Security.Claims; +using System.Threading.Tasks; + +namespace Microsoft.Identity.Web +{ + /// + /// Interface used to call a downstream web API, for instance from controllers. + /// + public interface IDownstreamWebApi + { + /// + /// Calls the downstream web API for the user, based on a description of the + /// downstream web API in the configuration. + /// + /// Name of the service describing the downstream web API. There can + /// be several configuration named sections mapped to a , + /// each for one downstream web API. You can pass-in null, but in that case + /// need to be set. + /// Overrides the options proposed in the configuration described + /// by . + /// [Optional] Claims representing a user. This is useful platforms like Blazor + /// or Azure Signal R where the HttpContext is not available. In other platforms, the library + /// will find the user from the HttpContext. + /// HTTP context in the case where is + /// , , . + /// An that the application will process. + public Task CallWebApiForUserAsync( + string serviceName, + Action? calledDownstreamWebApiOptionsOverride = null, + ClaimsPrincipal? user = null, + StringContent? content = null); + + /// + /// Calls a downstream web API consuming JSON with some data and returns data. + /// + /// Input type. + /// Output type. + /// Name of the service describing the downstream web API. There can + /// be several configuration named sections mapped to a , + /// each for one downstream web API. You can pass-in null, but in that case + /// need to be set. + /// Input parameter to the downstream web API. + /// Overrides the options proposed in the configuration described + /// by . + /// [Optional] Claims representing a user. This is useful in platforms like Blazor + /// or Azure Signal R where the HttpContext is not available. In other platforms, the library + /// will find the user from the HttpContext. + /// The value returned by the downstream web API. + /// + /// A list method that returns an IEnumerable<Todo>>. + /// + /// public async Task<IEnumerable<Todo>> GetAsync() + /// { + /// return await _downstreamWebApi.CallWebApiForUserAsync<object, IEnumerable<Todo>>( + /// ServiceName, + /// null, + /// options => + /// { + /// options.RelativePath = $"api/todolist"; + /// }); + /// } + /// + /// + /// Example of editing. + /// + /// public async Task<Todo> EditAsync(Todo todo) + /// { + /// return await _downstreamWebApi.CallWebApiForUserAsync<Todo, Todo>( + /// ServiceName, + /// todo, + /// options => + /// { + /// options.HttpMethod = HttpMethod.Patch; + /// options.RelativePath = $"api/todolist/{todo.Id}"; + /// }); + /// } + /// + /// + public Task CallWebApiForUserAsync( + string serviceName, + TInput input, + Action? downstreamWebApiOptionsOverride = null, + ClaimsPrincipal? user = null) + where TOutput : class; + + /// + /// Calls the downstream web API for the app, with the required scopes. + /// + /// Name of the service describing the downstream web API. There can + /// be several configuration named sections mapped to a , + /// each for one downstream web API. You can pass-in null, but in that case + /// need to be set. + /// Overrides the options proposed in the configuration described + /// by . + /// HTTP content in the case where is + /// , , . + /// An that the application will process. + public Task CallWebApiForAppAsync( + string serviceName, + Action? downstreamWebApiOptionsOverride = null, + StringContent? content = null); + } +} diff --git a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml index ab6114de2..ef89ca7e8 100644 --- a/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml +++ b/src/Microsoft.Identity.Web/Microsoft.Identity.Web.xml @@ -530,6 +530,204 @@ True, if the user agent does not allow "SameSite=None" cookie; otherwise, false. + + + Implementation for the downstream web API. + + + + + Constructor. + + Token acquisition service. + Named options provider. + HTTP client. + + + + + + + Merge the options from configuration and override from caller. + + Named configuration. + Delegate to override the configuration. + + + + + + + + + + Extension methods to support downstream web API services. + + + + + Adds a named downstream web API service related to a specific configuration section. + + Builder. + Name of the configuration for the service. + This is the name used when calling the service from controller/pages. + Configuration. + The builder for chaining. + + + + Adds a named downstream web API service initialized with delegates. + + Builder. + Name of the configuration for the service. + This is the name which will be used when calling the service from controller/pages. + Action to configure the options. + The builder for chaining. + + + + Options passed-in to call downstream web APIs. To call Microsoft Graph, see rather + . + + + + + Base URL for the called downstream web API. For instance "https://graph.microsoft.com/beta/".. + + + + + Path relative to the (for instance "me"). + + + + + Space separated scopes required to call the downstream web API. + For instance "user.read mail.read". + + + + + [Optional] tenant ID. This is used for specific scenarios where + the application needs to call a downstream web API on behalf of a user in several tenants. + It would mostly be used from code, not from the configuration. + + + + + [Optional]. User flow (in the case of a B2C downstream web API). If not + specified, the B2C downstream web API will be called with the default user flow from + . + + + + + HTTP method used to call this downstream web API (by default Get). + + + + + Clone the options (to be able to override them). + + A clone of the options. + + + + Return the downstream web API URL. + + URL of the downstream web API. + + + + Returns the scopes. + + Scopes. + + + + Interface used to call a downstream web API, for instance from controllers. + + + + + Calls the downstream web API for the user, based on a description of the + downstream web API in the configuration. + + Name of the service describing the downstream web API. There can + be several configuration named sections mapped to a , + each for one downstream web API. You can pass-in null, but in that case + need to be set. + Overrides the options proposed in the configuration described + by . + [Optional] Claims representing a user. This is useful platforms like Blazor + or Azure Signal R where the HttpContext is not available. In other platforms, the library + will find the user from the HttpContext. + HTTP context in the case where is + , , . + An that the application will process. + + + + Calls a downstream web API consuming JSON with some data and returns data. + + Input type. + Output type. + Name of the service describing the downstream web API. There can + be several configuration named sections mapped to a , + each for one downstream web API. You can pass-in null, but in that case + need to be set. + Input parameter to the downstream web API. + Overrides the options proposed in the configuration described + by . + [Optional] Claims representing a user. This is useful in platforms like Blazor + or Azure Signal R where the HttpContext is not available. In other platforms, the library + will find the user from the HttpContext. + The value returned by the downstream web API. + + A list method that returns an IEnumerable<Todo>>. + + public async Task<IEnumerable<Todo>> GetAsync() + { + return await _downstreamWebApi.CallWebApiForUserAsync<object, IEnumerable<Todo>>( + ServiceName, + null, + options => + { + options.RelativePath = $"api/todolist"; + }); + } + + + Example of editing. + + public async Task<Todo> EditAsync(Todo todo) + { + return await _downstreamWebApi.CallWebApiForUserAsync<Todo, Todo>( + ServiceName, + todo, + options => + { + options.HttpMethod = HttpMethod.Patch; + options.RelativePath = $"api/todolist/{todo.Id}"; + }); + } + + + + + + Calls the downstream web API for the app, with the required scopes. + + Name of the service describing the downstream web API. There can + be several configuration named sections mapped to a , + each for one downstream web API. You can pass-in null, but in that case + need to be set. + Overrides the options proposed in the configuration described + by . + HTTP content in the case where is + , , . + An that the application will process. + Extension methods. @@ -747,30 +945,30 @@ - Extensions methods on a MicrososoftAppCallingWebApiAuthenticationBuilder builder + Extensions methods on a MicrosoftIdentityAppCallingWebApiAuthenticationBuilder builder to add support to call Microsoft Graph. - Add support to calls Microsoft graph. From a named option and a configuration section. + Add support to call Microsoft Graph. From a named option and a configuration section. Builder. - Configuraiton section. + Configuration section. The builder to chain. - Add support to calls Microsoft graph. From a base graph Url and a default scope. + Add support to call Microsoft Graph. From a base Graph URL and a default scope. Builder. Named instance of option. - Configuraiton section. + Configuration section. The builder to chain. - Add support to calls Microsoft graph. From a named options and a configuraiton method. + Add support to call Microsoft Graph. From a named options and a configuration method. Builder. Method to configure the options. @@ -778,7 +976,7 @@ - Authentication provider based on MSAL.NET. + Authentication provider based on ITokenAcquisition. diff --git a/tests/BlazorServerCallsGraph/Startup.cs b/tests/BlazorServerCallsGraph/Startup.cs index 282162d04..89e365e5e 100644 --- a/tests/BlazorServerCallsGraph/Startup.cs +++ b/tests/BlazorServerCallsGraph/Startup.cs @@ -30,7 +30,7 @@ public void ConfigureServices(IServiceCollection services) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") .EnableTokenAcquisitionToCallDownstreamApi() .AddMicrosoftGraphServiceClient(Configuration.GetSection("GraphBeta")) - .AddDownstreamApiService("CalledApi", Configuration.GetSection("CalledApi")) + .AddDownstreamWebApiService("CalledApi", Configuration.GetSection("CalledApi")) .AddInMemoryTokenCaches(); services.AddControllersWithViews() diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Controllers/TodoListController.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Controllers/TodoListController.cs index 3f3fc0a36..653b22f74 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Controllers/TodoListController.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Controllers/TodoListController.cs @@ -1,35 +1,54 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Identity.Web; +using System.Collections.Generic; +using System.Net.Http; using System.Threading.Tasks; -using TodoListClient.Services; using TodoListService.Models; namespace TodoListClient.Controllers { + [Authorize] + [AuthorizeForScopes(ScopeKeySection = "TodoList:Scopes")] public class TodoListController : Controller { - private ITodoListService _todoListService; + private IDownstreamWebApi _downstreamWebApi; + private const string ServiceName = "TodoList"; public TodoListController(IDownstreamWebApi downstreamWebApi) { - _todoListService = new Services.TodoListService(downstreamWebApi); + _downstreamWebApi = downstreamWebApi; } // GET: TodoList - [AuthorizeForScopes(ScopeKeySection = "TodoList:Scopes")] public async Task Index() { - return View(await _todoListService.GetAsync()); + var value = await _downstreamWebApi.CallWebApiForUserAsync>( + ServiceName, + null, + options => + { + options.RelativePath = "api/todolist"; + }); + return View(value); } // GET: TodoList/Details/5 public async Task Details(int id) { - return View(await _todoListService.GetAsync(id)); + var value = await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + null, + options => + { + options.HttpMethod = HttpMethod.Get; + options.RelativePath = $"api/todolist/{id}"; + }); + return View(value); } // GET: TodoList/Create @@ -44,14 +63,28 @@ public ActionResult Create() [ValidateAntiForgeryToken] public async Task Create([Bind("Title,Owner")] Todo todo) { - await _todoListService.AddAsync(todo); + await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + todo, + options => + { + options.HttpMethod = HttpMethod.Post; + options.RelativePath = "api/todolist"; + }); return RedirectToAction("Index"); } // GET: TodoList/Edit/5 public async Task Edit(int id) { - Todo todo = await _todoListService.GetAsync(id); + Todo todo = await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + null, + options => + { + options.HttpMethod = HttpMethod.Get; + options.RelativePath = $"api/todolist/{id}"; + }); if (todo == null) { @@ -66,14 +99,28 @@ public async Task Edit(int id) [ValidateAntiForgeryToken] public async Task Edit(int id, [Bind("Id,Title,Owner")] Todo todo) { - await _todoListService.EditAsync(todo); + await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + todo, + options => + { + options.HttpMethod = HttpMethod.Patch; + options.RelativePath = $"api/todolist/{todo.Id}"; + }); return RedirectToAction("Index"); } // GET: TodoList/Delete/5 public async Task Delete(int id) { - Todo todo = await _todoListService.GetAsync(id); + Todo todo = await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + null, + options => + { + options.HttpMethod = HttpMethod.Get; + options.RelativePath = $"api/todolist/{id}"; + }); if (todo == null) { @@ -88,7 +135,13 @@ public async Task Delete(int id) [ValidateAntiForgeryToken] public async Task Delete(int id, [Bind("Id,Title,Owner")] Todo todo) { - await _todoListService.DeleteAsync(id); + await _downstreamWebApi.CallWebApiForUserAsync( + ServiceName, + options => + { + options.HttpMethod = HttpMethod.Delete; + options.RelativePath = $"api/todolist/{id}"; + }); return RedirectToAction("Index"); } } diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Services/ITodoListService.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Services/ITodoListService.cs deleted file mode 100644 index 84a924cf1..000000000 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Services/ITodoListService.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Collections.Generic; -using System.Threading.Tasks; -using TodoListService.Models; - -namespace TodoListClient.Services -{ - public interface ITodoListService - { - Task> GetAsync(); - - Task GetAsync(int id); - - Task DeleteAsync(int id); - - Task AddAsync(Todo todo); - - Task EditAsync(Todo todo); - } -} diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Services/TodoListService.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Services/TodoListService.cs deleted file mode 100644 index 80cb49801..000000000 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Services/TodoListService.cs +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -using System.Collections.Generic; -using System.Net.Http; -using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Identity.Web; -using TodoListService.Models; - -namespace TodoListClient.Services -{ - public static class TodoListServiceExtensions - { - public static MicrosoftIdentityAppCallsWebApiAuthenticationBuilder AddTodoListService( - this MicrosoftIdentityAppCallsWebApiAuthenticationBuilder builder, - IConfiguration configuration) - { - builder.AddDownstreamApiService(TodoListService.ServiceName, configuration); - // https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests - builder.Services.AddHttpClient(); - return builder; - } - } - - /// - /// - public class TodoListService : ITodoListService - { - private readonly IDownstreamWebApi _downstreamWebApi; - public const string ServiceName = "TodoList"; - - public TodoListService(IDownstreamWebApi downstreamWebApi) - { - _downstreamWebApi = downstreamWebApi; - } - - public async Task AddAsync(Todo todo) - { - return await _downstreamWebApi.CallWebApiForUserAsync( - ServiceName, - todo, - options => - { - options.HttpMethod = HttpMethod.Post; - options.RelativePath = "api/todolist"; - }); - } - - public async Task DeleteAsync(int id) - { - await _downstreamWebApi.CallWebApiForUserAsync( - ServiceName, - options => - { - options.HttpMethod = HttpMethod.Delete; - options.RelativePath = $"api/todolist/{id}"; - }); - } - - public async Task EditAsync(Todo todo) - { - return await _downstreamWebApi.CallWebApiForUserAsync( - ServiceName, - todo, - options => - { - options.HttpMethod = HttpMethod.Patch; - options.RelativePath = $"api/todolist/{todo.Id}"; - }); - } - - public async Task> GetAsync() - { - return await _downstreamWebApi.CallWebApiForUserAsync>( - ServiceName, - null, - options => - { - options.RelativePath = $"api/todolist"; - }); - } - - public async Task GetAsync(int id) - { - return await _downstreamWebApi.CallWebApiForUserAsync( - ServiceName, - null, - options => - { - options.HttpMethod = HttpMethod.Get; - options.RelativePath = $"api/todolist/{id}"; - }); - } - } -} diff --git a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs index c3bb3f3a7..0d7ab1cfd 100644 --- a/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs +++ b/tests/WebAppCallsWebApiCallsGraph/Client/Startup.cs @@ -10,7 +10,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Identity.Web; -using TodoListClient.Services; using Microsoft.Extensions.Hosting; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.Identity.Web.UI; @@ -45,7 +44,7 @@ public void ConfigureServices(IServiceCollection services) services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(Configuration, "AzureAd") .EnableTokenAcquisitionToCallDownstreamApi() - .AddTodoListService(Configuration.GetSection("TodoList")) + .AddDownstreamWebApiService("TodoList", Configuration.GetSection("TodoList")) .AddInMemoryTokenCaches(); services.AddControllersWithViews(options =>