// 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 System.Net; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging.Testing; using Xunit; using Xunit.Abstractions; namespace Microsoft.AspNetCore.Identity.FunctionalTests { public abstract class AuthorizationTests : IClassFixture> where TStartup : class where TContext : DbContext { public AuthorizationTests(ServerFactory serverFactory) { ServerFactory = serverFactory; } public ServerFactory ServerFactory { get; } public static TheoryData AuthorizedPages => new TheoryData { "/Identity/Account/Manage/ChangePassword", "/Identity/Account/Manage/DeletePersonalData", "/Identity/Account/Manage/Disable2fa", "/Identity/Account/Manage/DownloadPersonalData", "/Identity/Account/Manage/EnableAuthenticator", "/Identity/Account/Manage/ExternalLogins", "/Identity/Account/Manage/GenerateRecoveryCodes", "/Identity/Account/Manage/Index", "/Identity/Account/Manage/PersonalData", "/Identity/Account/Manage/ResetAuthenticator", "/Identity/Account/Manage/SetPassword", "/Identity/Account/Manage/ShowRecoveryCodes", "/Identity/Account/Manage/TwoFactorAuthentication", }; [Theory] [MemberData(nameof(AuthorizedPages))] public async Task AnonymousUserCantAccessAuthorizedPages(string url) { // Arrange var client = ServerFactory .CreateClient(); // Act var response = await client.GetAsync(url); // Assert var location = ResponseAssert.IsRedirect(response); Assert.StartsWith("/Identity/Account/Login?", location.PathAndQuery); } // The routes commented below are not directly accessible by // typing the URL in the browser. They have to be accessed as // part of a more complex interation. (like disable 2fa). // /Identity/Account/Manage/Disable2fa // /Identity/Account/Manage/GenerateRecoveryCodes // /Identity/Account/Manage/SetPassword // /Identity/Account/Manage/ShowRecoveryCodes public static TheoryData RouteableAuthorizedPages => new TheoryData { "/Identity/Account/Manage/ChangePassword", "/Identity/Account/Manage/DeletePersonalData", "/Identity/Account/Manage/EnableAuthenticator", "/Identity/Account/Manage/ExternalLogins", "/Identity/Account/Manage/Index", "/Identity/Account/Manage/PersonalData", "/Identity/Account/Manage/ResetAuthenticator", "/Identity/Account/Manage/TwoFactorAuthentication", "/Identity/Account/Logout", }; [Theory] [MemberData(nameof(RouteableAuthorizedPages))] public async Task AuthenticatedUserCanAccessAuthorizedPages(string url) { // Arrange var client = ServerFactory .CreateClient(); await UserStories.RegisterNewUserAsync(client); // Act var response = await client.GetAsync(url); // Assert await ResponseAssert.IsHtmlDocumentAsync(response); } // The routes commented below are not directly accessible by // typing the URL in the browser. They have to be accessed as // part of a more complex interation. (like login with 2fa). // /Identity/Account/LoginWithRecoveryCode // /Identity/Account/LoginWith2fa // /Identity/Account/ExternalLogin // /Identity/Account/ConfirmEmail // /Identity/Account/ResetPassword, public static TheoryData UnauthorizedPages => new TheoryData { "/Identity/Account/Login", "/Identity/Account/Lockout", "/Identity/Account/ForgotPasswordConfirmation", "/Identity/Account/ForgotPassword", "/Identity/Account/AccessDenied", }; [Theory] [MemberData(nameof(UnauthorizedPages))] public async Task AnonymousUserCanAccessNotAuthorizedPages(string url) { // Arrange var client = ServerFactory .CreateClient(); // Act var response = await client.GetAsync(url); // Assert await ResponseAssert.IsHtmlDocumentAsync(response); } public static TheoryData UnauthorizedPagesAllowAnonymous => new TheoryData { "/Identity/Error", "/Identity/Account/Register", "/Identity/Account/Login", "/Identity/Account/ForgotPassword", "/Identity/Account/Logout" }; [Theory] [MemberData(nameof(UnauthorizedPagesAllowAnonymous))] public async Task AnonymousUserAllowedAccessToPages_WithGlobalAuthorizationFilter(string url) { // Arrange void TestServicesConfiguration(IServiceCollection services) => services.SetupGlobalAuthorizeFilter(); var client = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(TestServicesConfiguration)) .CreateClient(); // Act var response = await client.GetAsync(url); // Assert await ResponseAssert.IsHtmlDocumentAsync(response); } } }