diff --git a/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADAuthenticationBuilderExtensions.cs b/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADAuthenticationBuilderExtensions.cs index 59daae707cf4..2337ddc8408a 100644 --- a/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADAuthenticationBuilderExtensions.cs +++ b/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADAuthenticationBuilderExtensions.cs @@ -60,6 +60,8 @@ public static AuthenticationBuilder AddAzureADBearer( builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, AzureADOptionsConfiguration>()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, AzureADOptionsValidation>()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, AzureADJwtBearerOptionsConfiguration>()); builder.Services.Configure(scheme, configureOptions); @@ -115,6 +117,8 @@ public static AuthenticationBuilder AddAzureAD( builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, AzureADOptionsConfiguration>()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, AzureADOptionsValidation>()); + builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, AzureADOpenIdConnectOptionsConfiguration>()); builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton, AzureADCookieOptionsConfiguration>()); diff --git a/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADOptionsValidation.cs b/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADOptionsValidation.cs new file mode 100644 index 000000000000..9b551d4dd81a --- /dev/null +++ b/src/Azure/AzureAD/Authentication.AzureAD.UI/src/AzureADOptionsValidation.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; + +using Microsoft.Extensions.Options; + +namespace Microsoft.AspNetCore.Authentication.AzureAD.UI +{ + internal class AzureADOptionsValidation : IValidateOptions + { + public ValidateOptionsResult Validate(string name, AzureADOptions options) + { + if (string.IsNullOrEmpty(options.Instance)) + { + return ValidateOptionsResult.Fail($"The '{nameof(AzureADOptions.Instance)}' option must be provided."); + } + + return ValidateOptionsResult.Success; + } + } +} diff --git a/src/Azure/AzureAD/Authentication.AzureAD.UI/test/AzureADAuthenticationBuilderExtensionsTests.cs b/src/Azure/AzureAD/Authentication.AzureAD.UI/test/AzureADAuthenticationBuilderExtensionsTests.cs index 2dd42619fa5e..1f0cb14ac4d4 100644 --- a/src/Azure/AzureAD/Authentication.AzureAD.UI/test/AzureADAuthenticationBuilderExtensionsTests.cs +++ b/src/Azure/AzureAD/Authentication.AzureAD.UI/test/AzureADAuthenticationBuilderExtensionsTests.cs @@ -2,10 +2,10 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.using Microsoft.AspNetCore.Authorization; using System; +using Microsoft.AspNetCore.Authentication.AzureAD.UI; using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.AspNetCore.Authentication.AzureAD.UI; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; @@ -237,6 +237,28 @@ public void AddAzureAD_ThrowsWhenCookieSchemeIsAlreadyInUse() Assert.Equal(expectedMessage, exception.Message); } + [Fact] + public void AddAzureAD_ThrowsWhenInstanceIsNotSet() + { + // Arrange + var services = new ServiceCollection(); + services.AddSingleton(new NullLoggerFactory()); + + services.AddAuthentication() + .AddAzureAD(o => { }); + + var provider = services.BuildServiceProvider(); + var azureADOptionsMonitor = provider.GetService>(); + + var expectedMessage = "The 'Instance' option must be provided."; + + // Act & Assert + var exception = Assert.Throws( + () => azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme)); + + Assert.Contains(expectedMessage, exception.Failures); + } + [Fact] public void AddAzureADBearer_AddsAllAuthenticationHandlers() { @@ -400,5 +422,27 @@ public void AddAzureADBearer_ThrowsWhenBearerSchemeIsAlreadyInUse() Assert.Equal(expectedMessage, exception.Message); } + + [Fact] + public void AddAzureADBearer_ThrowsWhenInstanceIsNotSet() + { + // Arrange + var services = new ServiceCollection(); + services.AddSingleton(new NullLoggerFactory()); + + services.AddAuthentication() + .AddAzureADBearer(o => { }); + + var provider = services.BuildServiceProvider(); + var azureADOptionsMonitor = provider.GetService>(); + + var expectedMessage = "The 'Instance' option must be provided."; + + // Act & Assert + var exception = Assert.Throws( + () => azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme)); + + Assert.Contains(expectedMessage, exception.Failures); + } } }