| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457 |
- // 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 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.Http;
- using Microsoft.Extensions.DependencyInjection;
- using Microsoft.Extensions.Logging;
- using Microsoft.Extensions.Logging.Abstractions;
- using Microsoft.Extensions.Options;
- using Xunit;
- namespace Microsoft.AspNetCore.Authentication
- {
- public class AzureADAuthenticationBuilderExtensionsTests
- {
- [Fact]
- public void AddAzureAD_AddsAllAuthenticationHandlers()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- // Act
- services.AddAuthentication()
- .AddAzureAD(o => { });
- var provider = services.BuildServiceProvider();
- // Assert
- Assert.NotNull(provider.GetService<OpenIdConnectHandler>());
- Assert.NotNull(provider.GetService<CookieAuthenticationHandler>());
- Assert.NotNull(provider.GetService<PolicySchemeHandler>());
- }
- [Fact]
- public void AddAzureAD_ConfiguresAllOptions()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- // Act
- services.AddAuthentication()
- .AddAzureAD(o =>
- {
- o.Instance = "https://login.microsoftonline.com";
- o.ClientId = "ClientId";
- o.ClientSecret = "ClientSecret";
- o.CallbackPath = "/signin-oidc";
- o.Domain = "domain.onmicrosoft.com";
- o.TenantId = "Common";
- });
- var provider = services.BuildServiceProvider();
- // Assert
- var azureADOptionsMonitor = provider.GetService<IOptionsMonitor<AzureADOptions>>();
- Assert.NotNull(azureADOptionsMonitor);
- var azureADOptions = azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme);
- Assert.Equal(AzureADDefaults.OpenIdScheme, azureADOptions.OpenIdConnectSchemeName);
- Assert.Equal(AzureADDefaults.CookieScheme, azureADOptions.CookieSchemeName);
- Assert.Equal("https://login.microsoftonline.com", azureADOptions.Instance);
- Assert.Equal("ClientId", azureADOptions.ClientId);
- Assert.Equal("ClientSecret", azureADOptions.ClientSecret);
- Assert.Equal("/signin-oidc", azureADOptions.CallbackPath);
- Assert.Equal("domain.onmicrosoft.com", azureADOptions.Domain);
- var openIdOptionsMonitor = provider.GetService<IOptionsMonitor<OpenIdConnectOptions>>();
- Assert.NotNull(openIdOptionsMonitor);
- var openIdOptions = openIdOptionsMonitor.Get(AzureADDefaults.OpenIdScheme);
- Assert.Equal("ClientId", openIdOptions.ClientId);
- Assert.Equal($"https://login.microsoftonline.com/Common", openIdOptions.Authority);
- Assert.True(openIdOptions.UseTokenLifetime);
- Assert.Equal("/signin-oidc", openIdOptions.CallbackPath);
- Assert.Equal(AzureADDefaults.CookieScheme, openIdOptions.SignInScheme);
- var cookieAuthenticationOptionsMonitor = provider.GetService<IOptionsMonitor<CookieAuthenticationOptions>>();
- Assert.NotNull(cookieAuthenticationOptionsMonitor);
- var cookieAuthenticationOptions = cookieAuthenticationOptionsMonitor.Get(AzureADDefaults.CookieScheme);
- Assert.Equal("/AzureAD/Account/SignIn/AzureAD", cookieAuthenticationOptions.LoginPath);
- Assert.Equal("/AzureAD/Account/SignOut/AzureAD", cookieAuthenticationOptions.LogoutPath);
- Assert.Equal("/AzureAD/Account/AccessDenied", cookieAuthenticationOptions.AccessDeniedPath);
- Assert.Equal(SameSiteMode.None, cookieAuthenticationOptions.Cookie.SameSite);
- }
- [Fact]
- public void AddAzureAD_AllowsOverridingCookiesAndOpenIdConnectSettings()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- // Act
- services.AddAuthentication()
- .AddAzureAD(o =>
- {
- o.Instance = "https://login.microsoftonline.com";
- o.ClientId = "ClientId";
- o.ClientSecret = "ClientSecret";
- o.CallbackPath = "/signin-oidc";
- o.Domain = "domain.onmicrosoft.com";
- o.TenantId = "Common";
- });
- services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, o =>
- {
- o.Authority = "https://overriden.com";
- });
- services.Configure<CookieAuthenticationOptions>(AzureADDefaults.CookieScheme, o =>
- {
- o.AccessDeniedPath = "/Overriden";
- });
- var provider = services.BuildServiceProvider();
- // Assert
- var openIdOptionsMonitor = provider.GetService<IOptionsMonitor<OpenIdConnectOptions>>();
- Assert.NotNull(openIdOptionsMonitor);
- var openIdOptions = openIdOptionsMonitor.Get(AzureADDefaults.OpenIdScheme);
- Assert.Equal("ClientId", openIdOptions.ClientId);
- Assert.Equal($"https://overriden.com", openIdOptions.Authority);
- var cookieAuthenticationOptionsMonitor = provider.GetService<IOptionsMonitor<CookieAuthenticationOptions>>();
- Assert.NotNull(cookieAuthenticationOptionsMonitor);
- var cookieAuthenticationOptions = cookieAuthenticationOptionsMonitor.Get(AzureADDefaults.CookieScheme);
- Assert.Equal("/AzureAD/Account/SignIn/AzureAD", cookieAuthenticationOptions.LoginPath);
- Assert.Equal("/Overriden", cookieAuthenticationOptions.AccessDeniedPath);
- }
- [Fact]
- public void AddAzureAD_RegisteringAddCookiesAndAddOpenIdConnectHasNoImpactOnAzureAAExtensions()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- // Act
- services.AddAuthentication()
- .AddOpenIdConnect()
- .AddCookie()
- .AddAzureAD(o =>
- {
- o.Instance = "https://login.microsoftonline.com";
- o.ClientId = "ClientId";
- o.ClientSecret = "ClientSecret";
- o.CallbackPath = "/signin-oidc";
- o.Domain = "domain.onmicrosoft.com";
- o.TenantId = "Common";
- });
- services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, o =>
- {
- o.Authority = "https://overriden.com";
- });
- services.Configure<CookieAuthenticationOptions>(AzureADDefaults.CookieScheme, o =>
- {
- o.AccessDeniedPath = "/Overriden";
- });
- var provider = services.BuildServiceProvider();
- // Assert
- var openIdOptionsMonitor = provider.GetService<IOptionsMonitor<OpenIdConnectOptions>>();
- Assert.NotNull(openIdOptionsMonitor);
- var openIdOptions = openIdOptionsMonitor.Get(AzureADDefaults.OpenIdScheme);
- Assert.Equal("ClientId", openIdOptions.ClientId);
- Assert.Equal($"https://overriden.com", openIdOptions.Authority);
- var cookieAuthenticationOptionsMonitor = provider.GetService<IOptionsMonitor<CookieAuthenticationOptions>>();
- Assert.NotNull(cookieAuthenticationOptionsMonitor);
- var cookieAuthenticationOptions = cookieAuthenticationOptionsMonitor.Get(AzureADDefaults.CookieScheme);
- Assert.Equal("/AzureAD/Account/SignIn/AzureAD", cookieAuthenticationOptions.LoginPath);
- Assert.Equal("/Overriden", cookieAuthenticationOptions.AccessDeniedPath);
- }
- [Fact]
- public void AddAzureAD_ThrowsForDuplicatedSchemes()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- services.AddAuthentication()
- .AddAzureAD(o => { })
- .AddAzureAD(o => { });
- var provider = services.BuildServiceProvider();
- var azureADOptionsMonitor = provider.GetService<IOptionsMonitor<AzureADOptions>>();
- // Act & Assert
- var exception = Assert.Throws<InvalidOperationException>(
- () => azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme));
- Assert.Equal("A scheme with the name 'AzureAD' was already added.", exception.Message);
- }
- [Fact]
- public void AddAzureAD_ThrowsWhenOpenIdSchemeIsAlreadyInUse()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- services.AddAuthentication()
- .AddAzureAD(o => { })
- .AddAzureAD("Custom", AzureADDefaults.OpenIdScheme, "Cookie", null, o => { });
- var provider = services.BuildServiceProvider();
- var azureADOptionsMonitor = provider.GetService<IOptionsMonitor<AzureADOptions>>();
- var expectedMessage = $"The Open ID Connect scheme 'AzureADOpenID' can't be associated with the Azure Active Directory scheme 'Custom'. " +
- "The Open ID Connect scheme 'AzureADOpenID' is already mapped to the Azure Active Directory scheme 'AzureAD'";
- // Act & Assert
- var exception = Assert.Throws<InvalidOperationException>(
- () => azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme));
- Assert.Equal(expectedMessage, exception.Message);
- }
- [Fact]
- public void AddAzureAD_ThrowsWhenCookieSchemeIsAlreadyInUse()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- services.AddAuthentication()
- .AddAzureAD(o => { })
- .AddAzureAD("Custom", "OpenID", AzureADDefaults.CookieScheme, null, o => { });
- var provider = services.BuildServiceProvider();
- var azureADOptionsMonitor = provider.GetService<IOptionsMonitor<AzureADOptions>>();
- var expectedMessage = $"The cookie scheme 'AzureADCookie' can't be associated with the Azure Active Directory scheme 'Custom'. " +
- "The cookie scheme 'AzureADCookie' is already mapped to the Azure Active Directory scheme 'AzureAD'";
- // Act & Assert
- var exception = Assert.Throws<InvalidOperationException>(
- () => azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme));
- Assert.Equal(expectedMessage, exception.Message);
- }
- [Fact]
- public void AddAzureAD_ThrowsWhenInstanceIsNotSet()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- services.AddAuthentication()
- .AddAzureAD(o => { });
- var provider = services.BuildServiceProvider();
- var azureADOptionsMonitor = provider.GetService<IOptionsMonitor<AzureADOptions>>();
- var expectedMessage = "The 'Instance' option must be provided.";
- // Act & Assert
- var exception = Assert.Throws<OptionsValidationException>(
- () => azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme));
- Assert.Contains(expectedMessage, exception.Failures);
- }
- [Fact]
- public void AddAzureADBearer_AddsAllAuthenticationHandlers()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- // Act
- services.AddAuthentication()
- .AddAzureADBearer(o => { });
- var provider = services.BuildServiceProvider();
- // Assert
- Assert.NotNull(provider.GetService<JwtBearerHandler>());
- Assert.NotNull(provider.GetService<PolicySchemeHandler>());
- }
- [Fact]
- public void AddAzureADBearer_ConfiguresAllOptions()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- // Act
- services.AddAuthentication()
- .AddAzureADBearer(o =>
- {
- o.Instance = "https://login.microsoftonline.com/";
- o.ClientId = "ClientId";
- o.CallbackPath = "/signin-oidc";
- o.Domain = "domain.onmicrosoft.com";
- o.TenantId = "TenantId";
- });
- var provider = services.BuildServiceProvider();
- // Assert
- var azureADOptionsMonitor = provider.GetService<IOptionsMonitor<AzureADOptions>>();
- Assert.NotNull(azureADOptionsMonitor);
- var options = azureADOptionsMonitor.Get(AzureADDefaults.BearerAuthenticationScheme);
- Assert.Equal(AzureADDefaults.JwtBearerAuthenticationScheme, options.JwtBearerSchemeName);
- Assert.Equal("https://login.microsoftonline.com/", options.Instance);
- Assert.Equal("ClientId", options.ClientId);
- Assert.Equal("domain.onmicrosoft.com", options.Domain);
- var bearerOptionsMonitor = provider.GetService<IOptionsMonitor<JwtBearerOptions>>();
- Assert.NotNull(bearerOptionsMonitor);
- var bearerOptions = bearerOptionsMonitor.Get(AzureADDefaults.JwtBearerAuthenticationScheme);
- Assert.Equal("ClientId", bearerOptions.Audience);
- Assert.Equal($"https://login.microsoftonline.com/TenantId", bearerOptions.Authority);
- }
- [Fact]
- public void AddAzureADBearer_CanOverrideJwtBearerOptionsConfiguration()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- // Act
- services.AddAuthentication()
- .AddAzureADBearer(o =>
- {
- o.Instance = "https://login.microsoftonline.com/";
- o.ClientId = "ClientId";
- o.CallbackPath = "/signin-oidc";
- o.Domain = "domain.onmicrosoft.com";
- o.TenantId = "TenantId";
- });
- services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, o =>
- {
- o.Audience = "http://overriden.com";
- });
- var provider = services.BuildServiceProvider();
- // Assert
- var bearerOptionsMonitor = provider.GetService<IOptionsMonitor<JwtBearerOptions>>();
- Assert.NotNull(bearerOptionsMonitor);
- var bearerOptions = bearerOptionsMonitor.Get(AzureADDefaults.JwtBearerAuthenticationScheme);
- Assert.Equal("http://overriden.com", bearerOptions.Audience);
- Assert.Equal($"https://login.microsoftonline.com/TenantId", bearerOptions.Authority);
- }
- [Fact]
- public void AddAzureADBearer_RegisteringJwtBearerHasNoImpactOnAzureAAExtensions()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- // Act
- services.AddAuthentication()
- .AddJwtBearer()
- .AddAzureADBearer(o =>
- {
- o.Instance = "https://login.microsoftonline.com/";
- o.ClientId = "ClientId";
- o.CallbackPath = "/signin-oidc";
- o.Domain = "domain.onmicrosoft.com";
- o.TenantId = "TenantId";
- });
- services.Configure<JwtBearerOptions>(AzureADDefaults.JwtBearerAuthenticationScheme, o =>
- {
- o.Audience = "http://overriden.com";
- });
- var provider = services.BuildServiceProvider();
- // Assert
- var bearerOptionsMonitor = provider.GetService<IOptionsMonitor<JwtBearerOptions>>();
- Assert.NotNull(bearerOptionsMonitor);
- var bearerOptions = bearerOptionsMonitor.Get(AzureADDefaults.JwtBearerAuthenticationScheme);
- Assert.Equal("http://overriden.com", bearerOptions.Audience);
- Assert.Equal($"https://login.microsoftonline.com/TenantId", bearerOptions.Authority);
- }
- [Fact]
- public void AddAzureADBearer_ThrowsForDuplicatedSchemes()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- services.AddAuthentication()
- .AddAzureADBearer(o => { })
- .AddAzureADBearer(o => { });
- var provider = services.BuildServiceProvider();
- var azureADOptionsMonitor = provider.GetService<IOptionsMonitor<AzureADOptions>>();
- // Act & Assert
- var exception = Assert.Throws<InvalidOperationException>(
- () => azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme));
- Assert.Equal("A scheme with the name 'AzureADBearer' was already added.", exception.Message);
- }
- [Fact]
- public void AddAzureADBearer_ThrowsWhenBearerSchemeIsAlreadyInUse()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- services.AddAuthentication()
- .AddAzureADBearer(o => { })
- .AddAzureADBearer("Custom", AzureADDefaults.JwtBearerAuthenticationScheme, o => { });
- var provider = services.BuildServiceProvider();
- var azureADOptionsMonitor = provider.GetService<IOptionsMonitor<AzureADOptions>>();
- var expectedMessage = $"The JSON Web Token Bearer scheme 'AzureADJwtBearer' can't be associated with the Azure Active Directory scheme 'Custom'. " +
- "The JSON Web Token Bearer scheme 'AzureADJwtBearer' is already mapped to the Azure Active Directory scheme 'AzureADBearer'";
- // Act & Assert
- var exception = Assert.Throws<InvalidOperationException>(
- () => azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme));
- Assert.Equal(expectedMessage, exception.Message);
- }
- [Fact]
- public void AddAzureADBearer_ThrowsWhenInstanceIsNotSet()
- {
- // Arrange
- var services = new ServiceCollection();
- services.AddSingleton<ILoggerFactory>(new NullLoggerFactory());
- services.AddAuthentication()
- .AddAzureADBearer(o => { });
- var provider = services.BuildServiceProvider();
- var azureADOptionsMonitor = provider.GetService<IOptionsMonitor<AzureADOptions>>();
- var expectedMessage = "The 'Instance' option must be provided.";
- // Act & Assert
- var exception = Assert.Throws<OptionsValidationException>(
- () => azureADOptionsMonitor.Get(AzureADDefaults.AuthenticationScheme));
- Assert.Contains(expectedMessage, exception.Failures);
- }
- }
- }
|