Add AllowAnonymous for resetting password navigation flow (#1744)

Addresses #1736 and aspnet/templating#448
This commit is contained in:
Jass Bagga 2018-04-13 16:46:00 -07:00 committed by GitHub
parent e5d9efbd48
commit ae9aa9ebec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 89 additions and 2 deletions

View File

@ -1,10 +1,12 @@
// 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.AspNetCore.Mvc.RazorPages;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
{
[AllowAnonymous]
public class ForgotPasswordConfirmation : PageModel
{
public void OnGet()

View File

@ -1,10 +1,12 @@
// 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.AspNetCore.Mvc.RazorPages;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
{
[AllowAnonymous]
public class LockoutModel : PageModel
{
public void OnGet()

View File

@ -4,11 +4,13 @@
using System;
using System.ComponentModel.DataAnnotations;
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(ResetPasswordModel<>))]
public abstract class ResetPasswordModel : PageModel
{

View File

@ -1,10 +1,12 @@
// 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.AspNetCore.Mvc.RazorPages;
namespace Microsoft.AspNetCore.Identity.UI.Pages.Account.Internal
{
[AllowAnonymous]
public class ResetPasswordConfirmationModel : PageModel
{
public void OnGet()

View File

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Razor">
<Project Sdk="Microsoft.NET.Sdk.Razor">
<PropertyGroup>
<Description>ASP.NET Core Identity UI is the default Razor Pages built-in UI for the ASP.NET Core Identity framework.</Description>
@ -16,7 +16,7 @@
<EmbeddedResource Remove="wwwroot/**/LICENSE*" />
<None Remove="wwwroot/**/.bower.json" />
<None Remove="wwwroot/**/LICENSE*" />
<None Include="THIRD-PARTY-NOTICES" Pack="true" />
<None Include="THIRD-PARTY-NOTICES" Pack="true" PackagePath="/"/>
</ItemGroup>
<ItemGroup>

View File

@ -48,5 +48,8 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
config.Filters.Add(new AuthorizeFilter(policy));
})
.Services;
public static IServiceCollection SetupMaxFailedAccessAttempts(this IServiceCollection services) =>
services.Configure<IdentityOptions>(o => o.Lockout.MaxFailedAccessAttempts = 0);
}
}

View File

@ -228,5 +228,60 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
await UserStories.ResetPasswordAsync(resetPasswordClient, email, userName, newPassword);
await UserStories.LoginExistingUserAsync(newClient, userName, newPassword);
}
[Fact]
public async Task CanResetPassword_WithGlobalAuthorizeFilter()
{
// Arrange
var emailSender = new ContosoEmailSender();
void ConfigureTestServices(IServiceCollection services) =>
services.SetupGlobalAuthorizeFilter().SetupTestEmailSender(emailSender);
var server = ServerFactory.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
var client = server.CreateClient();
var resetPasswordClient = server.CreateClient();
var newClient = server.CreateClient();
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"!Test.Password1$";
var newPassword = $"!New.Password1$";
await UserStories.RegisterNewUserAsync(client, userName, password);
var registrationEmail = Assert.Single(emailSender.SentEmails);
await UserStories.ConfirmEmailAsync(registrationEmail, client);
// Act & Assert
await UserStories.ForgotPasswordAsync(resetPasswordClient, userName);
Assert.Equal(2, emailSender.SentEmails.Count);
var email = emailSender.SentEmails[1];
await UserStories.ResetPasswordAsync(resetPasswordClient, email, userName, newPassword);
await UserStories.LoginExistingUserAsync(newClient, userName, newPassword);
}
[Fact]
public async Task UserLockedOut_AfterMaxFailedAccessAttempts_WithGlobalAuthorizeFilter()
{
// Arrange
var emailSender = new ContosoEmailSender();
void ConfigureTestServices(IServiceCollection services) =>
services.SetupGlobalAuthorizeFilter().SetupMaxFailedAccessAttempts().SetupTestEmailSender(emailSender);
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 wrongPassword = $"!Wrong.Password1$";
await UserStories.RegisterNewUserAsync(client, userName, password);
var registrationEmail = Assert.Single(emailSender.SentEmails);
await UserStories.ConfirmEmailAsync(registrationEmail, client);
// Act & Assert
await UserStories.LockoutExistingUserAsync(newClient, userName, wrongPassword);
}
}
}

View File

@ -64,6 +64,18 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests.Account
Context.WithAuthenticatedUser());
}
public async Task<DefaultUIPage> LockoutUserAsync(string userName, string password)
{
var loginAttempt = await SendLoginForm(userName, password);
var lockedOut = ResponseAssert.IsRedirect(loginAttempt);
Assert.Equal("/Identity/Account/Lockout", lockedOut.ToString());
var lockedOutResponse = await Client.GetAsync(lockedOut);
var lockout = await ResponseAssert.IsHtmlDocumentAsync(lockedOutResponse);
return new DefaultUIPage(Client, lockout, Context);
}
private async Task<HttpResponseMessage> SendLoginForm(string userName, string password)
{
return await Client.SendAsync(_loginForm, new Dictionary<string, string>()

View File

@ -36,6 +36,15 @@ namespace Microsoft.AspNetCore.Identity.FunctionalTests
return await login.LoginValidUserAsync(userName, password);
}
internal static async Task<DefaultUIPage> LockoutExistingUserAsync(HttpClient client, string userName, string password)
{
var index = await Index.CreateAsync(client);
var login = await index.ClickLoginLinkAsync();
return await login.LockoutUserAsync(userName, password);
}
internal static async Task<Index> RegisterNewUserWithSocialLoginAsync(HttpClient client, string userName, string email)
{
var index = await Index.CreateAsync(client, new DefaultUIContext().WithSocialLoginEnabled());