Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ public override async Task<IActionResult> OnPostConfirmationAsync(string? return

await _emailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));

// If account confirmation is required, we need to show the link if we don't have a real email sender
if (_userManager.Options.SignIn.RequireConfirmedAccount)
// If confirmation is required, we need to show the link if we don't have a real email sender
if (!await _signInManager.CanSignInAsync(user))
{
return RedirectToPage("./RegisterConfirmation", new { Email = Input.Email });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public override async Task<IActionResult> OnPostAsync(string? returnUrl = null)

await _emailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));

if (_userManager.Options.SignIn.RequireConfirmedAccount)
if (!await _signInManager.CanSignInAsync(user))
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,8 @@ public override async Task<IActionResult> OnPostConfirmationAsync(string? return

await _emailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));

// If account confirmation is required, we need to show the link if we don't have a real email sender
if (_userManager.Options.SignIn.RequireConfirmedAccount)
// If confirmation is required, we need to show the link if we don't have a real email sender
if (!await _signInManager.CanSignInAsync(user))
{
return RedirectToPage("./RegisterConfirmation", new { Email = Input.Email });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public override async Task<IActionResult> OnPostAsync(string? returnUrl = null)

await _emailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));

if (_userManager.Options.SignIn.RequireConfirmedAccount)
if (!await _signInManager.CanSignInAsync(user))
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public async Task<IActionResult> OnPostAsync(string returnUrl = null)

await _emailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));

if (_userManager.Options.SignIn.RequireConfirmedAccount)
if (!await _signInManager.CanSignInAsync(user))
{
return RedirectToPage("RegisterConfirmation", new { email = Input.Email });
}
Expand Down
12 changes: 6 additions & 6 deletions src/Identity/test/Identity.FunctionalTests/LoginTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ void ConfigureTestServices(IServiceCollection services) => services
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"[PLACEHOLDER]-1a";

var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
await UserStories.RegisterNewUserAsyncWithConfirmation(client, userName, password, hasRealEmailSender: true);

// Act & Assert
// Use a new client to simulate a new browser session.
Expand All @@ -192,7 +192,7 @@ void ConfigureTestServices(IServiceCollection services) => services
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"[PLACEHOLDER]-1a";

var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
await UserStories.RegisterNewUserAsyncWithConfirmation(client, userName, password, hasRealEmailSender: true);

// Act & Assert
// Use a new client to simulate a new browser session.
Expand All @@ -216,7 +216,7 @@ void ConfigureTestServices(IServiceCollection services) => services
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"[PLACEHOLDER]-1a";

var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
await UserStories.RegisterNewUserAsyncWithConfirmation(client, userName, password, hasRealEmailSender: true);

// Act & Assert
// Use a new client to simulate a new browser session.
Expand All @@ -243,7 +243,7 @@ void ConfigureTestServices(IServiceCollection services) => services
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"[PLACEHOLDER]-1a";

var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
await UserStories.RegisterNewUserAsyncWithConfirmation(client, userName, password, hasRealEmailSender: true);

// Act & Assert
// Use a new client to simulate a new browser session.
Expand Down Expand Up @@ -271,7 +271,7 @@ void ConfigureTestServices(IServiceCollection services) => services
var userName = $"{Guid.NewGuid()}@example.com";
var password = $"[PLACEHOLDER]-1a";

var loggedIn = await UserStories.RegisterNewUserAsync(client, userName, password);
await UserStories.RegisterNewUserAsyncWithConfirmation(client, userName, password, hasRealEmailSender: true);

// Act & Assert
// Use a new client to simulate a new browser session.
Expand Down Expand Up @@ -406,6 +406,6 @@ void ConfigureTestServices(IServiceCollection services) =>
await UserStories.ConfirmEmailAsync(registrationEmail, client);

// Act & Assert
await UserStories.LoginFailsWithWrongPasswordAsync(newClient, userName, wrongPassword);
await UserStories.LoginFailsAsync(newClient, userName, wrongPassword);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void ConfigureTestServices(IServiceCollection services) =>

// Verify can login with new email, fails with old
await UserStories.LoginExistingUserAsync(newClient, newEmail, password);
await UserStories.LoginFailsWithWrongPasswordAsync(failedClient, userName, password);
await UserStories.LoginFailsAsync(failedClient, userName, password);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public async Task<Index> LoginValidUserAsync(string userName, string password)
Context.WithAuthenticatedUser().WithPasswordLogin());
}

public async Task LoginWrongPasswordAsync(string userName, string password)
public async Task LoginFailsAsync(string userName, string password)
{
var failedLogin = await SendLoginForm(userName, password);

Expand Down
42 changes: 40 additions & 2 deletions src/Identity/test/Identity.FunctionalTests/RegistrationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,26 @@ public async Task CanRegisterAUserWithRequiredConfirmation()
var register = await UserStories.RegisterNewUserAsyncWithConfirmation(client, userName, password);

// Since we aren't confirmed yet, login should fail until we confirm
await UserStories.LoginFailsWithWrongPasswordAsync(client, userName, password);
await UserStories.LoginFailsAsync(client, userName, password);
await register.ClickConfirmLinkAsync();
await UserStories.LoginExistingUserAsync(client, userName, password);
}

