Add AllowAnonymous for some Identity razor pages (#1644)

Addresses #1617
This commit is contained in:
Jass Bagga 2018-02-23 13:57:37 -08:00 committed by GitHub
parent e0885a5017
commit 298a1e2a78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 99 additions and 2 deletions

View File

@ -5,12 +5,14 @@ using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
{ {
[AllowAnonymous]
[IdentityDefaultUI(typeof(ForgotPasswordModel<>))] [IdentityDefaultUI(typeof(ForgotPasswordModel<>))]
public abstract class ForgotPasswordModel : PageModel public abstract class ForgotPasswordModel : PageModel
{ {

View File

@ -7,12 +7,14 @@ using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
{ {
[AllowAnonymous]
[IdentityDefaultUI(typeof(LoginModel<>))] [IdentityDefaultUI(typeof(LoginModel<>))]
public abstract class LoginModel : PageModel public abstract class LoginModel : PageModel
{ {

View File

@ -4,12 +4,14 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
{ {
[AllowAnonymous]
[IdentityDefaultUI(typeof(LoginWith2faModel<>))] [IdentityDefaultUI(typeof(LoginWith2faModel<>))]
public abstract class LoginWith2faModel : PageModel public abstract class LoginWith2faModel : PageModel
{ {

View File

@ -4,12 +4,14 @@
using System; using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
{ {
[AllowAnonymous]
[IdentityDefaultUI(typeof(LoginWithRecoveryCodeModel<>))] [IdentityDefaultUI(typeof(LoginWithRecoveryCodeModel<>))]
public abstract class LoginWithRecoveryCodeModel : PageModel public abstract class LoginWithRecoveryCodeModel : PageModel
{ {

View File

@ -3,12 +3,14 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
{ {
[AllowAnonymous]
[IdentityDefaultUI(typeof(LogoutModel<>))] [IdentityDefaultUI(typeof(LogoutModel<>))]
public abstract class LogoutModel : PageModel public abstract class LogoutModel : PageModel
{ {

View File

@ -5,6 +5,7 @@ using System;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
@ -12,6 +13,7 @@ using Microsoft.Extensions.Logging;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
{ {
[AllowAnonymous]
[IdentityDefaultUI(typeof(RegisterModel<>))] [IdentityDefaultUI(typeof(RegisterModel<>))]
public abstract class RegisterModel : PageModel public abstract class RegisterModel : PageModel
{ {

View File

@ -2,11 +2,13 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics; using System.Diagnostics;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Microsoft.AspNetCore.Identity.UI.Pages namespace Microsoft.AspNetCore.Identity.UI.Pages
{ {
[AllowAnonymous]
public class ErrorModel : PageModel public class ErrorModel : PageModel
{ {
public string RequestId { get; set; } public string RequestId { get; set; }

View File

@ -31,7 +31,6 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
"/Identity/Account/Manage/SetPassword", "/Identity/Account/Manage/SetPassword",
"/Identity/Account/Manage/ShowRecoveryCodes", "/Identity/Account/Manage/ShowRecoveryCodes",
"/Identity/Account/Manage/TwoFactorAuthentication", "/Identity/Account/Manage/TwoFactorAuthentication",
"/Identity/Account/Logout",
}; };
[Theory] [Theory]
@ -78,7 +77,7 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
// Arrange // Arrange
var client = ServerFactory.CreateDefaultClient(); var client = ServerFactory.CreateDefaultClient();
await UserStories.RegisterNewUserAsync(client); await UserStories.RegisterNewUserAsync(client);
// Act // Act
var response = await client.GetAsync(url); var response = await client.GetAsync(url);
@ -117,5 +116,31 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
// Assert // Assert
await ResponseAssert.IsHtmlDocumentAsync(response); await ResponseAssert.IsHtmlDocumentAsync(response);
} }
public static TheoryData<string> UnauthorizedPagesAllowAnonymous =>
new TheoryData<string>
{
"/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
var server = ServerFactory.CreateServer(builder =>
builder.ConfigureServices(services => services.SetupGlobalAuthorizeFilter()));
var client = ServerFactory.CreateDefaultClient(server);
// Act
var response = await client.GetAsync(url);
// Assert
await ResponseAssert.IsHtmlDocumentAsync(response);
}
} }
} }

View File

@ -2,8 +2,10 @@
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Identity.DefaultUI.WebSite; using Identity.DefaultUI.WebSite;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.AspNetCore.Identity.UI.Services;
using Microsoft.AspNetCore.Mvc.Authorization;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@ -25,5 +27,15 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
public static IServiceCollection SetupEmailRequired(this IServiceCollection services) => public static IServiceCollection SetupEmailRequired(this IServiceCollection services) =>
services.Configure<IdentityOptions>(o => o.SignIn.RequireConfirmedEmail = true); services.Configure<IdentityOptions>(o => o.SignIn.RequireConfirmedEmail = true);
public static IServiceCollection SetupGlobalAuthorizeFilter(this IServiceCollection services) =>
services.AddMvc(config =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
config.Filters.Add(new AuthorizeFilter(policy));
})
.Services;
} }
} }

View File

@ -58,6 +58,28 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
await UserStories.LoginExistingUser2FaAsync(newClient, userName, password, twoFactorKey); await UserStories.LoginExistingUser2FaAsync(newClient, userName, password, twoFactorKey);
} }
[Fact]
public async Task CanLogInWithTwoFactorAuthentication_WithGlobalAuthorizeFilter()
{
// Arrange
var server = ServerFactory.CreateServer(builder =>
builder.ConfigureServices(services => services.SetupGlobalAuthorizeFilter()));
var client = ServerFactory.CreateDefaultClient(server);
var newClient = ServerFactory.CreateDefaultClient(server);
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"!Test.Password1$";
var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
var showRecoveryCodes = await UserStories.EnableTwoFactorAuthentication(loggedIn);
var twoFactorKey = showRecoveryCodes.Context.AuthenticatorKey;
// Act & Assert
// Use a new client to simulate a new browser session.
await UserStories.LoginExistingUser2FaAsync(newClient, userName, password, twoFactorKey);
}
[Fact] [Fact]
public async Task CanLogInWithRecoveryCode() public async Task CanLogInWithRecoveryCode()
{ {
@ -79,6 +101,28 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
await UserStories.LoginExistingUserRecoveryCodeAsync(newClient, userName, password, recoveryCode); await UserStories.LoginExistingUserRecoveryCodeAsync(newClient, userName, password, recoveryCode);
} }
[Fact]
public async Task CanLogInWithRecoveryCode_WithGlobalAuthorizeFilter()
{
// Arrange
var server = ServerFactory.CreateServer(builder =>
builder.ConfigureServices(services => services.SetupGlobalAuthorizeFilter()));
var client = ServerFactory.CreateDefaultClient(server);
var newClient = ServerFactory.CreateDefaultClient(server);
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"!Test.Password1$";
var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
var showRecoveryCodes = await UserStories.EnableTwoFactorAuthentication(loggedIn);
var recoveryCode = showRecoveryCodes.Context.RecoveryCodes.First();
// Act & Assert
// Use a new client to simulate a new browser session.
await UserStories.LoginExistingUserRecoveryCodeAsync(newClient, userName, password, recoveryCode);
}
[Fact] [Fact]
public async Task CannotLogInWithoutRequiredEmailConfirmation() public async Task CannotLogInWithoutRequiredEmailConfirmation()
{ {

View File

@ -1,10 +1,12 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
namespace Identity.DefaultUI.WebSite.Pages namespace Identity.DefaultUI.WebSite.Pages
{ {
[AllowAnonymous]
public class IndexModel : PageModel public class IndexModel : PageModel
{ {
public void OnGet() public void OnGet()