From a89dc30d43c35e6865d19d183037f8ecac1c1226 Mon Sep 17 00:00:00 2001 From: Jass Bagga Date: Tue, 1 May 2018 12:30:46 -0700 Subject: [PATCH] AllowAnonymous for external login providers and confirm email (#1769) Addresses #1762 --- .../Pages/Account/ConfirmEmail.cshtml.cs | 2 + .../Pages/Account/ExternalLogin.cshtml.cs | 2 + test/Identity.FunctionalTests/LoginTests.cs | 110 +++++++++++++++++- .../RegistrationTests.cs | 39 +++++++ .../Pages/Contoso/Login.cshtml.cs | 2 + 5 files changed, 151 insertions(+), 4 deletions(-) diff --git a/src/UI/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs b/src/UI/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs index daa126c877..0538c916d1 100644 --- a/src/UI/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs +++ b/src/UI/Areas/Identity/Pages/Account/ConfirmEmail.cshtml.cs @@ -3,11 +3,13 @@ using System; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal { + [AllowAnonymous] [IdentityDefaultUI(typeof(ConfirmEmailModel<>))] public abstract class ConfirmEmailModel : PageModel { diff --git a/src/UI/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs b/src/UI/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs index a0e5205d46..f57f6c7ad4 100644 --- a/src/UI/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs +++ b/src/UI/Areas/Identity/Pages/Account/ExternalLogin.cshtml.cs @@ -6,12 +6,14 @@ using System.ComponentModel.DataAnnotations; using System.Security.Claims; using System.Threading; using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Logging; namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal { + [AllowAnonymous] [IdentityDefaultUI(typeof(ExternalLoginModel<>))] public class ExternalLoginModel : PageModel { diff --git a/test/Identity.FunctionalTests/LoginTests.cs b/test/Identity.FunctionalTests/LoginTests.cs index e8c31c8eda..4aa9a6b7a7 100644 --- a/test/Identity.FunctionalTests/LoginTests.cs +++ b/test/Identity.FunctionalTests/LoginTests.cs @@ -8,7 +8,6 @@ using Identity.DefaultUI.WebSite; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Xunit; -using Xunit.Abstractions; using Xunit.Sdk; namespace Microsoft.AspNetCore.Identity.FunctionalTests @@ -41,6 +40,29 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests await UserStories.LoginExistingUserAsync(newClient, userName, password); } + [Fact] + public async Task CanLogInWithAPreviouslyRegisteredUser_WithGlobalAuthorizeFilter() + { + // Arrange + void ConfigureTestServices(IServiceCollection services) => + services.SetupGlobalAuthorizeFilter(); + + var server = ServerFactory + .WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices)); + + var client = server.CreateClient(); + var newClient = server.CreateClient(); + + var userName = $"{Guid.NewGuid()}@example.com"; + var password = $"!Test.Password1$"; + + // Act & Assert + await UserStories.RegisterNewUserAsync(client, userName, password); + + // Use a new client to simulate a new browser session. + await UserStories.LoginExistingUserAsync(newClient, userName, password); + } + [Fact] public async Task CanLogInWithTwoFactorAuthentication() { @@ -65,8 +87,14 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests public async Task CanLogInWithTwoFactorAuthentication_WithGlobalAuthorizeFilter() { // Arrange - var client = ServerFactory.CreateClient(); - var newClient = ServerFactory.CreateClient(); + void ConfigureTestServices(IServiceCollection services) => + services.SetupGlobalAuthorizeFilter(); + + var server = ServerFactory + .WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices)); + + var client = server.CreateClient(); + var newClient = server.CreateClient(); var userName = $"{Guid.NewGuid()}@example.com"; var password = $"!Test.Password1$"; @@ -130,7 +158,6 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests public async Task CannotLogInWithoutRequiredEmailConfirmation() { // Arrange - var emailSender = new ContosoEmailSender(); void ConfigureTestServices(IServiceCollection services) => services .SetupTestEmailSender(emailSender) @@ -151,6 +178,31 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests await Assert.ThrowsAnyAsync(() => UserStories.LoginExistingUserAsync(newClient, userName, password)); } + [Fact] + public async Task CannotLogInWithoutRequiredEmailConfirmation_WithGlobalAuthorizeFilter() + { + // Arrange + var emailSender = new ContosoEmailSender(); + void ConfigureTestServices(IServiceCollection services) => services + .SetupTestEmailSender(emailSender) + .SetupEmailRequired() + .SetupGlobalAuthorizeFilter(); + + var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices)); + + var client = server.CreateClient(); + var newClient = server.CreateClient(); + + var userName = $"{Guid.NewGuid()}@example.com"; + var password = $"!Test.Password1$"; + + var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password); + + // Act & Assert + // Use a new client to simulate a new browser session. + await Assert.ThrowsAnyAsync(() => UserStories.LoginExistingUserAsync(newClient, userName, password)); + } + [Fact] public async Task CanLogInAfterConfirmingEmail() { @@ -178,6 +230,34 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests await UserStories.LoginExistingUserAsync(newClient, userName, password); } + [Fact] + public async Task CanLogInAfterConfirmingEmail_WithGlobalAuthorizeFilter() + { + // Arrange + var emailSender = new ContosoEmailSender(); + void ConfigureTestServices(IServiceCollection services) => services + .SetupTestEmailSender(emailSender) + .SetupEmailRequired() + .SetupGlobalAuthorizeFilter(); + + var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices)); + + var client = server.CreateClient(); + var newClient = server.CreateClient(); + + var userName = $"{Guid.NewGuid()}@example.com"; + var password = $"!Test.Password1$"; + + var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password); + + // Act & Assert + // Use a new client to simulate a new browser session. + var email = Assert.Single(emailSender.SentEmails); + await UserStories.ConfirmEmailAsync(email, newClient); + + await UserStories.LoginExistingUserAsync(newClient, userName, password); + } + [Fact] public async Task CanLoginWithASocialLoginProvider() { @@ -199,6 +279,28 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests await UserStories.LoginWithSocialLoginAsync(newClient, userName); } + [Fact] + public async Task CanLoginWithASocialLoginProvider_WithGlobalAuthorizeFilter() + { + // Arrange + void ConfigureTestServices(IServiceCollection services) => services + .SetupTestThirdPartyLogin() + .SetupGlobalAuthorizeFilter(); + + var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices)); + + var client = server.CreateClient(); + var newClient = server.CreateClient(); + + var guid = Guid.NewGuid(); + var userName = $"{guid}"; + var email = $"{guid}@example.com"; + + // Act & Assert + await UserStories.RegisterNewUserWithSocialLoginAsync(client, userName, email); + await UserStories.LoginWithSocialLoginAsync(newClient, userName); + } + [Fact] public async Task CanLogInAfterResettingThePassword() { diff --git a/test/Identity.FunctionalTests/RegistrationTests.cs b/test/Identity.FunctionalTests/RegistrationTests.cs index b239323e9d..0ad2a32858 100644 --- a/test/Identity.FunctionalTests/RegistrationTests.cs +++ b/test/Identity.FunctionalTests/RegistrationTests.cs @@ -37,6 +37,24 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests await UserStories.RegisterNewUserAsync(client, userName, password); } + [Fact] + public async Task CanRegisterAUser_WithGlobalAuthorizeFilter() + { + // Arrange + void ConfigureTestServices(IServiceCollection services) => + services.SetupGlobalAuthorizeFilter(); + + var client = ServerFactory + .WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices)) + .CreateClient(); + + var userName = $"{Guid.NewGuid()}@example.com"; + var password = $"!Test.Password1$"; + + // Act & Assert + await UserStories.RegisterNewUserAsync(client, userName, password); + } + [Fact] public async Task CanRegisterWithASocialLoginProvider() { @@ -56,5 +74,26 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests // Act & Assert await UserStories.RegisterNewUserWithSocialLoginAsync(client, userName, email); } + + [Fact] + public async Task CanRegisterWithASocialLoginProvider_WithGlobalAuthorizeFilter() + { + // Arrange + void ConfigureTestServices(IServiceCollection services) => + services + .SetupTestThirdPartyLogin() + .SetupGlobalAuthorizeFilter(); + + var client = ServerFactory + .WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices)) + .CreateClient(); + + var guid = Guid.NewGuid(); + var userName = $"{guid}"; + var email = $"{guid}@example.com"; + + // Act & Assert + await UserStories.RegisterNewUserWithSocialLoginAsync(client, userName, email); + } } } diff --git a/test/WebSites/Identity.DefaultUI.WebSite/Pages/Contoso/Login.cshtml.cs b/test/WebSites/Identity.DefaultUI.WebSite/Pages/Contoso/Login.cshtml.cs index a99f1f7ff4..722128cf21 100644 --- a/test/WebSites/Identity.DefaultUI.WebSite/Pages/Contoso/Login.cshtml.cs +++ b/test/WebSites/Identity.DefaultUI.WebSite/Pages/Contoso/Login.cshtml.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.Extensions.Options; @@ -13,6 +14,7 @@ using System.Threading.Tasks; namespace Identity.DefaultUI.WebSite.Pages { + [AllowAnonymous] public class LoginModel : PageModel { public LoginModel(IOptionsMonitor options)