public OpenIdConnectMiddlewareDiagnosticsTests() { _customEventWasRaised = false; _httpContext = HttpContextUtilities.CreateHttpContext(); _logger = Substitute.For <ILogger <OpenIdConnectMiddlewareDiagnostics> >(); _openIdDiagnostics = new OpenIdConnectMiddlewareDiagnostics(new LoggerMock <OpenIdConnectMiddlewareDiagnostics>(_logger)); _openIdOptions = new OpenIdConnectOptions(); _openIdEvents = new OpenIdConnectEvents(); _authProperties = new AuthenticationProperties(); _authScheme = new AuthenticationScheme(OpenIdConnectDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme, typeof(OpenIdConnectHandler)); _eventHandler = (context) => { _customEventWasRaised = true; return(Task.CompletedTask); }; }
/// <summary> /// Add authentication with Microsoft identity platform. /// This method expects the configuration file will have a section named "AzureAd" with the necessary settings to initialize authentication options. /// </summary> /// <param name="services">Service collection to which to add this authentication scheme</param> /// <param name="configuration">The Configuration object</param> /// <param name="subscribeToOpenIdConnectMiddlewareDiagnosticsEvents"> /// Set to true if you want to debug, or just understand the OpenIdConnect events. /// </param> /// <returns></returns> public static IServiceCollection AddMicrosoftIdentityPlatformAuthentication( this IServiceCollection services, IConfiguration configuration, string configSectionName = "AzureAd", bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false) { services.AddAuthentication(AzureADDefaults.AuthenticationScheme) .AddAzureAD(options => configuration.Bind(configSectionName, options)); services.Configure <AzureADOptions>(options => configuration.Bind(configSectionName, options)); services.Configure <OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options => { // Per the code below, this application signs in users in any Work and School // accounts and any Microsoft Personal Accounts. // If you want to direct Azure AD to restrict the users that can sign-in, change // the tenant value of the appsettings.json file in the following way: // - only Work and School accounts => 'organizations' // - only Microsoft Personal accounts => 'consumers' // - Work and School and Personal accounts => 'common' // If you want to restrict the users that can sign-in to only one tenant // set the tenant value in the appsettings.json file to the tenant ID // or domain of this organization options.Authority = options.Authority + "/v2.0/"; // 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; // Set the nameClaimType to be preferred_username. // This change is needed because certain token claims from Azure AD V1 endpoint // (on which the original .NET core template is based) are different than Microsoft identity platform endpoint. // For more details see [ID Tokens](https://docs.microsoft.com/azure/active-directory/develop/id-tokens) // and [Access Tokens](https://docs.microsoft.com/azure/active-directory/develop/access-tokens) options.TokenValidationParameters.NameClaimType = "preferred_username"; // Avoids having users being presented the select account dialog when they are already signed-in // for instance when going through incremental consent options.Events.OnRedirectToIdentityProvider = context => { var login = context.Properties.GetParameter <string>(OpenIdConnectParameterNames.LoginHint); if (!string.IsNullOrWhiteSpace(login)) { context.ProtocolMessage.LoginHint = login; context.ProtocolMessage.DomainHint = context.Properties.GetParameter <string>( 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); } // Additional claims if (context.Properties.Items.ContainsKey(OidcConstants.AdditionalClaims)) { context.ProtocolMessage.SetParameter( OidcConstants.AdditionalClaims, context.Properties.Items[OidcConstants.AdditionalClaims]); } return(Task.FromResult(0)); }; if (subscribeToOpenIdConnectMiddlewareDiagnosticsEvents) { OpenIdConnectMiddlewareDiagnostics.Subscribe(options.Events); } }); return(services); }
/// <summary> /// 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. /// </summary> /// <param name="builder">AuthenticationBuilder to which to add this configuration</param> /// <param name="configSectionName">The configuration section with the necessary settings to initialize authentication options</param> /// <param name="configuration">The IConfiguration object</param> /// <param name="configureOptions">An action to configure OpenIdConnectOptions</param> /// <param name="openIdConnectScheme">The OpenIdConnect scheme name to be used. By default it uses "OpenIdConnect"</param> /// <param name="cookieScheme">The Cookies scheme name to be used. By default it uses "Cookies"</param> /// <param name="subscribeToOpenIdConnectMiddlewareDiagnosticsEvents"> /// Set to true if you want to debug, or just understand the OpenIdConnect events. /// </param> /// <returns></returns> public static AuthenticationBuilder AddSignIn( this AuthenticationBuilder builder, string configSectionName, IConfiguration configuration, string openIdConnectScheme, string cookieScheme, Action <OpenIdConnectOptions> configureOptions, bool subscribeToOpenIdConnectMiddlewareDiagnosticsEvents = false) { builder.Services.Configure(openIdConnectScheme, configureOptions); builder.Services.Configure <MicrosoftIdentityOptions>(options => configuration.Bind(configSectionName, options)); var microsoftIdentityOptions = configuration.GetSection(configSectionName).Get <MicrosoftIdentityOptions>(); var b2COidcHandlers = new AzureADB2COpenIDConnectEventHandlers(openIdConnectScheme, microsoftIdentityOptions); builder.AddCookie(cookieScheme); builder.AddOpenIdConnect(openIdConnectScheme, options => { options.SignInScheme = cookieScheme; if (string.IsNullOrWhiteSpace(options.Authority)) { options.Authority = AuthorityHelpers.BuildAuthority(microsoftIdentityOptions); } if (!AuthorityHelpers.IsV2Authority(options.Authority)) { options.Authority += "/v2.0"; } // B2C doesn't have preferred_username claims if (microsoftIdentityOptions.IsB2C) { options.TokenValidationParameters.NameClaimType = "name"; } else { options.TokenValidationParameters.NameClaimType = "preferred_username"; } // 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 <string>(OpenIdConnectParameterNames.LoginHint); if (!string.IsNullOrWhiteSpace(login)) { context.ProtocolMessage.LoginHint = login; context.ProtocolMessage.DomainHint = context.Properties.GetParameter <string>( 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); } // Additional claims if (context.Properties.Items.ContainsKey(OidcConstants.AdditionalClaims)) { context.ProtocolMessage.SetParameter( OidcConstants.AdditionalClaims, context.Properties.Items[OidcConstants.AdditionalClaims]); } if (microsoftIdentityOptions.IsB2C) { context.ProtocolMessage.SetParameter("client_info", "1"); // 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); } await redirectToIdpHandler(context).ConfigureAwait(false); }; if (microsoftIdentityOptions.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); await remoteFailureHandler(context).ConfigureAwait(false); }; } if (subscribeToOpenIdConnectMiddlewareDiagnosticsEvents) { OpenIdConnectMiddlewareDiagnostics.Subscribe(options.Events); } }); return(builder); }