[Fact]
public async Task CanRegisterAUserWithRequiredEmailConfirmation()
{
void ConfigureTestServices(IServiceCollection services) { services.SetupEmailRequired(); };

var server = ServerFactory
.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices));
var client = server.CreateClient();

var userName = $"{Guid.NewGuid()}@example.com";
var password = $"[PLACEHOLDER]-1a";

var register = await UserStories.RegisterNewUserAsyncWithConfirmation(client, userName, password);

await UserStories.LoginFailsAsync(client, userName, password);
await register.ClickConfirmLinkAsync();
await UserStories.LoginExistingUserAsync(client, userName, password);
}
Expand Down Expand Up @@ -88,7 +107,7 @@ void ConfigureTestServices(IServiceCollection services)
var register = await UserStories.RegisterNewUserAsyncWithConfirmation(client, userName, password, hasRealEmailSender: true);

// Since we aren't confirmed yet, login should fail until we confirm
await UserStories.LoginFailsWithWrongPasswordAsync(client, userName, password);
await UserStories.LoginFailsAsync(client, userName, password);
}

[Fact]
Expand Down Expand Up @@ -151,6 +170,25 @@ void ConfigureTestServices(IServiceCollection services)
await UserStories.RegisterNewUserWithSocialLoginWithConfirmationAsync(client, userName, email);
}

[Fact]
public async Task CanRegisterWithASocialLoginProviderFromLoginWithRequiredEmailConfirmation()
{
void ConfigureTestServices(IServiceCollection services) =>
services
.SetupEmailRequired()
.SetupTestThirdPartyLogin();

var client = ServerFactory
.WithWebHostBuilder(whb => whb.ConfigureServices(ConfigureTestServices))
.CreateClient();

var guid = Guid.NewGuid();
var userName = $"{guid}";
var email = $"{guid}@example.com";

await UserStories.RegisterNewUserWithSocialLoginWithConfirmationAsync(client, userName, email);
}

[Fact]
public async Task CanRegisterWithASocialLoginProviderFromLoginWithConfirmationAndRealEmailSender()
{
Expand Down
4 changes: 2 additions & 2 deletions src/Identity/test/Identity.FunctionalTests/UserStories.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ internal static async Task<Index> LoginExistingUserAsync(HttpClient client, stri
return await login.LoginValidUserAsync(userName, password);
}

internal static async Task LoginFailsWithWrongPasswordAsync(HttpClient client, string userName, string password)
internal static async Task LoginFailsAsync(HttpClient client, string userName, string password)
{
var index = await Index.CreateAsync(client);

var login = await index.ClickLoginLinkAsync();

await login.LoginWrongPasswordAsync(userName, password);
await login.LoginFailsAsync(userName, password);
}

internal static async Task<DefaultUIPage> LockoutExistingUserAsync(HttpClient client, string userName, string password)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,8 +177,8 @@
new Dictionary<string, object?> { ["userId"] = userId, ["code"] = code });
await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));

// If account confirmation is required, we need to show the link if we don't have a real email sender
if (UserManager.Options.SignIn.RequireConfirmedAccount)
// If confirmation is required, we need to show the link if we don't have a real email sender
if (!await SignInManager.CanSignInAsync(user))
{
RedirectManager.RedirectTo("Account/RegisterConfirmation", new() { ["email"] = Input.Email });
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@

await EmailSender.SendConfirmationLinkAsync(user, Input.Email, HtmlEncoder.Default.Encode(callbackUrl));

if (UserManager.Options.SignIn.RequireConfirmedAccount)
if (!await SignInManager.CanSignInAsync(user))
{
RedirectManager.RedirectTo(
"Account/RegisterConfirmation",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,34 @@ public async Task BlazorWebTemplate_CanUsePasskeys(BrowserKind browserKind)
await TestProjectCoreAsync(project, browserKind, pagesToExclude, authenticationFeatures);
}

[Theory]
[InlineData(BrowserKind.Chromium)]
public async Task BlazorWebTemplate_CanRequireConfirmedEmail(BrowserKind browserKind)
{
var project = await CreateBuildPublishAsync(
args: ["-int", "None", "-au", "Individual"],
onlyCreate: true);

var programPath = Path.Combine(project.TemplateOutputDir, "Program.cs");
var program = await File.ReadAllTextAsync(programPath);
const string requireConfirmedAccount = "options.SignIn.RequireConfirmedAccount = true;";
Assert.Contains(requireConfirmedAccount, program);
program = program.Replace(
requireConfirmedAccount,
"options.SignIn.RequireConfirmedEmail = true;",
StringComparison.Ordinal);
await File.WriteAllTextAsync(programPath, program);

await project.RunDotNetPublishAsync(noRestore: false);
await project.RunDotNetBuildAsync();

await TestProjectCoreAsync(
project,
browserKind,
BlazorTemplatePages.Counter,
AuthenticationFeatures.RegisterAndLogIn);
}

private async Task TestProjectCoreAsync(Project project, BrowserKind browserKind, BlazorTemplatePages pagesToExclude, AuthenticationFeatures authenticationFeatures)
{
var appName = project.ProjectName;
Expand Down
Loading