Skip to content

[release/10.0-preview4] Backport identity template fix. #61795

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: release/10.0-preview4
Choose a base branch
from
Open
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
@@ -1,5 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Identity;
using BlazorWeb_CSharp.Data;

namespace BlazorWeb_CSharp.Components.Account;

Expand All @@ -15,7 +17,6 @@ internal sealed class IdentityRedirectManager(NavigationManager navigationManage
MaxAge = TimeSpan.FromSeconds(5),
};

[DoesNotReturn]
public void RedirectTo(string? uri)
{
uri ??= "";
Expand All @@ -26,21 +27,16 @@ public void RedirectTo(string? uri)
uri = navigationManager.ToBaseRelativePath(uri);
}

// During static rendering, NavigateTo throws a NavigationException which is handled by the framework as a redirect.
// So as long as this is called from a statically rendered Identity component, the InvalidOperationException is never thrown.
navigationManager.NavigateTo(uri);
throw new InvalidOperationException($"{nameof(IdentityRedirectManager)} can only be used during static rendering.");
}

[DoesNotReturn]
public void RedirectTo(string uri, Dictionary<string, object?> queryParameters)
{
var uriWithoutQuery = navigationManager.ToAbsoluteUri(uri).GetLeftPart(UriPartial.Path);
var newUri = navigationManager.GetUriWithQueryParameters(uriWithoutQuery, queryParameters);
RedirectTo(newUri);
}

[DoesNotReturn]
public void RedirectToWithStatus(string uri, string message, HttpContext context)
{
context.Response.Cookies.Append(StatusCookieName, message, StatusCookieBuilder.Build(context));
Expand All @@ -49,10 +45,11 @@ public void RedirectToWithStatus(string uri, string message, HttpContext context

private string CurrentPath => navigationManager.ToAbsoluteUri(navigationManager.Uri).GetLeftPart(UriPartial.Path);

[DoesNotReturn]
public void RedirectToCurrentPage() => RedirectTo(CurrentPath);

[DoesNotReturn]
public void RedirectToCurrentPageWithStatus(string message, HttpContext context)
=> RedirectToWithStatus(CurrentPath, message, context);

public void RedirectToInvalidUser(UserManager<ApplicationUser> userManager, HttpContext context)
=> RedirectToWithStatus("Account/InvalidUser", $"Error: Unable to load user with ID '{userManager.GetUserId(context.User)}'.", context);
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
if (UserId is null || Code is null)
{
RedirectManager.RedirectTo("");
return;
}

var user = await UserManager.FindByIdAsync(UserId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
{
RedirectManager.RedirectToWithStatus(
"Account/Login", "Error: Invalid email change confirmation link.", HttpContext);
return;
}

var user = await UserManager.FindByIdAsync(UserId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
if (externalLoginInfo is null)
{
RedirectManager.RedirectToWithStatus("Account/Login", "Error loading external login information.", HttpContext);
return;
}

// Sign in the user with this external login provider if the user already has a login.
Expand All @@ -121,6 +122,7 @@
else if (result.IsLockedOut)
{
RedirectManager.RedirectTo("Account/Lockout");
return;
}

// If the user does not have an account, then ask the user to create an account.
Expand All @@ -135,6 +137,7 @@
if (externalLoginInfo is null)
{
RedirectManager.RedirectToWithStatus("Account/Login", "Error loading external login information during confirmation.", HttpContext);
return;
}

var emailStore = GetEmailStore();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
{
// Don't reveal that the user does not exist or is not confirmed
RedirectManager.RedirectTo("Account/ForgotPasswordConfirmation");
return;
}

// For more information on how to enable account confirmation and password reset please
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

@inject UserManager<ApplicationUser> UserManager
@inject SignInManager<ApplicationUser> SignInManager
@inject IdentityUserAccessor UserAccessor
@inject RedirectManager RedirectManager
@inject IdentityRedirectManager RedirectManager
@inject ILogger<ChangePassword> Logger

Expand Down Expand Up @@ -41,7 +41,7 @@

@code {
private string? message;
private ApplicationUser user = default!;
private ApplicationUser? user;
private bool hasPassword;

[CascadingParameter]
Expand All @@ -52,7 +52,13 @@

protected override async Task OnInitializedAsync()
{
user = await UserAccessor.GetRequiredUserAsync(HttpContext);
user = await UserManager.GetUserAsync(HttpContext.User);
if (user is null)
{
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
return;
}

hasPassword = await UserManager.HasPasswordAsync(user);
if (!hasPassword)
{
Expand All @@ -62,6 +68,11 @@

private async Task OnValidSubmitAsync()
{
if (user is null)
{
throw new InvalidOperationException("User is not loaded; cannot change password.");
}

var changePasswordResult = await UserManager.ChangePasswordAsync(user, Input.OldPassword, Input.NewPassword);
if (!changePasswordResult.Succeeded)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

@inject UserManager<ApplicationUser> UserManager
@inject SignInManager<ApplicationUser> SignInManager
@inject IdentityUserAccessor UserAccessor
@inject IdentityRedirectManager RedirectManager
@inject ILogger<DeletePersonalData> Logger

Expand Down Expand Up @@ -40,7 +39,7 @@

@code {
private string? message;
private ApplicationUser user = default!;
private ApplicationUser? user;
private bool requirePassword;

[CascadingParameter]
Expand All @@ -52,12 +51,23 @@
protected override async Task OnInitializedAsync()
{
Input ??= new();
user = await UserAccessor.GetRequiredUserAsync(HttpContext);
user = await UserManager.GetUserAsync(HttpContext.User);
if (user is null)
{
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
return;
}
requirePassword = await UserManager.HasPasswordAsync(user);
}

private async Task OnValidSubmitAsync()
{
if (user is null)
{
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
return;
}

if (requirePassword && !await UserManager.CheckPasswordAsync(user, Input.Password))
{
message = "Error: Incorrect password.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
@using BlazorWeb_CSharp.Data

@inject UserManager<ApplicationUser> UserManager
@inject IdentityUserAccessor UserAccessor
@inject IdentityRedirectManager RedirectManager
@inject ILogger<Disable2fa> Logger

Expand All @@ -31,14 +30,19 @@
</div>

@code {
private ApplicationUser user = default!;
private ApplicationUser? user;

[CascadingParameter]
private HttpContext HttpContext { get; set; } = default!;

protected override async Task OnInitializedAsync()
{
user = await UserAccessor.GetRequiredUserAsync(HttpContext);
user = await UserManager.GetUserAsync(HttpContext.User);
if (user is null)
{
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
return;
}

if (HttpMethods.IsGet(HttpContext.Request.Method) && !await UserManager.GetTwoFactorEnabledAsync(user))
{
Expand All @@ -48,6 +52,11 @@

private async Task OnSubmitAsync()
{
if (user is null)
{
throw new InvalidOperationException("User is not loaded; failed to disable 2FA.");
}

var disable2faResult = await UserManager.SetTwoFactorEnabledAsync(user, false);
if (!disable2faResult.Succeeded)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

@inject UserManager<ApplicationUser> UserManager
@inject IEmailSender<ApplicationUser> EmailSender
@inject IdentityUserAccessor UserAccessor
@inject NavigationManager NavigationManager
@inject IdentityRedirectManager RedirectManager

<PageTitle>Manage email</PageTitle>

Expand Down Expand Up @@ -55,7 +55,7 @@

@code {
private string? message;
private ApplicationUser user = default!;
private ApplicationUser? user;
private string? email;
private bool isEmailConfirmed;

Expand All @@ -67,7 +67,13 @@

protected override async Task OnInitializedAsync()
{
user = await UserAccessor.GetRequiredUserAsync(HttpContext);
user = await UserManager.GetUserAsync(HttpContext.User);
if (user is null)
{
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
return;
}

email = await UserManager.GetEmailAsync(user);
isEmailConfirmed = await UserManager.IsEmailConfirmedAsync(user);

Expand All @@ -82,6 +88,12 @@
return;
}

if (user is null)
{
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
return;
}

var userId = await UserManager.GetUserIdAsync(user);
var code = await UserManager.GenerateChangeEmailTokenAsync(user, Input.NewEmail);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
Expand All @@ -101,6 +113,12 @@
return;
}

if (user is null)
{
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
return;
}

var userId = await UserManager.GetUserIdAsync(user);
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user);
code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
@using BlazorWeb_CSharp.Data

@inject UserManager<ApplicationUser> UserManager
@inject IdentityUserAccessor UserAccessor
@inject UrlEncoder UrlEncoder
@inject IdentityRedirectManager RedirectManager
@inject ILogger<EnableAuthenticator> Logger
Expand Down Expand Up @@ -70,7 +69,7 @@ else
private const string AuthenticatorUriFormat = "otpauth://totp/{0}:{1}?secret={2}&issuer={0}&digits=6";

private string? message;
private ApplicationUser user = default!;
private ApplicationUser? user;
private string? sharedKey;
private string? authenticatorUri;
private IEnumerable<string>? recoveryCodes;
Expand All @@ -83,13 +82,22 @@ else

protected override async Task OnInitializedAsync()
{
user = await UserAccessor.GetRequiredUserAsync(HttpContext);

await LoadSharedKeyAndQrCodeUriAsync(user);
user = await UserManager.GetUserAsync(HttpContext.User);
if (user is null)
{
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
return;
}
}

private async Task OnValidSubmitAsync()
{
if (user is null)
{
RedirectManager.RedirectToInvalidUser(UserManager, HttpContext);
return;
}

// Strip spaces and hyphens
var verificationCode = Input.Code.Replace(" ", string.Empty).Replace("-", string.Empty);

Expand Down
Loading
Loading